Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS : use a variable into <div>

i have a controller named "HomeCtrl" which calculates the total number of user's into the {{total}} binding variable, like this:

.controller('HomeCtrl', function($scope, $http){
    $scope.total = 0;
});

In my view, I am trying to display my total in an animated widget by passing {{total}} as the value of an attribute on a <div> tag, like this:

<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 of {{total}} in my view, but when I pass {{total}} into the attribute, as data-to= "{{total}}", it does not work. It doesn't recognize it as a number.

like image 780
Alaa-GI Avatar asked Dec 17 '14 08:12

Alaa-GI


People also ask

What is ng repeat?

Definition and Usage The ng-repeat directive repeats a set of HTML, a given number of times. The set of HTML will be repeated once per item in a collection. The collection must be an array or an object. Note: Each instance of the repetition is given its own scope, which consist of the current item.

What does ng click do?

The ng-click Directive in AngluarJS is used to apply custom behavior when an element is clicked. It can be used to show/hide some element or it can pop up an alert when the button is clicked.

What is controller in Angular 8?

AngularJS applications are controlled by controllers. The ng-controller directive defines the application controller. A controller is a JavaScript Object, created by a standard JavaScript object constructor.


2 Answers

This works for me: The Number is retrieved using a async webservice call when the controller loads. That means the value isn't there when the sm.fullyEnteredViewport function is called. But luckily you can set a data-delay attribute on 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 modify your directive like this: Retrieve the delay value from element and put the rest of the other code into the delayed function like this:

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();
            });
        }
    };
}).
Your webservice should return within the delay time. That does the trick for me.
like image 136
Helmut Obertanner Avatar answered Oct 28 '22 15:10

Helmut Obertanner


You have to distinguish, because if you are just using {{total}} in your directive template it works, because angular automatically will 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 value of total in an isolated scope, you can bind to your data-to attribute, and this is achieved by following code:

app.directive('xeCounter', function(){
 return {
    restrict: 'EA',
    scope: { to: '@' },
    link: function(scope)
    {
        console.log(scope.to);
    }
 };
});

Btw. I changed the restrict from EAC to EA, because otherwise your directive is going to be applied twice and breaks. And you have to put the asterisks around the attribute value.

See the full working example here.

like image 31
Manuel B. Avatar answered Oct 28 '22 14:10

Manuel B.