On Github rhettl / angular-intro
These are some of the features Angular is most notable for currently, but they are not why it was originally written. It was written just to be fast to develop and easily testable.
Now we will review MVC theory and how AngularJS sees MVC
The first part to look at is the view in my opinion. AngularJS really looks at the view differently the most other frameworks out there, esp. jQuery.
jQuery: HTML/View is an anchor point so jQuery can insert DOM as it sees fit
We all know jQuery and how it interacts with the DOM.
In AngularJS
In this example, I am ONLY using the view. Nothing more nothing less.
I have assigned part of the DOM to listen to a variable named `$scope.who` and an input to manipulate `$scope.who`
<div ng-app=""> Hello {{ who }}!<br><br> <input ng-model="who" type="text"> </div>
This is the whole code. Notice:
$scope
nulldefault
The view has many more parts to it. Templates and Models are just the beginning.
AngularJS has built in functions to help simplify changing data types. In this example we:
<div ng-app=""> List the people you want to say hello to:<br><br> <input ng-list="" ng-model="who" type="text"> <br> <ul> <li ng-repeat="person in who"> Hello {{person}}! </li> </ul> </div>
You said hello to people
You said hello to nobody?!?!
Notice:<p>You said hello to {{ who.length }} people</p> <p> You said hello to <ng-pluralize count="who.length || 0" when="{'0': 'nobody?!?!', 'one': '1 person.', 'other': '{} people!'}"></ng-pluralize> </p> <input ng-model="who" type="text" ng-list="">
$scope.who
Notice here that anything you type in will limit the output of the repeat. It is using filters to modify the array before the repeat get it.
<div ng-init="people = [ {name:'Rhett'}, {name:'Ali'}, {name:'Ray'}, {name:'Maria'}, {name:'Jannah'}, {name:'Naz'}, {name:'David'} ]"> Only These people:<br><br> <input ng-model="onlyMe" type="text"><br> <ul> <li ng-repeat="person in people | filter:onlyMe"> Hello {{person.name}}! </li> </ul> </div>
Notice
Notice:
We are nearly done with the view and its powers. But the view can do so much more! By now I hope you are getting that the view has a lot of power in AngularJS
Notice
<h3>Counter: {{ counter }}</h3> <span ng-click="counter = 0">Reset</span><br> <a ng-click="counter = counter + 1">+1</a><br> <button ng-click="counter = counter + 5">+5</button>
This is the phone code.
A counter is set as `$scope.counter` two click handlers are set in place to increment the counter one click event sets it to zerong-click="myFunc(variable)"
ng-click="variable = variable + 1"
ng-click="variable = variable + 1; myFunc(variable)"
ngClick is a directive with many traits. It can:
It also has built in that any anchor or button with ng-click will automatically prevent default.
Here is a list of other directives that are extremely useful to the view.
There are many more. To read more about these directives and others, click on any of the directives
The controller is just as powerful as the View and is as testable, but only if it is used properly.
<div ng-app="" ng-controller="myAppCtrl"> {{ variable }} <span ng-click="myFunc('This will appear in an alert')">Click Me</span> </div>
var myAppCtrl = function($scope){ $scope.variable = 'Anything I want'; $scope.myFunc = function(text){ alert(text); }; };
the top is in the view and the bottom is in the controller
function myController($scope, $timeout, myFactory){ // Variable Instantiation var a, b, c; var obj = {}; var fac = new myFactory(); // Function Instantiation var myFunc = function(text){ alert(text); } var initFunc = function(){ //do initialization stuff here } // Scope Instantiation $scope.myVar = 1; $scope.obj = {name: "test"}; $scope.myFunc = myFunc; $scope.round = Math.round; $scope.addAB = function(){ $scope.myVar = a + b; } // Initiate processes or data with functions initFunc(); fac.init(); }
This is how I like to structure my Controllers.
The order isn't all important, but I really prefer instantiation and declaration at top and function initialization at that bottom.
Notice
function myController($scope, $timeout, myFactory){ var el = angular.element('#someID'); el.find('div').hide(); }
The controller doesn't work like jQuery. It isn't for writing random code to change the DOM. Instead use it to allow the DOM/View to make it's own changes.
<div ng-app="myApp" ng-controller="myAppCtrl"> {{ variable | whatsMyName }} <span ng-click="myFunc('This will appear in an alert')">Click Me</span> </div>
angular.module('myApp', []) .filter('whatsMyName', [function(){ return function(input){ return input + " is my name!"; } }]) .controller('myAppCtrl', ['$scope', function($scope){ $scope.variable = 'Anything I want'; $scope.myFunc = function(text){ alert(text); }; }]);
In this example notice the scafholding for the application.
Directives are for altering HTML or creating new behaviors in HTML
examples of when one might make a directive
<input spinner="" ng-model="count" min="-5" max="5">
angular.module('myApp', []).directive('spinner', [function(){ return { restrict: 'A', scope: { currentNum: '=ngModel', min: '@?', max: '@?', inc: '=?' }, replace: true, template: '<div class="spinner">' + '<input ng-model="currentNum">' + '<span class="plusOne" ng-click="add(inc)">' + '<i class="chevron-up"></i>' + '</span>' + '<span class="minusOne" ng-click="subtract(inc)">' + '<i class="chevron-down"></i>' + '</span>' + '</div>', link: function(scope, iElement){ if (typeof scope.min === 'undefined'){ scope.min = -1000000000000000; } if (typeof scope.max === 'undefined'){ scope.max = 1000000000000000; } if (typeof scope.inc === 'undefined'){ scope.inc = 1; } scope.add = function(num){ var newNum; num = (typeof num === 'undefined' ? 1 : num); if (num + scope.currentNum > scope.max){ newNum = scope.max } else { newNum = num + scope.currentNum; } scope.currentNum = newNum; }; scope.subtract = function(num){ var newNum; num = (typeof num === 'undefined' ? 1 : num); if (scope.currentNum - num < scope.min){ newNum = scope.min } else { newNum = scope.currentNum - num; } scope.currentNum = newNum; }; } } }]);
First notice:
We can ise the spinner directive anywhere within the ngApp as name times as we like.
Providers are the model. There are several types of providers.
Provider Types
There are different types of providers that are ment to do different things
angular.module('myApp', []) .factory('myLogs', ['$http', function($http){ var myFact = function(){ //init script this.reqUrl = '/includes/assets/scripts/rest/json.php'; this.logs = []; this.query = { func: 'get_logs', args: [] } } myFact.prototype.getLogs = function(time){ this.query.args = [time]; $http.get(this.reqUrl, this.query) .success(function(data){ this.logs = data; }).error(function(){ this.logs = []; console.log('there is a problem!!'); }); }; }]) .controller('myCtrl', ['$scope', 'myLogs', function($scope, myLogs){ $scope.fac = new myLogs(); }]);
<div ng-app="myApp" ng-controller="myCtrl"> <ul> <li ng-repeat="log in fac.logs" ng-bind="log.entry"></li> </ul> <button ng-click="fac.getLogs()">Update</button> </div>Notice
If it only deals in how things look it belongs in the view. Ex: Simple Pagination
Simple pagination is when it has nothing to do with the model. All results are returned and the view is just combing through them
Simple pagination doesn't have anything to do with how the data is returned or what data is returned so there is little reason to place it in the controller or the model. If it can cleanly go into the View, put it there.
Most of the time you will deal with these two.
What belongs in the model is anything pertaining to the fetching, holding, or checking of a specific type of dataThere are also more general models
What SHOULD go in the model are things like getters for THAT type of information and it is fine for the returned information to stay in the model
The controller Should hold the burden of going the model's dirty work
Think of this as:
The controller is a place to:
Don't use it as a place to initialize jQuery or manipulate the DOM
Ideally, the best directives appear to work without you touching them from the controller or the view.
All elements should be as modular as possible.