AngularJS : Communication between directives - ng-repeat not refresh - javascript

I apologize of a mess but this is the first time on stackoverflow ;)
Link to jsfiddle
http://jsfiddle.net/1u1oujmu/19/
I have problem with communication between directives and refresh ng-repeat.
I have two pages homePage and dashboardPage - on these page I have directive when I refresh page (dashboardPage) everything is working, but when I switch on homePage and I will back to dahsboardPage my problem starts occurs.
Step reproduce:
dashboardPage - reload - add new link - list-link directive is refresh new link is on list
go to homePage
back to dashboard page
try to add new link - when link is added (on server and I receives response) I call factory to store a data:
dataFactory.editData("userLinksList", result.data);
//part of factory to edit and propagation data
editData: function(name, data){
dataArray[name] = data;
$rootScope.$broadcast(name);
},
Then in directive controller I have condition to listen propagation "userLinksList" checkRootScope this is flag for only one register listener
Problem is in line:
$scope.data.links = dataFactory.getData("userLinksList");
In $scope.data.links I receives new data but I don't know why ng-repeat is not refresh
when I go to homePage and back to dashboard new link will be on list
if(checkRootScope){
$rootScope.$on("userLinksList", function () {
$scope.data.links = dataFactory.getData("userLinksList");
});
checkRootScope = false;
}
homePage - on the page I have list-link directive:
<div class="columns marketing-grid">
<div class="col-md-6">
<list-link hp="true"></list-link>
</div>
</div>
dashboardPage - on the page I have this same directive without parameter:
<div class="row">
<div class="col-sm-12 col-md-8">
<list-link></list-link>
</div>
</div>
template of list-link:
<ul ng-if="data.links">
<li ng-repeat="link in data.links | filter: search" class="link-list-item" data-id="{{link.id}}">
<div class="row">
<div class="col-md-9">
<a ng-href="link.url"><h3>{{link.title}} <span>{{link.host}}</span></h3></a>
</div>
<div class="col-md-3 link-list-time text-right">
{{link.date | date : 'd/MM/yyyy' }}
</div>
<div class="col-md-12">
<blockquote ng-show="link.comment">{{link.comment}}</blockquote>
</div>
<div class="col-md-2">
<span class="link-list-counter all" title="Number of links">{{link.counterAll}}</span>
</div>
<div class="col-md-6 link-list-tags">
<span>tags:</span>
<ul ng-if="link.tags">
<li ng-repeat="item in link.tags">#{{item}}</li>
</ul>
</div>
<div class="col-md-4 text-right link-list-buttons">
<button class="btn btn-default btn-xs" title="Edit" ng-click="edit(link.id);">Edit <span class="glyphicon glyphicon-edit" aria-hidden="true"></span></button>
<button class="btn btn-default btn-xs" title="Delete" ng-click="delete(link.id);">Delete <span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
</div>
</div>
</li>
</ul>
Directive list-link:
app.directive("listLink", ['path', function(path){
var path = path.url(),
checkRootScope = true;
return {
restrict : "E",
scope : {
hp : "="
},
templateUrl: path.template.listlink,
replace : true,
transclude : false,
controller : ['$rootScope', '$scope','conn', 'auth', 'loaderService','stringOperation','dataFactory', function($rootScope, $scope, conn, auth, loaderService, stringOperation,dataFactory){
var dataConenction = function(){
conn.getData(path.server.link, { params : $scope.data })
.then(function(result){
if($scope.data.all == true){
dataFactory.addData("popularLinksList",result.data);
$scope.data.links = dataFactory.getData("popularLinksList");
} else{
dataFactory.addData("userLinksList",result.data);
$scope.data.links = dataFactory.getData("userLinksList");
}
}, function(msg){
console.log(msg);
});
};
$scope.hp = (typeof $scope.hp === "undefined" ? false : $scope.hp);
$scope.path = path;
$scope.userInfo = auth.getUserInfo();
$scope.data = {
auth : $scope.userInfo,
check : false,
all : $scope.hp
};
dataConenction();
if(checkRootScope){
$rootScope.$on("userLinksList", function () {
$scope.data.links = dataFactory.getData("userLinksList");
});
checkRootScope = false;
}
$scope.edit = function(id){
$rootScope.$broadcast("editLink", {"id": id});
};
$scope.delete = function(id){
var check = confirm("Are you sure you want to remove?");
if (check == true) {
conn.deleteData(path.server.link, {"params" : {auth : $scope.userInfo, id : id}})
.then(function(result){
dataFactory.editData("userLinksList",result.data.links);
$scope.data.links = dataFactory.getData("userLinksList");
dataFactory.editData("userTagsList",result.data.tags);
}, function(msg){
console.log(msg);
});
}
};
}]
}
}]);

Not sure if you already fixed it but I had a crack at it.
First the "why not working" part -
Page1 creates a new scope, lets say scope1.
Page2 creates a new scope, say scope2.
When the Page1 is clicked the data.link is set to 5 items and below code is run [scope1.data.link = 5 items] -
if(checkRootScope){
$rootScope.$on("userLinksList", function () {
$scope.data.links = dataFactory.getData("userLinksList");
});
checkRootScope = false;
}
When the Page2 is clicked, it set 7 items to dataFactory and it is broadcasted to and $rootScope.on is executed to update scope2.data.links to 7 items. However scope2.data.links is still set to 5 items. This is because when $rootScope.on is executed first time the "$scope" variable within the "on" function refers to closure scope i.e scope1 and NOT scope2. So essentially when scope.data.links is set to 7 then scope.data.links is set to 7 and scope2.data.links is still set to 5.
Basically ng-view creates a new scope and if directive is part of each of the views, you would always end up having different data.link value in each of the views.
Solution:
You can fix it in two ways:
Option 1: You would be better off setting the value in scope as soon the promise is resolved instead of setting in factory and getting from it in $on listener. Atleast in this case.
http://plnkr.co/edit/IdrsO1OT9zDqdRiaSBho?p=preview
Option 2: If broadcast is really essentially I think you would have to bind the data.link to rootscope (which might not be a good practice).
http://plnkr.co/edit/VptbSKRf7crU3qqNyF3i?p=preview
and may be there are other options...

Related

Evaluate or call directive on click in angular

I am trying to load an image from json and if image is not available, then show firstname and lastname.
I have controller like this:
app.controller('task1Controller',['$scope', 'taskFactory', '$state', 'imageTestService', function($scope, taskFactory, $state, imageTestService){
$scope.taskData = {};
$scope.current = 0;
taskFactory.get().then(function(response){
$scope.jsonData = response.data.data.resultCareGivers;
});
$scope.back = function(){
$scope.current = ($scope.current !== 0 ? $scope.current - 1 : 0);
};
$scope.next = function(){
$scope.current = ($scope.current !== $scope.jsonData.length-1 ? $scope.current + 1 : $scope.jsonData.length-1);
};
}]);
and a Directive to verify image loading:
app.directive('imageTestDirective', function($http){
return {
restrict: 'A',
link: function($scope, elem, attrs){
attrs.$observe('ngSrc', function(ngSrc){
if(ngSrc != null && ngSrc != ""){
$http.get(ngSrc).then(function(success){
$scope.noImage = false;
console.log('success loading image', success);
}, function(error){
$scope.noImage = true;
console.log('error loading image', error);
});
}
});
}
};
});
Html with attribute directive and next and back button to cycle through json:
<img image-test-directive ng-show="noImage === false" ng-src="{{jsonData[current].profilepic}}" alt=""/>
<div ng-if="noImage">
<div>{{jsonData[current].firstName.charAt(1)+jsonData[current].lastName.charAt(1)}}</div>
</div>
<div class="col-xs-12">
<div class="col-xs-2">
<button type="button" ng-click="back()">Back</button>
</div>
<div class="col-xs-6" style="text-align: right">
<button type="button" ng-click="next()">Next</button>
</div>
</div>
The problem is the directive works on page load and the image is loaded properly, but I when I navigate through json object to view details, the directive is not evaluated (I mean when there no image inside json, it should show firstName+lastName)
How do I achieve it?
I think you wrote the logic too complicated for this use case.
In basic words JSON you get from Server contains some data with/without image URL or with broken image URL.
So instead to make HTML to be complicated, just embed your JSON in service and bring new JSON to your controller.
for example:
app.service('SomeService',['$q', /* ... */ function ($q /* ... */) {
function MyNewJSON(origJSON){
// check here if origJSON contains wrong image url
// and set new JSON key hasImage = true or false by validating it here in service and not in directive.
this.hasImage = true;
/* ... */
}
function getNewJSON(){
return new MyNewJSON(origJSON); // it might be promise and you need resolve it in controller
}
}]);
So your HTML should look like:
<img ng-if="stateData.hasImage" ng-src="stateData.profilepic" alt=""/>
<div ng-if="!stateData.hasImage">
<div >{{stateData.firstName.charAt(1)+stateData.lastName.charAt(1)}}</div>
</div>
No directive needed.
Since image validation can take some time, you can put default image (some kind of placeholder)

How can I update a variable from an AngularJS view?

What I want
I have 3 views. All views have their own controller. The first view is home. From the home view the user goes to view 2 by clicking on a div element. On view 2 the user opens view 3 by clicking on a button. On view 3 the user clicks on a button and goes back to view 2.
The problem I am facing is that I want to know if the user came from view 2. In that case I want to show different content then when the user came from the home view.
Create another view
Can it be done without creating another view?
My try
I created a service that keeps track of if I came from view 3, but the controller of view 2 isn't executed anymore after view 2 got opened from the home view. So basicly $scope.fromViewThree isn't updated and still false.
I added $route.reload() before $window.location = "#/app/viewtwo"; because I thought it would reinitialise the controllers(source) and then $scope.fromViewThree should have been updated. I also tried adding it below $window.location = "#/app/viewtwo";.
Controller view 2
.controller('ViewTwoCtrl', function($scope, $window, fromViewThree) {
$scope.fromViewThree = fromViewThree.getBoolean();
fromViewThree.setBoolean(false);
$scope.goToViewThree = function() {
$window.location = "#/app/viewthree";
};
})
Controller view 3
.controller('ViewThreeCtrl', function($scope, $window, fromViewThree) {
$scope.goToViewTwo = function() {
fromViewThree.setBoolean(true);
$window.location = "#/app/viewtwo";
};
})
Directives.js
.service('fromViewThree', function () {
var b = false;
return {
getBoolean: function() {
return b;
},
setBoolean: function(value) {
b = value;
}
};
})
HTML view 2
<div ng-if="fromViewThree == false">
<p>You came from view home!</p>
</div>
<div ng-if="fromViewThree == true">
<p>You came from view three!</p>
</div>
<div>
<button ng-click="goToViewThree()" ng-if="fromViewThree == false">Go to view 3</button>
<button ng-click="goToViewThree()" ng-if="fromViewThree == true">Go again to view 3</button>
</div>
HTML view 3
<div class="row">
<button class='button' ng-click="goToViewTwo()">Lets go to view two!</button>
</div>
Try implementing the views and controllers using the UI router. Once you have the states setup, accessing the previous state will be easy Angular - ui-router get previous state
Solution
Manu Antony pushed me in the right direction towards $rootScope(more info). I added code in app.js which stores the previous state/view name into $rootScope.fromViewThree. I can now access the previous state/view name in the HTML of view 2 and the previous state/view name will be updated when switching state/view has been successful.
Warning:
All scopes inherit from $rootScope, if you have a variable
$rootScope.data and someone forgets that data is already defined
and creates $scope.data in a local scope you will run into problems.
Controller view 2
.controller('ViewTwoCtrl', function($scope, $window) {
$scope.goToViewThree = function() {
$window.location = "#/app/viewthree";
};
})
Controller view 3
.controller('ViewThreeCtrl', function($scope, $window) {
$scope.goToViewTwo = function() {
$window.location = "#/app/viewtwo";
};
})
Directives.js
I no longer need the service because I use $rootScope now to monitor which view is my previous view.
HTML view 2
<div class="row" ng-if="fromViewThree != 'app.viewthree'">
<p>You came from view home!</p>
</div>
<div class='row' ng-if="fromViewThree == 'app.viewthree'">
<p>You came from view three!</p>
</div>
<div class="row">
<button id="activateCameraBtn" class='button' ng-click="goToViewThree()" ng-if="fromViewThree != 'app.viewthree'">Go to view 3</button>
<button id="activateCameraBtn" class='button' ng-click="goToViewThree()" ng-if="fromViewThree == 'app.viewthree'">Go again to view 3</button>
</div>
HTML view 3
The HTML for view 3 hasn't changed.
App.js
angular.module('myApp', [])
.run(function($rootScope) {
$rootScope.$on('$stateChangeSuccess', function (ev, to, toParams, from, fromParams) {
$rootScope.fromViewThree = from.name; //e.g. app.home
});
})
....

Three condition button based on Angular

I am fairly new to Angular an I am feeling lost in all of it's documentation.
Problem:
I am trying to create a button which has three phases:
Add User - Remove Request - Remove User
So if you want to add a user you click on the Add button, which
sends an ajax request to the server and if successful the button
should then turn into a Pending button.
In the pending state if you click on it again, your request will be
deleted and it will again turn back to a Add button.
The third phase is also if the user has accepted your request, you
will be seeing a Remove user button which when you click on
you will again see the Add button which if you click you will get
the Pending button and so forth.
So basically it is a familiar button if you've been using social networks.
When the page is loaded the user will see the users and the buttons for each user based on it's current condition (so the server will be handling this part). From this part Angular should handle the ajax calls and changing of the button per user connection request.
What I need:
I have done the Ajax part for sending the request. However I can't manage to handle the part which Angular needs to change the button to it's new state (for a specific user on the list, meaning the list has more than 1 user which you can send connection add/pending/delete requests.) I have tried different solutions but failed till now.
Some of my messy failure code which I have left unfinished:
Angular Controller:
foundationApp.controller('ConnectionButtonCtrl', function ($scope, $http) {
$scope.addUser = function(id) {
$http({
method : 'GET',
url : '/api/connections/add/'+id,
dataType: "html",
})
.success(function() {
$scope.activeId;
$scope.activeId = id;
$scope.isAdd = function(id){
return $scope.activeId === id;
};
})
};
$scope.removeRequest = function(id) {
$http({
method : 'GET',
url : '/api/connections/removeRequest/'+id,
dataType: "html",
})
.success(function() {
})
};
});
Laravel Blade View:
<span ng-controller="ConnectionButtonCtrl" >
<a class="label radius fi-plus" ng-show="!isRemove(1)" ng-click="addUser(1)"></a>
<a class="label radius fi-clock info" ng-show="isRemove(1)" ng-click="removeRequest(1)"></a>
<a class="label radius fi-x alert" ng-show="!isAdd(1)" ng-click="removeUser(1)"></a>
</span>
If I understand correctly, just use $index or user.id. I am assuming your buttons are on the same line as the user. If that's true then you are probably using an ng-repeat.
For example:
<div ng-repeat="user in users">
<a class="label radius fi-plus" ng-show="!isRemove(user.id)" ng-click="addUser(user.id)"></a>
<a class="label radius fi-clock info" ng-show="isRemove(user.id)" ng-click="removeRequest(user.id)"></a>
<a class="label radius fi-x alert" ng-show="!isAdd(user.id)" ng-click="removeUser(user.id)"></a>
<div> some user information {{user.name}} </div>
</div>
Then you can pass the id of the user with your ajax request. You can also use $index (as a parameter in my code instead for the index of the user in the array).
DEMO: http://plnkr.co/edit/hhOdNTV6ogJHhtXcM03a?p=preview
js
var app = angular.module('myApp', []);
app.controller('myController', function ($scope) {
$scope.users = {
user1: {
'status': 'add',
'statusClass': 'positive'
},
user2: {
'status': 'pending',
'statusClass': 'waiting'
},
user3: {
'status': 'remove',
'statusClass': 'negative'
}
};
$scope.handle = function (user) {
if (user.status === 'add') {
alert('send request to the user');
user.status = 'pending';
user.statusClass = 'waiting'
}
else if (user.status === 'pending') {
alert('send request to discard a connection req');
user.status = 'add';
user.statusClass = 'positive'
}
else {
alert('send req for removal');
user.status = 'add';
user.statusClass = 'positive'
}
};
});
app.$inject = ['$scope'];
HTML:
<body ng-app="myApp" ng-controller="myController">
<div ng-repeat="user in users">
User {{$index+1}} - <button ng-click="handle(user)" ng-class="user.statusClass">{{ user.status }}</button>
</div>
</body>
http://plnkr.co/edit/hhOdNTV6ogJHhtXcM03a?p=preview

How to automatically throw up a message when "Angular" {{variable}} disappears after Session DIES

I have an Angular app, the problem is, that when the {{controllername.name}} disappears for displaying the username, after session timeout, even though the warning for ngIdle comes up, the user can still refresh the screen and it keeps you on the page not taking you BACK to the login page.
The {{ctrlDash.userinfo.name}} disappears after 20 min. (See Below)
<ul class='nav'>
<li class='dropdown dark user-menu'>
<a class='dropdown-toggle' data-toggle='dropdown' href='#'>
<img width="23" height="23" alt="" src="assets/images/avatar.jpg" />
<span class='user-name'>{{ctrlDash.userInfo.name}}</span>
<b class='caret'></b>
</a>
<ul class='dropdown-menu'>
<li>
<a href='user_profile.html'>
<i class='icon-user'></i>
Profile
</a>
</li>
<li>
<a href='user_profile.html'>
<i class='icon-cog'></i>
Settings
</a>
</li>
<li class='divider'></li>
<li>
<a href='sign_in.html' target="_self">
<i class='icon-signout'></i>
Sign out
</a>
</li>
</ul>
</li>
</ul>
So, now, I want this feature in an template to "DETECT" when that happens and force the user to login again;
This is the ng-template on the same page at the bottom:
<!-- Templates for Modals -->
<script type="text/ng-template" id="warning-dialog.html">
<div class="modal-header">
<h3>You're Idle. Do Something!</h3>
</div>
<div class="modal-body" idle-countdown="countdown" ng-init="countdown=5">
<p>You'll be logged out in <span class="label label-warning">{{countdown}}</span> <span ng-pluralize="" count="countdown" when="{'one': 'second', 'other': 'seconds' }"></span>.</p>
<progressbar max="20" value="countdown" animate="true" class="progress-striped active" type="warning"></progressbar>
</div>
<div class="modal-footer">
Quick! Move your mouse and your session will reset...
</div>
</script>
<script type="text/ng-template" id="timedout-dialog.html">
<div class="modal-header">
<h3>Oh, Snap! You've Timed Out!</h3>
</div>
<div class="modal-body">
<p>
You were idle too long. Click the button below to be redirected to the login page and begin again.
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger btn-small" data-ng-click="goBack()">Back To Login</button>
</div>
</script>
<!-- End Templates for Modals -->
First the TIMER detects IDLE and then the WARNING pops up and tells the user, OOPS, you need to login. But, when I hit refresh, it refreshes the page, but the {{ctrlDash.userInfo.name}} is now empty.
This is the code for ngIdle
//This is the IDLE function
$scope.started = false;
$scope.ended = false;
$scope.events = [];
$scope.idle = 20; //this is in ACTUAL seconds
$scope.timeout = 20; //this is in ACTUAL seconds
function closeModals() {
if ($scope.warning) {
$scope.warning.close();
$scope.warning = null;
}
if ($scope.timedout) {
$scope.timedout.close();
$scope.timedout = null;
}
}
$scope.$on('IdleStart', function () {
closeModals();
$scope.warning = $modal.open({
templateUrl: 'warning-dialog.html',
windowClass: 'modal-danger'
});
});
$scope.$on('IdleEnd', function () {
closeModals();
});
$scope.$on('IdleTimeout', function () {
closeModals();
$scope.timedout = $modal.open({
templateUrl: 'timedout-dialog.html',
windowClass: 'modal-danger'
});
});
$scope.start = function () {
closeModals();
Idle.watch();
$scope.started = true;
};
$scope.stop = function () {
closeModals();
Idle.unwatch();
$scope.started = false;
};
if(!angular.isDefined($scope.goBack)) {
console.log("I\'m not defined...");
if(!angular.isFunction($scope.goBack)) {
console.log("I\'m not a function...")
}
}
$scope.goBack = function _goBack() {
closeModals();
Idle.unwatch();
$window.location.href = $scope.templateViews.logout;
};
Finally: The goBack() function, within the controller = dashboardController, throws an error
Unreferenced error, goBack is NOT DEFINED.
Those are my issues. Would love to assistance, please. Thanks everyone.
I'm developing my first angular app, so not a master by any means.. I implemented a logout functionality. When the user attempts to go to any page after logging out, the controller checks for the presence of credentials, if none present, they get sent back to the login page with:
`$location.path('/login');`
--Updated from comment
I have 2 service modules (with factories). 1 - communicates with REST endpoints, 2 - deals with all my business stuff. When a user logs in, on success, I pass along the user's info to the setCreds function.
var businessService = angular.module('businessService, ['ngCookies' ]);
businessService.factory('setCreds', ['$cookies', function ($cookies) {
return function(un, pw, userRole) {
var token = un.concat(":", pw);
$cookies.creds = token;
$cookies.usersRole = userRole;
Then, the first thing I check on all my controllers, before getting any info needed for a view, is checkCreds.
if (!checkCreds()) {
$location.path('/login');
} else { ..proceed with getting stuff
My checkCreds looks like:
businessService.factory('checkCreds', ['$cookies', function ($cookies) {
return function () {
var returnVal = false;
var creds = $cookies.creds;
if (creds !== undefined && creds !== "") {
returnVal = true;
}
return returnVal;
};}]);
Be sure to inject your businessService into your app, and the service factory you want to use into your controller.

AngularJS directive - ng-class in ng- repeat should it be a $watcher to toggle style?

I am currently implementing a spike to further my understanding on angular directives etc.
The premise is to create a FX watch list on a number of currency pairs.
My data feed is set up for my price updates via socket.io.
The stumbling block that i have is being able to change the css dependent on price change ie up arrow for up, down arrow for down.
I feel a watcher function is what i need but struggled on where to start so was looking for some sort of expression in ng-class to do the job ... but the method not only started to look like a $watcher it was also flawed as saving the previous price to scope on my directive meant there was only ever one old value not one for each price.
There for my question is : Is the solution with ng-class or in setting up a $watcher function ?
Heres my code ...
HTML template
<div ng-repeat="rate in rates" ng-click="symbolSelected(rate)">
<div class="col-1-4">
{{rate.symbol}}
</div>
<div class="col-1-4">
<span ng-class='bullBear(rate.bidPoint)' ></span> {{rate.bidBig}}<span class="point">{{rate.bidPoint}}</span>
</div>
<div class="col-1-4">
<span ng-class='bullBear(rate.offerPoint)' ></span> {{rate.offerBig}}<span class="point">{{rate.offerPoint}}</span>
</div>
<div class="col-1-4">
{{rate.timeStamp | date : 'hh:mm:ss'}}
</div>
</div>
My directive currently looks like this ... as noted this will not work and the bullBear method was starting to look like a $watcher function.
.directive('fxmarketWatch', function(fxMarketWatchPriceService){
return {
restrict:'E',
replace:'true',
scope: { },
templateUrl:'common/directives/fxMarketWatch/marketwatch.tpl.html',
controller : function($scope, SYMBOL_SELECTED_EVT,fxMarketWatchPriceService){
$scope.symbolSelected = function(currency){
$scope.$emit(SYMBOL_SELECTED_EVT,currency);
}
$scope.bullBear = function(newPrice){
if ($scope.oldPrice> newPrice ){
return ['glyphicon glyphicon-arrow-down','priceDown'];
}
else if ($scope.oldPrice > newPrice ){
return ['glyphicon glyphicon-arrow-up','priceUp'];
}
}
$scope.$on('socket:fxPriceUpdate', function(event, data) {
$scope.rates = data.payload;
});
}
}
})
You could modify the ng-class and move the logic into the view, because styling and placing classes shouldn't be done in code.
<div class="col-1-4">
<span class="glyphicon" ng-class="{'glyphicon-arrow-up priceUp': oldPrice > rate.bidPoint, 'glyphicon-arrow-down priceDown':oldPrice > rate.bidPoint}"></span> {{rate.bidBig}}<span class="point">{{rate.bidPoint}}</span>
</div>
Or like this:
<span class="glyphicon {{oldPrice > rate.bidPoint ? 'glyphicon-arrow-down priceDown':'glyphicon-arrow-up priceUp'}}></span> {{rate.bidBig}}<span class="point">{{rate.bidPoint}}</span>
I will recommend you to use both ng-class and $watcher. The two can actually compliment each other:
UPDATE: To make the code works with ng-repeat, we need to migrate all of CSS classes logic to another controller:
app.controller('PriceController', function($scope) {
// we first start off as neither up or down
$scope.cssBid = 'glyphicon';
$scope.cssOffer = 'glyphicon';
var cssSetter = function(newVal, oldVal, varName) {
if (angular.isDefined(oldVal) && angular.isDefined(newVal)) {
if (oldVal > newVal) {
$scope[varName] = 'glyphicon glyphicon-arrow-down priceDown';
} else if (newVal > oldVal) {
$scope[varName] = 'glyphicon glyphicon-arrow-up priceUp';
} else {
$scope[varName] = 'glyphicon';
}
}
};
// watch for change in 'rate.bidPoint'
$scope.$watch('rate.bidPoint', function(newVal, oldVal) {
cssSetter(newVal, oldVal, 'cssBid');
});
// watch for change in 'rate.offerPoint'
$scope.$watch('rate.offerPoint', function(newVal, oldVal) {
cssSetter(newVal, oldVal, 'cssOffer');
});
});
Next, we bind this PriceController onto ng-repeat div. By doing so, Angular will create one controller instance for each rate in rates. So this time rate.bidPoint and rate.offerPoint should be available for $watch-ing:
<div ng-repeat="rate in rates" ng-click="symbolSelected(rate)" ng-controller="PriceController">
<div class="col-1-4">
<span ng-class='cssBid'></span> {{rate.bidBig}}<span class="point">{{rate.bidPoint}}</span>
</div>
<div class="col-1-4">
<span ng-class='cssOffer'></span> {{rate.offerBig}}<span class="point">{{rate.offerPoint}}</span>
</div>
</div>
Now, directive's controller will be much shorter than before:
controller: function($scope, SYMBOL_SELECTED_EVT, fxMarketWatchPriceService){
$scope.symbolSelected = function(currency) {
$scope.$emit(SYMBOL_SELECTED_EVT, currency);
}
$scope.$on('socket:fxPriceUpdate', function(event, data) {
$scope.rates = data.payload;
});
}

Categories

Resources