AngularJS: use the variable in the <div>
I have a controller named "HomeCtrl" that calculates the total number of users in the {{total}}
binding variable, for example:
.controller('HomeCtrl', function($scope, $http){ $scope.total = 0; });
In my opinion, I'm trying to show my total amount in an animated widget by passing {{total}}
as the attribute value in the <div>
, for example:
<div ng-controller="HomeCtrl" ng-init="init('users')"> <div class="xe-widget xe-counter xe-counter-green" xe-counter data-count=".num" data-from="1" data-to= "{{total}}" data-suffix="users" data-duration="3" data-easing="true"> <div class="xe-icon"> <i class="linecons-user"></i> </div> <div class="xe-label"> <strong class="num">1k</strong> <span>Users Total </span> </div> </div> <center> <b> Total utilisateurs : {{total}} </b> </center>
Here is the widget directive:
.directive('xeCounter', function(){ return { restrict: 'EAC', link: function(scope, el, attrs) { var $el = angular.element(el), sm = scrollMonitor.create(el); sm.fullyEnterViewport(function() { var opts = { useEasing: attrDefault($el, 'easing', true), useGrouping: attrDefault($el, 'grouping', true), separator: attrDefault($el, 'separator', ','), decimal: attrDefault($el, 'decimal', '.'), prefix: attrDefault($el, 'prefix', ''), suffix: attrDefault($el, 'suffix', ''), }, $count = attrDefault($el, 'count', 'this') == 'this' ? $el : $el.find($el.data('count')), from = attrDefault($el, 'from', 0), to = attrDefault($el, 'to', ''), duration = attrDefault($el, 'duration', 2.5), delay = attrDefault($el, 'delay', 0), decimals = new String(to).match(/\.([0-9]+)/) ? new String(to).match(/\.([0-9]+)$/)[1].length : 0, counter = new countUp($count.get(0), from, to, decimals, duration, opts); setTimeout(function(){ counter.start(); }, delay * 1000); sm.destroy(); }); } }; })
I can display the correct value {{total}} in my view, but when I pass {{total}}
to an attribute like data-to= "{{total}}"
, it does not work. He does not recognize it as a number.
This works for me: The number is retrieved using the async webservice call when the controller boots. This means that the value does not exist when the sm.fullyEnteredViewport function is called. But, fortunately, you can set the data delay attribute in the xe-counter element.
<div class="xe-widget xe-counter" xe-counter data-delay="1" data-count=".num" data-from="0" data-to="{{ total }}" data-suffix="" data-duration="5"> <div class="xe-icon"><i class="linecons-cup" /></div> <div class="xe-label"><strong class="num">0</strong><span>TOTAL</span></div> </div>
Then change your directive as follows: Extract the delay value from the element and put the rest of the other code in the delayed function as follows:
directive('xeCounter', function () { return { restrict: 'EAC', link: function (scope, el, attrs) { var $el = angular.element(el), sm = scrollMonitor.create(el); //get the delay attribute from element var delay = attrs.delay ? attrs.delay : 0; sm.fullyEnterViewport(function () { setTimeout(function () { // get all values from element delayed and start the counter var opts = { useEasing: attrDefault($el, 'easing', true), useGrouping: attrDefault($el, 'grouping', true), separator: attrDefault($el, 'separator', ','), decimal: attrDefault($el, 'decimal', '.'), prefix: attrDefault($el, 'prefix', ''), suffix: attrDefault($el, 'suffix', '') }, $count = attrDefault($el, 'count', 'this') == 'this' ? $el : $el.find($el.data('count')), from = attrs.from ? attrs.from : 0, to = attrs.to ? attrs.to : 100, duration = attrs.duration ? attrs.duration : 2.5, decimals = String(to).match(/\.([0-9]+)/) ? String(to).match(/\.([0-9]+)$/)[1].length : 0, counter = new countUp($count.get(0), from, to, decimals, duration, opts); counter.start(); }, delay * 1000); sm.destroy(); }); } }; }).
You have to distinguish, because if you just use {{total}} in your directive template, it works, because angular will automatically look for total in the parent controller if it is not found in the local one.
On the other hand, if you want to use the total value in an isolated scope, you can bind to the data-to attribute, and this is achieved using the following code:
app.directive('xeCounter', function(){ return { restrict: 'EA', scope: { to: '@' }, link: function(scope) { console.log(scope.to); } }; });
Btw. I changed the restriction from EAC to EA, because otherwise your directive will be applied twice and broken. And you have to put asterisks around the attribute value.
See the full working example here .
This works for me.
Replace your directive for this:
directive('xeCounter', function () { return { restrict: 'EAC', link: function (scope, el, attrs) { var $el = angular.element(el), sm = scrollMonitor.create(el); sm.fullyEnterViewport(function () { var opts = { useEasing: attrDefault($el, 'easing', true), useGrouping: attrDefault($el, 'grouping', true), separator: attrDefault($el, 'separator', ','), decimal: attrDefault($el, 'decimal', '.'), prefix: attrDefault($el, 'prefix', ''), suffix: attrDefault($el, 'suffix', '') }, $count = attrDefault($el, 'count', 'this') == 'this' ? $el : $el.find($el.data('count')), from = attrs.from ? attrs.from : 0, to = attrs.to ? attrs.to : 100, duration = attrs.duration ? attrs.duration : 2.5, delay = attrs.delay ? attrs.delay : 0, decimals = String(to).match(/\.([0-9]+)/) ? String(to).match(/\.([0-9]+)$/)[1].length : 0, counter = new countUp($count.get(0), from, to, decimals, duration, opts); setTimeout(function () { counter.start(); }, delay * 1000); sm.destroy(); }); } }; }).
And the HTML should look like this:
<div class="xe-widget xe-counter" xe-counter data-count=".num" data-from="0" data-to="{{ total }}" data-suffix="" data-duration="5"> <div class="xe-icon"><i class="linecons-cup" /></div> <div class="xe-label"><strong class="num">0</strong><span>TOTAL</span></div> </div>
Make sure the variable $ scope.total is declared and its value is a number.