Isolate Scope with $watch - javascript

I have a custom directive that I am going to put on a page multiple times
<div id="upcomingweekssubnav" style="text-align:center">
<div style="width:100%">
<div style="width: 50%; float:left">
<h4>Week:</h4>
<ul class="weeks">
<li ng-model="vm.selectedWeek" ng-repeat="n in vm.range(vm.selectedLeague.StartWeek,vm.selectedLeague.EndWeek)">
<span ng:click="vm.setWeeklyLineup(n)">{{n}}</span>
</li>
</ul>
</div>
</div>
</div>
<br /><br />
<div id="my-team-lineup" ng-show="vm.showMe" style="text-align:center">
<div id="myteamDiv" style="width:100%; overflow:hidden;">
<div id="myTeamBeforeDiv" style="width:50%; float: left;">
<center>
<h4>Before Trade</h4>
<div ng-lineup week="vm.selectedWeek" lineup="vm.myBeforeTradeLineup"></div>
</center>
</div>
<div id="myTeamAfterDiv " style="width:50%; float: right ">
<center>
<h4>After Trade</h4>
<div ng-lineup week="vm.selectedWeek" lineup="vm.myAfterTradeLineup"></div>
</center>
</div>
</div>
</div>
<div id="thier-team-lineup" ng-show="!vm.showMe" style="text-align:center">
<div id="thierteamDiv" style="width:100%; overflow:hidden;">
<div id="thierTeamBeforeDiv" style="width:50%; float: left">
<center>
<h4>Before Trade</h4>
<div ng-lineup week="vm.selectedWeek" lineup="vm.thierBeforeTradeLineup"></div>
</center>
</div>
<div id="thierTeamAfterDiv " style="width:50%; float: right ">
<center>
<h4>After Trade</h4>
<div ng-lineup week="vm.selectedWeek" lineup="vm.thierAfterTradeLineup"></div>
</center>
</div>
</div>
</div>
ng-lineup is the directive name, here is the javascript and template file
app.directive('ngLineup', function () {
var directive = {
link: function (scope, elem, attrs) {
scope.week = null;
scope.$watch(attrs.week, function (data) {
var myBefore = scope.$eval(attrs.lineup);
if (myBefore !== undefined) {
myBefore.forEach(function (element) {
if (element.Week === data) {
var roster = element.Roster;
element.Roster.forEach(function (player) {
if (player.WeeklyMatchups[data] !== undefined) {
player.WeekProjections = player.WeeklyMatchups[data].WeekProjections;
player.Opponent = player.WeeklyMatchups[data].Opponent;
}
}, this);
scope.lineup = roster;
scope.pointsTotal = element.ProjectedPoints;
}
}, this);
}
});
},
restrict: 'AE',
priority: 10,
templateUrl: '/app/templates/lineup.html',
};
return directive;
});
Template
<div class="tableRow header blue" id="statTable0">
<div class="cell">Pos</div>
<div class="cell">Players</div>
<div class="cell">Opp</div>
<div class="cell">Proj Pts</div>
</div>
<div class="tableRow" ng:repeat="e in lineup">
<div class="cell">
{{e.Name == "" ? 'No Player Available' : e.Name}}
</div>
<div class="cell">
{{e.Position.Abbreviation.indexOf("_") > -1 ? "FLEX" : e.Position.Abbreviation }}
</div>
<div class="cell">
{{e.Opponent}}
</div>
<div class="cell">
{{vm.selectedWeek == e.ByeWeek[0] ? 'BYE' : e.WeekProjections}}
</div>
</div>
<br />
<h4>Week {{vm.selectedWeek}} Projected Total (Before Trade): {{vm.myBeforeWeekProjectedPoints}}</h4>
And here is what the directive looks like on the screen
What I am doing is based on the selected Week, I am showing some data that is based off that scope variable. What is happening is that when the directive watch is triggered, all the directives on the page are being updated, so each one has the same data in it. I started reading on isolated scope, but I am having a hard time being able to wire that up with the watch that I need.

use scope:true
as
var directive = {
scope:true;
link: function (scope, elem, attrs) {
it will inherit from parent but won't reflect back any changes made from parent back to directive.

The problem is that vm.selectedWeek is shared as an week. Thus a change triggered in one of the directives would definitely trigger the watch in the other directives. Thus, although you changed the value at one, the change got reflected across. Try to use the bindings property and set it to
var directive = {
...
...
bindings:{
week: '<'
...
}
This will ensure only one-way binding
Also, instead of using attrs.week, try to use week directly from the controller scope. Mark as answer if this helps.

Related

How to bind this within js nested object iteration within a function. Jquery

again, probably a terrible title - but what I'm trying to do is to make a simple search feature on my website. You click a nav button, which updates the search bar, whi in turn triggers an onchange event to update the current appended list.
function update() {
var list = $("#comic__modern-list");
list.empty();
$.each(Object.keys(comics), function() {
var currentObject = comics[this];
var filter = comics[this].type;
var publisher = comics[this].publisher;
if (search == "") {
if(filter == "modern") {
list.append(`
<div class="comic__box">
<div class="comic__image-box">
<img src="${currentObject['data-item-image']}" alt="${currentObject['data-item-description']}" class="img-fluid">
<div class="comic__desc-wrap">
<div class="comic__desc">${currentObject['data-item-description']}, issue #${currentObject['issue']} (${currentObject['year']})</div>
</div>
</div>
<div style="text-align:center; margin-top: 1rem">
<button
class="btn btn-warning snipcart-add-item comic__button"
data-item-id="${currentObject['data-item-id']}"
data-item-price="${currentObject['data-item-price']}"
data-item-url="${currentObject['data-item-url']}"
data-item-description="${currentObject['data-item-description']}"
data-item-image="${currentObject['data-item-image']}"
data-item-name="${currentObject['data-item-name']}">
<div class="comic__desc-desk">£${currentObject['data-item-price']}<br>Add to cart</div><div class="comic__desc-mob">BUY <br> ${currentObject['data-item-description']}, Issue: ${currentObject['issue']} (${currentObject['year']})</div>
</button>
</div>
</div>
`)
}
} else if (search == publisher) {
list.append(`
<div class="comic__box">
<div class="comic__image-box">
<img src="${currentObject['data-item-image']}" alt="${currentObject['data-item-description']}" class="img-fluid">
<div class="comic__desc-wrap">
<div class="comic__desc">${currentObject['data-item-description']}, issue #${currentObject['issue']} (${currentObject['year']})</div>
</div>
</div>
<div style="text-align:center; margin-top: 1rem">
<button
class="btn btn-warning snipcart-add-item comic__button"
data-item-id="${currentObject['data-item-id']}"
data-item-price="${currentObject['data-item-price']}"
data-item-url="${currentObject['data-item-url']}"
data-item-description="${currentObject['data-item-description']}"
data-item-image="${currentObject['data-item-image']}"
data-item-name="${currentObject['data-item-name']}">
<div class="comic__desc-desk">£${currentObject['data-item-price']}<br>Add to cart</div><div class="comic__desc-mob">BUY <br> ${currentObject['data-item-description']}, Issue: ${currentObject['issue']} (${currentObject['year']})</div>
</button>
</div>
</div>
`)
}
});
}
The current list is generated by this, which works fine:
$.each(Object.keys(comics), function() {
var currentObject = comics[this];
var currentObject2 = comics[this].type;
console.log(currentObject2);
if (search == "") {
if(currentObject2 == "modern") {
var list = $("#comic__modern-list");
list.append(`
<div class="comic__box">
<div class="comic__image-box">
<img src="${currentObject['data-item-image']}" alt="${currentObject['data-item-description']}" class="img-fluid">
<div class="comic__desc-wrap">
<div class="comic__desc">${currentObject['data-item-description']}, issue #${currentObject['issue']} (${currentObject['year']})</div>
</div>
</div>
<div style="text-align:center; margin-top: 1rem">
<button
class="btn btn-warning snipcart-add-item comic__button"
data-item-id="${currentObject['data-item-id']}"
data-item-price="${currentObject['data-item-price']}"
data-item-url="${currentObject['data-item-url']}"
data-item-description="${currentObject['data-item-description']}"
data-item-image="${currentObject['data-item-image']}"
data-item-name="${currentObject['data-item-name']}">
<div class="comic__desc-desk">£${currentObject['data-item-price']}<br>Add to cart</div><div class="comic__desc-mob">BUY <br> ${currentObject['data-item-description']}, Issue: ${currentObject['issue']} (${currentObject['year']})</div>
</button>
</div>
</div>
`)
}
}
});
From what I can gather, this has to do with the keyword "this" no longer meaning what it did when it was outside of the function, so I'm assuming the fix will be to do with bind(), but I can't make heads nor tails of it.
p.s, if there's an easier/simpler way to set up a search system, please enlighten me!

Separate scope variablesin angular

I have one scope variables for four elements in div. When I change the variable it affects all the four elements within which it is included. I am beginner in angular js and can't handle it alone.
Here is an example to explain better:
JS:
/* controller-home.js ********************************************************/
app.controller("homeController", function($scope, $http, $state) {
$scope.heading = "SWITCHES";
$scope.button1 = "Хол"
$scope.button2 = "Кухня"
$scope.button3 = "Баня"
$scope.button4 = "Балкон"
$scope.imageSrc = "LitLamp.png";
$scope.onOf = function() {
console.log("Switched");
if ($scope.imageSrc === "LitLamp.png") {
$scope.imageSrc = "NotLit.png";
}
}
})
The HTML:
<div style="text-align: center;">
<h1 >SWITCHES</h1>
<div ng-controller="homeController">
<div style="display:inline-block;">
<button ng-click="onOf()" class="homeSwitchButton">{{button1}}</button>
<img class="homeButtonImage" src="{{imageSrc}}" alt="Lamp" >
</div>
<div style="display:inline-block;">
<button ng-click="onOf()" class="homeSwitchButton">{{button2}}</button>
<img class="homeButtonImage" src="{{imageSrc}}" alt="Lamp" >
</div>
<div style="display:inline-block;">
<button ng-click="onOf()" class="homeSwitchButton">{{button3}}</button>
<img class="homeButtonImage" src="{{imageSrc}}" alt="Lamp" >
</div>
<div style="display:inline-block;">
<button ng-click="onOf()" class="homeSwitchButton">{{button4}}</button>
<img class="homeButtonImage" src="{{imageSrc}}" alt="Lamp" >
</div>
</div>
</div>
The problem is that when I hit one of the four buttons, all the images change. How to group image with button, or when I hit the first button only the image below it to change and the rest three to remain unchanged?
The problem here is because you are using the same variable imageSrc for all image. What you can do here is create an object for each image.
$scope.images = {
button1: 'source.png',
button2: 'source.png',
button3: 'source.png',
button4: 'source.png'
}
In the onOf method you can pass the name of the button you are changing
$scope.onOf = function(buttonName) {
if ($scope.images[buttonName] === 'bla.png') {
$scope.images[buttonName] = 'yay.png';
}
}
And in the html you set the images calling each property and passing the name of the button as argument on onOf
<div style="display:inline-block;">
<button ng-click="onOf('button1')" class="homeSwitchButton">{{button1}}</button>
<img class="homeButtonImage" src="{{images.button1}}" alt="Lamp" >
</div>
Better approach: You can put the buttons as an array and use ng-repeat
$scope.buttons = [{ name: 'bla', image: 'yay.png'}]
$scope.onOf = function(button) {
if (button.image === 'yay') {
...
}
}
And in the html
<div ng-repeat="button in buttons" style="display:inline-block;">
<button ng-click="onOf(button)" class="homeSwitchButton">{{button.name}}</button>
<img class="homeButtonImage" src="{{button.image}}" alt="Lamp" >
</div>

Getting undefined when i try to access parameter

I am trying to access the parameter which is passed to the JavaScript function and alert the value. but when i alert the value i am getting undefined in alert. what is wrong i have done here.
html
<div ng-app="plusminusApp" ng-controller="categorylist">
<div class="whitescreen" id="buttons-overlay">
<div class="icons-container">
<div class="icons-inside-container">
<div ng-repeat="category in categories" value="{{category.picture}}" class="category-icon-thumbnail" onclick="setCategory(this.value);">
<img value="{{category.category}}" src="{{category.picture}}">
</div>
</div>
</div>
</div>
</div>
app.js
function setCategory(category){
alert(category)
document.getElementById('buttons-overlay').style.display = 'none';
}
If you want to pass a angular's scope value to a function, it must be ng- prefixed event. You can't pass scope variable to a function outside of angular context.
<div ng-repeat="category in categories" value="{{category.picture}}" class="category-icon-thumbnail" ng-click="setCategory(category.picture)">
and the function must be in the scope of the controller that means you need to define $scope.setCategory = function(val){}
HTML:
<div ng-app="plusminusApp" ng-controller="categorylist">
<div class="whitescreen" id="buttons-overlay">
<div class="icons-container">
<div class="icons-inside-container">
<div ng-repeat="category in categories"class="category-icon-thumbnail" >
<img value="{{category.category}}" src="{{category.picture}}" ng-click="setCategory(category.picture);">
</div>
</div>
</div>
</div>
JS:
$scope.setCategory = function(val){
console.log(val)
}
Assuming this to be your json
$scope.categories = [{
'category': 'ABC',
'picture': 'https://randomuser.me/api/portraits/men/22.jpg'
}, {
'category': 'ced',
'picture': 'https://randomuser.me/api/portraits/men/13.jpg'
}]
Use the below code
$scope.setCategory =function(category) {
$scope.something=category;
document.getElementById('buttons-overlay').style.display = 'none';
}
<div ng-app="plusminusApp" ng-controller="categorylist">
<p>Hello!</p>
<div class="whitescreen" id="buttons-overlay">
<div class="icons-container">
<div class="icons-inside-container">
<div ng-repeat="category in categories" value="{{category.picture}}" class="category-icon-thumbnail">
<button ng-click="setCategory(category.category)"> {{category.category}}
</button>
<img value="{{category.category}}" src="{{category.picture}}">
</div>
</div>
</div>
</div>
</div>
For simplicity and understanding purpose I have changed the click event from div to button.
LIVE DEMO

Selecting only one child element in AngularJS with jquery

So, I had a working function in jQuery but then I decided to use Angular for my application. Just can't find the way so it adds the CSS to only one child element.
Jquery code that was working
$('.list-div').on('mouseenter', function(){
$(this).find('.client-jar').css('opacity','1');
}).on('mouseleave', function() {
$(this).find('.client-jar').css('opacity','0');
});
Current html
<ul>
<li ng-repeat="one in ones | orderBy:'-date'">
<div class="list-div">
<div class="row jar-div first-jar-div" ng-mouseover="showButton()" ng-mouseleave="hideButton()">
<div class="col-xs-7 description-div">
<p class="version">{{ one.version }}</p>
<p class="date">{{ one.date }}</p>
</div>
<div class="col-xs-5 buttons-div">
<div class="list-button client-jar">
<a class="list-link" data-toggle="modal" data-target="#myModal">create server</a>
</div>
<div class="list-button server-jar">
<a class="list-link">Server jar</a>
</div>
</div>
</div>
</div>
</li>
</ul>
And Current Angular JS
$scope.showButton = function(){
angular.element('.list-div').find('.client-jar').css('opacity','1');
};
$scope.hideButton = function(){
angular.element('.list-div').find('.client-jar').css('opacity','0');
};
I would use:
https://docs.angularjs.org/api/ng/directive/ngMouseenter
<button ng-mouseenter="hoverState = true">mouse in mouse out</button>
Then use with:
https://docs.angularjs.org/api/ng/directive/ngMouseleave
<button ng-mouseenter="hoverState = true" ng-mouseleave="hoverState = false">mouse in mouse out</button>
At this point you have a hover over and off flag. You can now pick this flag up with ng-class to set and unset a CSS class which contains your opacity stuff, and any future CSS animations etc etc:
https://docs.angularjs.org/api/ng/directive/ngClass
<button ng-mouseenter="hoverState = true" ng-mouseleave="hoverState = false" ng-class="{'opacity-class':hoverState}">mouse in mouse out</button>
No jQuery required, AngularJS is just a totally different way of going about things.
<style>
.opacity-class .client-jar{
opacity:0;
}
</style>
<ul>
<li ng-repeat="one in ones | orderBy:'-date'">
<div class="list-div">
<div class="row jar-div first-jar-div" ng-mouseenter="hoverState = true" ng-mouseleave="hoverState = false" ng-class="{'opacity-class':hoverState}">
<div class="col-xs-7 description-div">
<p class="version">{{ one.version }}</p>
<p class="date">{{ one.date }}</p>
</div>
<div class="col-xs-5 buttons-div">
<div class="list-button client-jar">
<a class="list-link" data-toggle="modal" data-target="#myModal">create server</a>
</div>
<div class="list-button server-jar">
<a class="list-link">Server jar</a>
</div>
</div>
</div>
</div>
</li>
</ul>
angular.module('App').directive('listFade', function() {
return function(scope, element) {
element.bind('mouseover', function(children) {
// YOUR ANIMATION CODE HERE
});
element.bind('mouseout', function(children) {
// YOUR ANIMATION OUT CODE HERE
});
}
})
then just add the directive to your ng-repeat markup, list-fade=""
you don't need children but its a easy way to call the children of each element. This should help you out. Then get rid of that ng-mouseover showButton();
Updating your code to use inline CSS, would be like this.
var element = document.querySelector('.list-div .client-jar');
$scope.showButton = function(){
angular.element(element).css('opacity','1');
};
$scope.hideButton = function(){
angular.element(element).css('opacity','0');
};
As in AngularJS .element documentation, it's said that you need to pass a element.
You can also use ng-class, creating a class for opacity:
<div class="client-jar" ng-class="{class: expression}"></div>
https://docs.angularjs.org/api/ng/directive/ngClass
Or use ng-show and ng-hide for display control:
<div class="client-jar" ng-show="expression"></div>
https://docs.angularjs.org/api/ng/directive/ngShow
You could even use ng-style for inline css:
<div class="client-jar" ng-style="{'opacity': '1'}"></div>
https://docs.angularjs.org/api/ng/directive/ngStyle

AngularJS: How to prevent "code flash" in page while loading

I have created a simple app using AngularJS. When I open the page for a second I see the screen below:
However, after the load is complete I see the loaded and styled content which is fine:
How do I prevent the flash of AngularJS code on my page ? Is this related to FOUC ?
Here is the HTML code:
<!doctype html>
<html class="no-js" lang="en" ng-app="MainApp">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Foundation | Welcome</title>
<link rel="stylesheet" href="css/foundation.css" />
<script src="js/vendor/modernizr.js"></script>
<style>
.row.full-width {
width: 100%;
margin-left: auto;
margin-right: auto;
max-width: initial;
}
</style>
</head>
<body ng-controller="MainCtrl">
<div class="off-canvas-wrap" data-offcanvas>
<div class="inner-wrap">
<nav class="tab-bar">
<section class="right-small">
<a class="right-off-canvas-toggle menu-icon" href="#"><span></span></a>
</section>
<section class="left tab-bar-section">
<h1 class="title">Salary Calculator</h1>
</section>
</nav>
<aside class="right-off-canvas-menu">
<ul class="off-canvas-list">
<li>
<label>Location</label>
</li>
<li>United Kingdom
</li>
</ul>
</aside>
<section class="main-section">
<div class="row full-width">
<div class="large-4 columns">
<ul class="tabs" data-tab>
<li class="tab-title active">Annual Salary
</li>
<li class="tab-title">Monthly Expenses
</li>
</ul>
<div class="tabs-content">
<div class="content active" id="panel1">
<div class="row">
<div class="large-12 columns">
<input ng-change="calculate()" type="text" placeholder="Salary" ng-model="salary"/>
</div>
</div>
</div>
<div class="content" id="panel2">
<div class="row">
<div class="large-4 columns">
<input ng-change="calculate()" type="text" placeholder="Rent" ng-model="rent" />
</div>
<div class="large-4 columns">
<input ng-change="calculate()" type="text" placeholder="Wireless, TV, Home Phone" ng-model="telecom"/>
</div>
<div class="large-4 columns">
<input ng-change="calculate()" type="text" placeholder="TV License" ng-model="tv" />
</div>
</div>
<div class="row">
<div class="large-4 columns">
<input ng-change="calculate()" type="text" placeholder="Mobile Phone" ng-model="mobile"/>
</div>
<div class="large-4 columns">
<input ng-change="calculate()" type="text" placeholder="Subscription" ng-model="subscription"/>
</div>
<div class="large-4 columns">
<input ng-change="calculate()" type="text" placeholder="Electricty" ng-model="electricity" />
</div>
</div>
<div class="row">
<div class="large-4 columns">
<input ng-change="calculate()" type="text" placeholder="Food" ng-model="food"/>
</div>
<div class="large-4 columns">
<input ng-change="calculate()" type="text" placeholder="Transport" ng-model="transport" />
</div>
<div class="large-4 columns">
<input ng-change="calculate()" type="text" placeholder="Charity" ng-model="charity"/>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<input ng-change="calculate()" type="text" placeholder="Other" ng-model="other"/>
</div>
</div>
</div>
</div>
</div>
<div class="large-8 columns" ng-cloak >
<table >
<thead>
<tr>
<th width="200"></th>
<th width="250">Yearly</th>
<th width="250">Monthly</th>
<th width="250">Weekly</th>
<th width="250">Daily</th>
</tr>
</thead>
<tbody ng-repeat="val in results">
<tr>
<td>{{val.rowType}}</td>
<td>{{val.yearly}}</td>
<td>{{val.monthly}}</td>
<td>{{val.weekly}}</td>
<td>{{val.daily}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<a class="exit-off-canvas"></a>
</div>
</div>
<script src="../bower_components/angularjs/angular.js"></script>
<script src="js/app-service.js"></script>
<script src="js/app-controller.js"></script>
<script src="js/app-directives.js"></script>
<script src="js/app.js"></script>
<script src="js/vendor/jquery.js"></script>
<script src="js/foundation.min.js"></script>
<script>
$(document).foundation();
</script>
</body>
</html>
EDIT:
Please see my answer as well for an alternative solution in addition to the accepted one.
ng-cloak will help to some extent, but you can fully prevent it using ng-bind directive instead of using {{ }}.
e.g.
<td ng-bind="val.monthly"> </td>
not
<td>{{val.monthly}}</td>
It has been a long time but here is for my working solution for this one:
You need to use ng-cloak on the body tag of your html BUT the most important part is this CSS below:
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important;
}
For me I had to add this for getting ng-cloak to work. This is probably not the only solution to this problem as can be seen in other answers. Hope this helps someone.
Angular already gives you the tool to prevent this: ngCloak: https://docs.angularjs.org/api/ng/directive/ngCloak
Just put the directive on your body like <body ng-cloak> and it should work.
EDIT
The Docs also advice you to actually not put it on the body, but on smaller portions of your page - wherever you see the need. Depending on the size of your page, that is a good idea. For smaller Pages I put it on the body and never had problems.
Along with ng-cloak, you can use a resolve object in your router. This will prevent the controller from instantiating and the view from rendering until the data is there.
In the following example I am assuming you are using uiRouter. The same pattern applies for ngRouter.
Your state config:
$stateProvider
.state('yourState',{
templateUrl: 'yourTemplate.html',
controller: 'YourController as vm',
resolve: YourController.resolve
})
As you can see, you have set the resolve property of the state to a static resolve object on your controller. Now the route will not resolve until this object is resolved.
To setup resolve object, lets assume you have a service yourService that has a method getData that returns a promise. This is very important. Because we don't want the route resolved until the promise is resolved.
So your controller may look something like this.
YourController.$inject = ['yourService'];
function YourController(yourService) {
var self = this;
yourService.getData().then((data) { self.data = data});
}
This is pretty standard. You can access the data from the view with vm.data but you will see a flash of {{vm.data}}. That is, if we remove the resolve we have added to the state config.
So now we change the controller to add a static resolve object to work with the resolve we have added to the state config.
YourController.resolve = {
'yourService': 'yourService',
'data': ['yourService', function(yourService) {
return yourService.getData();
}]
}
YourController.$inject = ['data'];
function YourController(data) {
this.data = data;
}
So now we have a resolve object. The yourService will resolve as a normal service, but the data property will resolve only when the promise returned by getData() is resolved. Then this data will be passed directly into the controller using Dependancy Injection.
In reality, you probably wont need to use ng-cloak if you use resolve.
Here is a working example:
angular.module('app', ['ui.router'])
.config(['$stateProvider',
function($stateProvider) {
$stateProvider
.state('noDot', {
controller: "NoDotController",
template: "Using a old style $scope binding {{customers[0].CutomerName}}"
})
.state('noResolve', {
controller: "NoResolveController as vm",
template: "We are displaying things before the data is here {{vm.customers[0].CustomerName}}"
})
.state('withResolve', {
controller: "WithResolveController as vm",
template: "We are waiting for data before displaying anything {{vm.customers[0].CustomerName}}",
resolve: WithResolveController.resolve
})
.state('empty', {
template: ""
})
}
])
.controller('NoResolveController', NoResolveController)
.controller('NoDotController', NoDotController)
.controller('WithResolveController', WithResolveController)
.service('northwind', Northwind);
NoDotController.$inject = ['$scope', 'northwind'];
function NoDotController($scope, northwind) {
northwind.getCustomers().then(function(customers) {
$scope.customers = customers});
}
NoResolveController.$inject = ['northwind'];
function NoResolveController(northwind) {
var self = this;
northwind.getCustomers().then(function(customers) {
self.customers = customers;
});
}
WithResolveController.resolve = {
'northwind': 'northwind',
'customers': ['northwind',
function(northwind) {
return northwind.getCustomers();
}
]
}
WithResolveController.$inject = ['customers'];
function WithResolveController(customers) {
this.customers = customers;
}
Northwind.$inject = ['$timeout', '$q'];
function Northwind($timeout, $q) {
this.$q = $q;
this.$timeout = $timeout;
}
Northwind.prototype.getCustomers = function() {
var deferred = this.$q.defer();
this.$timeout(function() {
deferred.resolve([{CustomerName: "Name of Customer"}])
}, 1000);
return deferred.promise;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.13/angular-ui-router.js"></script>
<div ng-app="app">
<a ui-sref="noDot" href="#">No Dot</a>
<span> | </span>
<a ui-sref="empty" href="#">Emtpy</a>
<span> | </span>
<a ui-sref="noResolve" href="#">No Resolve</a>
<span> | </span>
<a ui-sref="empty" href="#">Emtpy</a>
<span> | </span>
<a ui-sref="withResolve" href="#">With Resolve</a>
<br>
<br>
<ui-view></ui-view>
</div>

Categories

Resources