Here are my notes from a free CodeSchool tutorial sponsored by Google:
Things I wish I were told about Angular.js.
Binding
<!DOCTYPE html> <html> <head> <title>AngularJS Tutorials</title> </head> <body> <div ng-app=""> <input type="text" ng-model="data.message"> <h1>{{data.message}}</h1> </div> <script type="text/javascript" src="angular.js"></script> </body> </html>
Controllers
<html> <body> <div ng-app=""> <div ng-controller="FirstCtrl"> <h1>{{data.message + " world"}}</h1> <div class="{{data.message}}"> Msg... </div> </div> </div> <script type="text/javascript" src="angular.js"></script> <script type="text/javascript" src="main.js"></script> </body> </html> //main.js function FirstCtrl($scope){ $scope.data = {message: "Hello"}; }
Dot
https://www.youtube.com/watch?v=DTx23w4z6Kc
The initial setup:
<div ng-app=""> <input type="text" ng-model="data.message"> <h1>{{ data.message }}</h1> <div ng-controller="FirstCtrl"> <input type="text" ng-model="data.message"> <h1>{{ data.message }}</h1> </div> <div ng-controller="SecondCtrl"> <input type="text" ng-model="data.message"> <h1>{{ data.message }}</h1> </div> </div>
function FirstCtrl($scope) { } function SecondCtrl($scope) { }
In this setup, all three instances of data.message are bound to each other through the first data.message, which is in the scope of the entire application.
If we were to replace the instances of data.message with just message,
<div ng-app=""> <input type="text" ng-model="message"> <h1>{{ message }}</h1> <div ng-controller="FirstCtrl"> <input type="text" ng-model="message"> <h1>{{ message }}</h1> </div> <div ng-controller="SecondCtrl"> <input type="text" ng-model="message"> <h1>{{ message }}</h1> </div> </div>
It breaks the scope inheritance that was binding all the data.message instances. Now, each new ng-model of message is creating a new instance of message, and so each model will be an unbound instance. So, important to note here is the data.message which will be available to all of the controllers!
Sharing data between controllers
https://www.youtube.com/watch?v=HXpHV5gWgyk
The initial setup:
<div ng-app=""> <input type="text" ng-model="data.message"> <h1>{{ data.message }}</h1> <div ng-controller="FirstCtrl"> <input type="text" ng-model="data.message"> <h1>{{ data.message }}</h1> </div> <div ng-controller="SecondCtrl"> <input type="text" ng-model="data.message"> <h1>{{ data.message }}</h1> </div> </div>
function FirstCtrl($scope) { } function SecondCtrl($scope) { }
With this setup, data.message is defined outside of either controller, scoped to the entire ng-app. The bindings within each of the controller divs both point to that ‘parent’ model. Because of this, all 3 instances of the data.message input are bound to each other because of the first instance, which is globally scoped in the application.
If one were to remove the first model that does not reside in a controller, there is no parent model for either controller to bind to, so each instance of data.message will be scoped within its respective controller. Thus, neither data.message will be bound to the other.
We’d like to share the data model between the two controllers without creating a parent scope. This requires a service within a formally defined Angular application.
<div ng-app="myApp"> <div ng-controller="FirstCtrl">
var myApp = angular.module('myApp', []); myApp.factory('Data', function () { return { message: "I'm data from a service" }; }); function FirstCtrl($scope) {
This Data service can be injected into each of the controllers as a parameter. By doing this, we are now attaching the data.model to an app service, which repairs the binding between the two controller models.
Stackoverflow thread on this.
<!DOCTYPE html> <html> <head> <title></title> </head> <body ng-app="myApp"> <div ng-controller="FirstCtrl"> <input type="text" ng-model="data.message"> <h1>{{ data.message }}</h1> </div> <div ng-controller="SecondCtrl"> <input type="text" ng-model="data.message"> <h1>{{ data.message }}</h1> </div> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script> <script type="text/javascript" charset="utf-8"> angular.module('myApp', []) .factory('Data', function () { return { message: "I'm data from a service" }; }) .controller('FirstCtrl', function ($scope, Data){ $scope.data = Data; }) .controller('SecondCtrl', function ($scope, Data){ $scope.data = Data; }); </script> </body> </html>
Method on a scope
function SecondCtrl($scope, Data) { $scope.data = Data; $scope.reversedMessage = function() { return $scope.data.message.split("").reverse().join(""); }; }
Bootstraping https://docs.angularjs.org/guide/bootstrap
Changing the data in the service and then showing it again, the ultimate example which eluded me for some time (Plunkr):
<!DOCTYPE html> <html> <head> <title></title> </head> <body ng-app="myApp"> <div ng-controller="FirstCtrl"> <input type="text" ng-model="data.msg"> <h1>{{ data.msg }}</h1> <button type="" ng-click="sayItBack()"></button> </div> <div ng-controller="SecondCtrl"> <input type="text" ng-model="data.msg"> <h1>{{ data.msg }}</h1> </div> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script> <script type="text/javascript" charset="utf-8"> angular.module('myApp', []) .service('Data', function () { this.data = {}; this.data.msg = "Howdy!"; this.getMsg = function() { return this.data; }; this.setMsg = function(city){ this.data.msg = city; }; }) .controller('FirstCtrl', function ($scope, Data){ $scope.data = Data.getMsg(); $scope.sayItBack = function(){ Data.setMsg("Hello to you too!"); } }) .controller('SecondCtrl', function ($scope, Data){ $scope.data = Data.getMsg(); }); </script> </body> </html>