Angular
Angular
Purpose of additional technology and approach is to deal with complexity not making the
code more complex
Easier way to deal with code
Good code organization
Update functionality without a re-write of large portions of your code
Code reuse( don’t re-write the same/similar code twice)
Code should be easy to test(even small chunks of functionality)
Why does code get complex
Bad or inconsistent coding style
Hard to read the variables and function name
No comments or API documentation
Lack of high cohesion and low coupling
o High cohesion- smaller pieces of functionality are strongly related to each
other within some code boundary and are less complex(tight coupling)
o Loose coupling- least possible dependency of one component to another
component/ change in one component doesn’t affect another component
e.g. one function does 3 fairly unrelated things(low cohesion webpage)
How to achieve high cohesion and loose coupling (mvvm)
Model-View-ViewModel
Mode l- represent and holds raw data
Some of this data in some form may be displayed In the view
Contain logic to retrieve the data from some source
Contain no logic associated with displaying the model, doesn’t know how to get
displayed or who’s going to display it
View - user interface
In the web app, it’s just the html and css
Only displays the data that it is given
Never changes the data just receive
Declaratively broadcast events, but never handles them
ViewModel - representation of the state of the view(backside)
Holds the data displayed in the view
Responds to view events e.g. presentation logic
Calls other functionality for business logic processing
Never directly asks the view to display anything, never manipulate the DOM
o Allows loose coupling because it never calls id’s in the html
Declarative binder- binds the model of the viewModel to the view
Declarative means you don’t have to write any code to bind them these is where
the framework does this magic
Declarative binder is the key enabler of the MVVM pattern without it you will
have to write all the pattern by hand
View(UI/Presentation) html css
View Model(presentation logic) JavaScript
Model(data/business logic) JavaScript
Js app
(function (){
'use strict';
angular.module('myFirstApp', [])
})();
angular.module('myFirstApp', []) – takes the name of the application
and the list of indipandences in a form of an array<html ng-
app="myFirstApp"
<html ng-app="myFirstApp"
ng-app – (angular application), we place it at an outer tag where we want it to be
responsible for
o from any it we named "myFirstApp" (<html>) to the end of the
tag(</html>) our angular application is responsible for it
for a smaller position of code e.g div to be responsible for we use-
(function (){
'use strict';
angular.module('myFirstApp', [])
})
})();
.controller – is the way we define the viewModule of the view
o Takes 2 things the name of the view module or controller and the function
'use strict';- enable certain things to protect from making
mistakes
Sharing data with the view through scopes
An object to share data between the viewModule and the view $scope
.controller('myFirstController', function ($scope){
You can call a string
.controller('myFirstController', function ($scope){
$scope.name = "Tshepo"
angular.module("nameCalculator", [])
.controller("nameCalculatorController", function($scope){
$scope.name = ""; // equal to the textbox/ displayed in the
textox
$scope.totalValue = 0;
$scope.displayNumeric = function(){
let totalNumericValue = calculateNumericString($scope.name);
$scope.totalValue = totalNumericValue
};
function calculateNumericString(string){
let totalStringvalue = 0;
for( let i = 0; i < string.length; i++){ //
totalStringvalue += string.charCodeAt(i) //
}
return totalStringvalue;
}
});
})()
DEPENDENCY INJECTION(DI)
design pattern that implements inversion of control(loC) for resolving dependencies
during an payment process clients at called with the independency by some system
the system is angularJS
client is not responsible for instantiating the dependency
DI in javascript
function DIController ($scope, $filter){
$filter let use create filtering functions that is used for formatting the data that get
displayed to a viewer
$filter used the same way as $scope e.g
angular.module('DIApp', [])
.controller('DIController', DIController);
Minification – is the process of removing of all unnecessary characters from source code
without changing its functionality
Its is also uglfy it uglyfies the code
Removes wide space characters, comments , new line characters etc
Purpose of it is not reduce the amount of data transferred from server
During manification ($scope, $filter) are the names that angular must
look
for in order to inject to the DIcontroller
DI in angular need to be manification proof
To fix you can
1. (a) In the .controller function the 2nd argument is a function in can be an
array [or in line array with function as last element
.controller('DIController',
['$scope','$filter',DIController]);
(b)
.controller('DIController', ['$scope','$filter',
function($scope, $filter){
$scope.name = 'Tshepo'
$scope.upper = function(){
let upCase = $filter('uppercase')
$scope.name = upCase($scope.name)
}
Manificated version of it
!function(){"use strict";function e(e,n)
{e.name="Tshepo",e.upper=function(){let o=n("uppercase");
e.name=o(e.name)}}angular.module("DIApp",
[]).controller("DIController",e),e.$inject=["$scope","$filter"]}()
function MsgController($scope){
$scope.name = 'tshepo';
$scope.sayMessage = function(){
return 'Tshepo likes to eat healthy snacks'
}
}
Example 2
<button ng-click="feedTshepo()">Feed Tshepo</button>
<br>
<img ng-src="img/young-man-{{stateOfBeing}}.webp">
</div>
MsgController.$inject =['$scope'];
function MsgController($scope){
$scope.name = 'tshepo';
$scope.stateOfBeing = 'hungry'
$scope.sayMessage = function(){
return 'Tsepo likes to eat healthy snacks'
}
$scope.feedTshepo = function(){
$scope.stateOfBeing = 'fed'
}
use ng-src=”” because we only want the image to be fetched when angular got uphold
to it.
ng-click=””
MODULE 2
Filters
change the output of an expression
you can do that either on javascript or html
filters in javascript
const output =
$filters(‘uppercase’)(value)
Filters in html
{{ “Hello” | uppercase }}
“hello” can either be $scope.value
$scope.sayMessage = function(){
let name = 'Tshepo likes to eat healthy snacks'
let msg = $filter('uppercase')(name)
return msg // name will be in uppercase
under angulajs website there are a lot of different built in-filters and other built-in
components e.g currency, number, date , JSON
currency
in html
{{ currency_expression | currency : symbol : fractionSize }}
In javascript
$filter(‘currency’)(amount, symbol, fractonSize )
fractionSize is 0.00 or .000
symbol – dollar or yen or euro or rand sign
custom filters
creating our own custom filters
there are steps to create it –
1. define filter factory function
function customFilterfactory(){
return function(){
// change input
return changed input
customFilterFactory this function creates and return our filter function
2 way binding
Your name:
<input type= ‘text’ ng-model=’name’>
1 way binding
Ng-repeat
<ul>
<li ng-repeat="item in shoppingList1"> {{item}} </li>
</ul>
<ul></ul> - annotated list
Ng-repeat – is similar to a for each loop
Item in shoppingList1 – means we are going to loop over shoppingList1 array
and each through interaction the item of the collection will be equal to the
item variable
o If you don’t write item in an error will occur
{{item}} – interpolating the item as the value of the body of the <li> tag
<ul>
<li ng-repeat="item in shoppingList2"> {{$index + 1}}. Buy
{{item.quantity}} of {{item.name}}(s) </li>
</ul>
const shoppingList2 = [
{
name: "Milk",
quantity: "2"
},
{
name: "Donuts",
quantity: "200"
},
{
name: "Qookies",
quantity: "300"
},
{
name: "Peanut Butter",
quantity: "5"
}
]
angular.module('shoppingListApp', [])
.controller('shoppingListController', shoppingListController);
shoppingListController.$inject = ["$scope"]
function shoppingListController($scope){
$scope.shoppingList1 = shoppingList1;
$scope.shoppingList2 = shoppingList2;
$scope.addToList = function(){
const newItem = {
name: $scope.newItemName ,
quantity: $scope.newItemQuantity
};
$scope.shoppingList2.push(newItem)
}
}
})()
Filter ng-repeat
Array have a specific function called filter
Creates new array where each item satisfies some condition of comparison
function passed into the filter function
Angular has a specific filter called filter
Provided a string as 1st argument, it will filter the array applied to it. Matching
all string item against the provided one
We apply it using – ng-repeat=”item in collect | filter : searchString”
const numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log("Number array: ", numberArray)
or
const numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log("Number array: ", numberArray)
function above5filter(value){
return value > 5
}
let filterNumberArray = numberArray.filter(above5filter)
console.log("Filtered number array: ", filterNumberArray)
The value(parameter) will be equal to each item in numberArray
Searching for an item in the shopping list(angular)
const shoppingList1 = [
"Milk", "Donuts", "Cookies", "Chocolate", "Peanut Butter",
"Pepto Bismol",
"Pepto Bismol (Chocolate Flavour)", "Peptom Bismol {cookie
Flavour}"
];
The filter uses the search string to figure out weather the item in the
shoppingList array matches the search string. But since we are updating the
search string using the 2 way binding(ng-model = “search”) the ng-repeat get
filtered on the fly(automatic)
Js Prototypal inheritance
Unlike object oriented inheritance which is based on classes and more complex and has
so much rules. Prototypal inheritance is based on object instance and simple and straight
forward
Child
Type= “child” type of the parent will be
masked by the new type
Parent to child
const parent = {
value : "parentObject",
obj: {
objValue : "parentObjValue"
},
Walk: () => {
console.log("walking!")
}
}
childController1.$inject = ['$scope']
function childController1($scope){
console.log("$scope.parentValue: ", $scope.parentValue)
console.log("CHILD $scope: ", $scope)
_proto_ - on the prototype in scope of the child, the parentValue of the child = 1. Directly
on the child scope parentValue is not available
$scope.parentValue = 5;
console.log("$*** CHANGED: $scope.parentValue = 5 ***")
console.log("$scope.parenrValue: ", $scope.parentValue )
console.log($scope)
}
parentValue = 5 because the current parentValue belongs to the child controller
on the child scope the is directly a parentValue = 5. On the _proto_ the parentValue we
used before is still =1, because the child controller scope is masking the parentValue
property
$scope.pc – traverse the prototype chain to the parent object which means if you change the
parentValue ( $scope.pc.parentValue = 5; ) it will not only change the child value it will also change
in its roots the parentController1
Controller as syntax
parentController2.$inject = ['$scope'] //not need because we are
attaching the
property directly to the
controller
function parentController2(){
let parent = this;
parent.value = 1;
}
ChildController2.$inject = ['$scope']
function ChildController2($scope){
const child = this;
child.value = 5;
console.log("ChildController $scope: ", $scope)
}
Since .value is assigned to the controllers of both child and parent properties the
child.value= 5 will not mask parent.value = 1
If you reference a proper controller .value can work independently
<div ng-controller="parentController2 as parent">
Parent value: {{parent.value}}
Custom servives
Controller responsibility –
Use controllers to
Set up the Initial state of $scope
Add behavior to the $scope
Do not use controllers to
Handle business logic directly
Share code or state across controllers
Share data across components
Register service function constructor
Angular.module(‘app’, [])
.controller(‘ctrl’, ctrl)
.service(‘customService’, customService)
‘customService’ – the string name you give to the service is used
to inject into other services or controllers not the name of the
function that is used a function constructor to create the service
.service(‘name’, function)-
The function you supply to the .service e.g customService will be
treated as a function constructor
o Means the angular js internally will new up your function
using a new keyword which has a ramification for what
this keyword means inside your service function
let itemAdder = this;
Singleton design pattern-
Restricts object to always having a single instance
o Each dependent component gets a reference to the
same instance
o Multiple controllers injected with a service will all have
access to the same service instance
Lazily instantiated-
Only created if an application component declares it as a
dependency
o If no component in your application are dependent on this
service it will never get created
<div ng-controller="shoppingListAddController as itemAdder">
<input type="text" ng-model="itemAdder.itemName"
placeholder="item name">
<input type="text" ng-model="itemAdder.itemQuantity"
placeholder="quantity">
<button ng-click="itemAdder.addItem();">Add Item To Shopping
List</button>
</div>
Angular.module(‘app’, [])
.controller(‘ctrl’, ctrl)
.factory(‘customService’, customService)
customService the function that is expected to produce a service
.service() – the customService the function is expected to be the service
‘customService’ – whats injected
Factory function
function customService(){
const factory = () => {
return new someService();
};
return factory;
}
We want to create someService, to call new because we decide what gets created or not
then we return that
Ng-if
<div class="error" ng-if="list2.errorMessage">error:
{{ list2.errorMessage }}</div>
</div>
Ng-if takes a condition as its value, if there condition is true the
entire div is shown if the condition is false, angular takes the
entire div out of the dom tree
E.g on the shopping cart list, the div is not existing(false)
because maximum items(10) haven’t been reached
Ng-show
<div class="error" ng-show="list2.errorMessage">error:
{{ list2.errorMessage }}</div>
</div>
Has a class ng-hide in console.log that display: none when you
reached maximum the ng-hide disappears and get displayed on
screen as error: max item(5) reached
Ng-hide
<div class="error" ng-hide="!list2.errorMessage">error:
{{ list2.errorMessage }}</div>
</div>
Opposite of ng-show(vise versa) for ng not to display reaching
max item before adding items you must include ! on ng-hide=””
ANGULAR JS AND NEW ES6 API
Before promise the were callbacks
Callbacks were hard to read
They couldn’t be executed in parallel and did not display an error
asyncFunction1(function (){
asyncFunction2(function (){
asyncFunction3(function (){
})
)}
)}
Promise – object which can be passed around or returned that holds references to the
outcome of asynchronous behavior
Give us a lot of flexibility when dealing asynchronous behavior
In angular promise API are created through the $q service
Promises either get resolved of rejected
The ‘ then‘ method takes 2 arguments(both are functions) –
1. Function that handle success or resolve outcome
2. Function to handle error or reject outcome
Then itself returns a promise sot its chainable
Angularjs $q service promise
2nd- step
function asyncFunction (){
let deferred = $q.defer()
if(…) { deferred.resolve(result) }
else { deferred.reject(error) }
return deferred.promise;
$q.defer() Creates objects that a async environment with all the hooks into it, including
the promise object
.resolve marks a successful completion of our execution, then wraps the data for the
promise
.reject If something goes wrong marks a unsuccessful completion , then wraps the data
for the promise
return deferred.promise; Return the promise to the caller (a hook back to the entire
process)
1st- step
let promise = asyncFunction()
promise.then(function (result){
}
Function(error){
}).then(…)
next step is for the caller to call the asynchronous function and call a reference to the
promise object let promise. then when the application is appropriate, you call the then
function on the promise to extract the result or the error promise.then which are
functions themselves
if there are more than one promises
3rd-step
$q.all([promise1, promise2])
.then(function(result){
})
.catch(function(error){
})
$q.all – allow us to execute multiple promises in parallel, handling success/fail in
one place
e.g
2nd -step
shoppingListService.$inject = ['$q', 'weightLossFilterService']
function shoppingListService($q, weightLossFilterService){
let service = this;
const result = {
message: ""
}
$timeout(function(){
//check for cookies
if(name.toLowerCase().indexOf('cookies') === -1){
deferred.resolve(result)
}
else{
result.message = "Stay away from cookies, Tshepo";
deferred.reject(result)
}
}, 3000);
return deferred.promise
}
$timeout(function(){
if(quantity < 6){
deferred.resolve(result)
}
else{
result.message = "That's too much, Tshepo";
deferred.reject(result);
}
}, 1000)
return deferred.promise returned back to have the hook for the
hook
}
$timeout – is similar to setTimeout in javascript but angularised
Name is lowercased name.toLowerCase(). and the word cookie will be checked if it is
not there indexOf('cookies') === -1
If not, it will be successful(.resolve) with the result being an empty string
deferred.resolve(result)
Else if the word cookie is there it will be unsuccessful(.reject)
deferred.reject(result) and a message will be displayed in the empty
string result.message = "Stay away from cookies, Tshepo
Since the is more than one promise the 2nd step can be void and do the 3rd
shoppingListService.$inject = ['$q', 'weightLossFilterService']
function shoppingListService($q, weightLossFilterService){
let service = this;
$q.all([namePromise, quantityPromise]).
then( function (response) {
const item = {
name: name,
quantity: quantity
}
items.push(item)
})
.catch( function(errorResponse){
console.log(errorResponse.message)
})
}
service.getItem = () => {
return items
}
}
.directive('listItemDescription', listItemDescription)
function listItemDescription(){
const ddo = {
template: '{{ item.quantity }} of {{ item.name }}'
};
return ddo;
}
register name of directive you must use camelCase
.directive('listItemDescription'
when calling it, you use kabab-case <list-item-description></
<list-item-description></list-item-description>
function listItem(){
const ddo = {
templateUrl : 'listItem.html'
}
return ddo
}
listItem.html – newly created file that templateUrl points to
<ol>
<list-item ng-repeat="item in list.items"></list-
item>
</ol>
on the <list-item> tags its optional to write the ng-repeat there can be written in
the main file.
We use these to avoid code duplication
function listItem(){
const ddo = {
restrict: "AE",
templateUrl : 'listItem.html'
}
return ddo
}
Function myDirective(){
Let ddo = {
Scope: {
MyProp: ‘=attributeName’}
}
}
Return ddo
}
<shopping-list my-list="list1 " title="{{list1.title}}"></shopping-list>
.directive('shoppingList', shoppingList)
function shoppingList(){
const ddo = {
templateUrl: 'shoppingList.html',
scope: {
list: '=myList',
title: '@title'
}
}
return ddo;
}
},
list.removeItem = (itemIndex) => {
this.lastRemoved = "Last item removed was " +
this.items[itemIndex].name
saving the array in the last remove property
shoppingList.removeItem(itemIndex);
list.title = origTitle + " ( " + list.items.length + " items )"
};
}
<shopping-list
items="list.items"
title="{{list.title}}"
bad-remove="list.removeItem" passed a function of removing
item
on-remove="list.removeItem(index)"> index for mapping
</shopping-list>
list.removeItem(index)"> -this (index) is not passed by shoppingListController as
list, these index is just a key for our directive to be able to find
<h3>{{ list.myTitle }}</h3>
<ol>
<li ng-repeat="item in list.items">
{{ item.quantity }} of {{ item.name }}
<button ng-click="list.badRemove($index)">Bad Remove
Item</button>
<button ng-click="list.onRemove({index: $index});">Remove
Item</button>
</li> index that I mapped is = to $index when clicking
</ol>
<div class="error" ng-if="list.cookiesInList()">WARNING! WARNING! COOKIES
DETECTED!</div>
angular.module('ShoppingListComponentApp', [])
.controller('shoppingListController1', shoppingListController1)
.factory('shoppingListFactory', shoppingListFactory)
.component('shoppingList', { instead of directive we are using
component
templateUrl: 'shoppingList.html',
controller: shoppingListComponentController,
bindings: { bindings = scope
items: '<',
myTitle: '@title',
onRemove: '&'
}
})
// function shoppingListDirective(){
// const ddo = {
// templateUrl: 'shoppingList.html',
// scope: {
// items: '<',
// myTitle: '@title',
// onRemove: '&'
// },
// controller: shoppingListDirectiveController,
// controllerAs: 'list',
// bindToController: true
// }
// return ddo;
// }
$ctrl.$postLink = function(){
$scope.$watch('$ctrl.cookiesInList()', function(newValue ,
oldValue){
console.log($element)$watch-will watch($ctrl.cookiesInList()) and
watch
if(newValue === true){ it with newValue and oldValue
//show warning
let warningElem = $element.find('div.error');
warningElem.slideDown(900)
}else{
//hide warning
let warningElem = $element.find('div.error')
warningElem.slideUp(900)
}
})
}
Avoid using $scope
$ctrl.$doCheck = function(){
if($ctrl.items.length !== totalItems){
console.log("# of items change. Checking for cookies!")
totalItems = $ctrl.items.length
if($ctrl.cookiesInList()){
let warningElem = $element.find('div.error');
warningElem.slideDown(900)
}
else{
let warningElem = $element.find('div.error')
warningElem.slideUp(900)
}
}
}
}
$scope.$on(‘namespace:eventName’, handler)
Function handler(event, data)[
If(data.prop === ‘val1’){
}
ShoppingListComponentController.$inject = ['$rootScope', '$element',
'$q', 'WeightLossFilterService']
function ShoppingListComponentController($rootScope, $element, $q,
WeightLossFilterService) {
var $ctrl = this;
var totalItems;
$ctrl.$onInit = function () {
totalItems = 0;
};
$ctrl.$doCheck = function () {
if ($ctrl.items.length !== totalItems) {
totalItems = $ctrl.items.length;
promises.push(WeightLossFilterService.checkName($ctrl.items[i].name));
}
SpinnerController.$inject = ['$rootScope']
function SpinnerController($rootScope) {
var $ctrl = this;
if (data.on) {
$ctrl.showSpinner = true;
}
else {
$ctrl.showSpinner = false;
}
});
};
To listen for events use $scope.$on or $rootScope.$on
Modules
Modules help us to split up our application into small part they then can be good together
angular.module( ‘module1’) or <html ng-
app=’module1’>
angular.module(‘module3, [ ‘module1’, ‘module2’] )
</html>
.controller(‘MyController’ , Mycontroller
<script src=src/mod2/module2.js”></script>
agular.module(‘module2’)
script src=”src/mode2/controller.js”></script> .run(function()
[] – if you want to specify the 2 argument you create the module not retrieving
nd
an existing one
It is best to separate js code into different files and best to place artifacts e.g
controllers into 1 file
Doesn’t matter the order you declare your modules e.g start with module2 instead
of module1
However you cannot declare an artifact before a module
.config(function() - runs before any other methods in the module
o The function value passed into the config method, can be injected with a
provider or constants
.run(function() – is executed right after the config method, can only inject
instances(e.g services) and constants not providers because we want to prevent
the system from being re-configured during run time
<!-- Libraries -->
<script src="lib/jquery-3.1.0.min.js"></script>
<script src="lib/angular.min.js"></script>
<script
src="src/shoppinglist/shoppinglist.module.js"></script>
<script src="src/spinner/spinner.module.js"></script>
Routing
2 types of package to use for routing implantation in a angularjs app
-ng-route
-ui-router
ngRoute Ui-router
- Separate Js file - Separate JS file
- Developed by google & - Developed by community
community - UI state is central( can have a
- No concept of UI state route with no unique URL for that
- Every route must be represented route)
by a URL - URL routing is also supported( UI
- No concept of nested views state is updated based on the URL
- OK for prototype projects - Nested view supported
- Better choice for more serious
projects
<script src=”lib/angular.min.js”></script>
angular.module(‘App’, [‘ui.router’]
<script src=lib/angular-ui-router.min.js”></script>
<body>
<ui-view></ui-view>
Angular.module(“app”)
.config(RoutesConfig)
RoutesConfig.$inject = [‘$stateProvider’ , ‘$urlRouterProvider’];
Function routersConfig(‘$stateProvider’ , ‘$urlRouterProvider’){}
$stateProvider.state(‘view1, { $urlRouterProvider.otherwise(‘/
url: view1’)
‘/view1’, $stateProvider.state(‘view1’, {
url:
template: <div></div} /view1}
.state(‘view2, {})
angular.module('RoutingApp',['ui.router']);
angular.module('RoutingApp')
.config(RoutesConfig);
// Set up UI states
$stateProvider
.state('tab1', {
url: '/tab1', //hyperlink
templateUrl: 'src/tab1.html'
})
.state('tab2', {
url: '/tab2',
templateUrl: 'src/tab2.html'
});
}
<div class="tabs">
<a ui-sref="tab1" ui-sref-active="activeTab">Tab 1</a>
<a ui-sref="tab2" ui-sref-active="activeTab">Tab 2</a>
<!-- <button ui-sref="tab2">Tab 2</button> -->
</div>
ui-sref="tab1" – ui router state reference
"tab1" === .state('tab1' must match/ must be equal
If you were to comment out url: '/tab2' , tab2 will no longer be a hyper link but you can
still press tab2 to execute the information inside
ui-sref-active="activeTab"> -let us specify a css class that should be applied to a
specific tag
Routes.js
angular.module('ShoppingList')
.config(RoutesConfig);
// Home page
.state('home', {
url: '/',
templateUrl: 'src/shoppinglist/templates/home.template.html'
})
// Premade list page
.state('mainList', {
url: '/main-list',
templateUrl: 'src/shoppinglist/templates/main-
shoppinglist.template.html',
controller: 'MainShoppingListController as mainList'
});
RoutesConfig Sets up a couple of states .state
1st of all it re-routes anything that doesn’t match any particular url
$urlRouterProvider.otherwise('/' to a slash('/') or home page
.state('home', { and its template url is templateUrl:
'src/shoppinglist/templates/home.template.html' e which is a very
short template
Home.template.html
<a ui-sref="mainList">See our Premade No Cookie Shopping List!
</a>
o It is using state reference ui-sref= to "mainList"> so "mainList">
better be a state we defined in routes.js .state('mainList',
The template url of .'mainList' which is templateUrl
'src/shoppinglist/templates/main-shoppinglist.template.html' is
pointing to
Main-shoppinglist.template.html
<div id="list" ng-controller='MainShoppingListController as
mainList'> declares a controller labelled mainList
<a ui-sref="home">Home</a> < <span>List</span>
<h3>Premade List with Absolutely No Cookies in it</h3>
<shopping-list items="mainList.items"></shopping-list>
</div>
o <a ui-sref="home">Home</a> < <span>List</span>
declaring a link that helps us go back to the home
screen
o it uses the shoppinglist component <shopping-list to
output the list
Shoppinglist.component.js
angular.module('ShoppingList')
.component('shoppingList', {
templateUrl:
'src/shoppinglist/templates/shoppinglist.template.html',
bindings: {
items: '<'
}
o The shopping list component just passes along the items items: which is
the list of our shopping items and it is pointing us to a url templateUrl:
'src/shoppinglist/templates/shoppinglist.template.html'
Shoppinglist.template.html
<li ng-repeat="item in $ctrl.items">
{{ item.quantity }} of {{ item.name }}
</li>
o Loop over the item quantity and name to output the list
{{ item.quantity }} of {{ item.name }}
Main-shoppinglist.controller
angular.module('ShoppingList')
.controller('MainShoppingListController', MainShoppingListController);
MainShoppingListController.$inject = ['ShoppingListService'];
function MainShoppingListController(ShoppingListService) {
var mainList = this;
mainList.items = [];
mainList.$onInit = function () {
ShoppingListService.getItems()
.then(function (result) {
mainList.items = result;
});
Main-shoppinglist.controller - Its is outputting the whole list to begin with
We injected the 'ShoppingListService'into it and we are using the
'ShoppingListService’ in order to initialize these mainList.items
o We use a promise .getItems()which is returning a promise since we
use the .then method and when only the promise returns we are setting
the mainList.items to the = result which its returning (result)
Shoppinglist.service.js
ShoppingListService.$inject = ['$q', '$timeout']
function ShoppingListService($q, $timeout) {
var service = this;
return deferred.promise;
o We use a promise because we are simulating a call to a server
o That server call comes back to the main-shoppinglist.controller and the
mainList.items gets set , which then goes to main-
shoppinglist.template.html and able to pass
items="mainList.items"></ into shoppinglist component
<shopping-list then goes ahead to output the shopping list
Shoppinglist.template.html {{ item.quantity }} of {{ item.name
}}
resolve Is a configuration object that has some key and value pairs
o can be used to inject values directly into the controller responsible for the state
Service.getData() return a promise
myData is going to have a value, which is going to be injected into the view1
controller with the key of myData
o if the resolve property which is myData gets aside a promise, the router will
not advance us to the new state(‘view1’) until the promise is resolved, if the
promise is rejected all together the router will not advance us to the new state
the name of the key in the resolve’s property object is what is to be injected into the
corresponding controller function
o resolve can have properties that can contain anything : object, string, etc
when clicking the link on the webpage(main-list),the list pops in 800 millisecond late because we
are switching the view 1st and then get the data
create a resolve property in the route
.state('mainList', {
url: '/main-list',
templateUrl: 'src/shoppinglist/templates/main-
shoppinglist.template.html',
controller: 'MainShoppingListController as mainList',
resolve: {
items: ['ShoppingListService', (ShoppingListService) => {
return ShoppingListService.getItems()
// MainShoppingListController.$inject = ['ShoppingListService'];
// function MainShoppingListController(ShoppingListService) {
MainShoppingListController.$inject = ['items'];
function MainShoppingListController(items) {
var mainList = this;
mainList.items = items
// mainList.$onInit = function () {
// ShoppingListService.getItems()
// .then(function (result) {
// mainList.items = result;
// });
// };
}
url: ‘/view1/{param1}’
.state('itemDetail', {
url: '/item-detail/{itemId}',
templateUrl: 'src/shoppinglist/templates/item-detail.template.html',
controller: 'ItemDetailController as itemdetail',
resolve: {
item: ['$stateParams', 'ShoppingListService',
($stateParams, ShoppingListService) => {
return ShoppingListService.getItems().then( (items) => {
return items[$stateParams.itemId] refers to the specific item
looked at
}
{itemId} Tell us which item id (0 or 1 or 2) with 3 items since its an array it is 0 base
'$stateParams'give use the value of this parameter itemId
angular.module('ShoppingList')
.controller('ItemDetailController', ItemDetailController);
//'item' is injected through state's resolve
ItemDetailController.$inject = ['item']protects the controller from
manification
function ItemDetailController(item){
let itemdetail = this;
itemdetail.name = item.name;
itemdetail.quantity = item.quantity;
itemdetail.description = item.description;
}
itemdetail Instance of our controller ItemDetailController which we are using inside
of our template
<a ui-sref="home">Home</a> <
<a ui-sref="mainList">List</a> <