9

I try to write loader with AngularJS by using directive and spin.js (that doesn't use jQuery).

I know that AngularJS has own jQuery lite. However I can't fetch width from element in directive.

Basically I need get button width (inside directive)

I tried so far:

element[0].width  // < - error
angular.element(element[0]).css('width')  // < - undefined

Here we go:

Demo in Plunker

HTML

 <button type="submit" loader left="5" ng-click="loadData()" >Load Data</button>

JS

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope, stockData, $timeout) {


  $scope.loadData = function(){

    $scope.init();

            stockData.query()
                        .then(function (result) {
                        $timeout(function () {
                            $scope.data = result.data;

                            $scope.stop();
                            return result.data;
                        }, 3000);
                    }, function (result) {
                        alert("Error: No data returned");
                    });   
               }
      });


app.directive('loader', ['$parse',  'stockData', '$timeout', function ($parse, stockData, $timeout) {

    return {
        restrict: 'A',
        link: function (scope, element, attr) {

            var spinner;

             var opts = {
                lines: 13, // The number of lines to draw
                length: 3, // The length of each line
                width: 2, // The line thickness
                radius: 7, // The radius of the inner circle
                corners: 1, // Corner roundness (0..1)
                rotate: 0, // The rotation offset
                direction: 1, // 1: clockwise, -1: counterclockwise
                color: '#000', // #rgb or #rrggbb or array of colors
                speed: 1.3, // Rounds per second
                trail: 60, // Afterglow percentage
                shadow: false, // Whether to render a shadow
                hwaccel: false, // Whether to use hardware acceleration
                className: 'spinner', // The CSS class to assign to the spinner
                zIndex: 2e9, // The z-index (defaults to 2000000000)
                top: 'auto', // Top position relative to parent in px
                left: 'auto' // Left position relative to parent in px
            };


               target = element[0];

              scope.init = function(){
               attr.$set('disabled', true);


             if(attr['left'] != undefined){

               var left_ = parseInt(attr['left']);

             console.log(element[0].width); // < - error
             console.log(angular.element(element[0]).css('width')); // < - undefined


               if(left_ >= 0){
                 //opts.left = element.width() + parseInt(attr['left']);
               }
               else{
                // opts.left =  -element.width()/2  + parseInt(attr['left']);
               }
             }  

               spinner = new Spinner(opts).spin(target);
            }; 

            scope.stop =  function(){
              attr.$set('disabled', false);
              spinner.stop();
            };
        }
    };
}]);


app.factory('stockData', ['$http', '$q', function ($http, $q) {

    var factory = {
        query: function () {
             // dummy call
            var data = $http.get('http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22YHOO%22)%0A%09%09&env=http%3A%2F%2Fdatatables.org%2Falltables.env&format=json');
            var deferred = $q.defer();
            deferred.resolve(data);
            return deferred.promise;
        }

    }
    return factory;
}]);

Thank you,

3 Answers 3

20

Use element[0].offsetWidth

.css('width') will be undefined as you don't have any inline CSS defining the width, and .width is a jQuery thing.

angular.element uses a 'jqLite' if jQuery isn't available, which only offers a subset of the functionality. Computed CSS style is not one of these things (and won't be any time soon due to performance implications).

There's a decent reference for what you can do without jQuery here

Sign up to request clarification or add additional context in comments.

2 Comments

Isn't this a getter though? In jQuery you can get style properties with .css( propertyName )
In jQuery, yes, but angular's jqlite doesn't support this due to it being a fairly expensive operation to perform. See this comment for more information. JQLite only returns inline style with .css(..)
6

element[0].getBoundingClientRect() is another powerful API.

You can get bottom, height, left, right, top, width by calling:

element[0].getBoundingClientRect()

Comments

2

For those of you interested in retrieving an arbitrary CSS property, you can access the CSS style of an Angular element in a directive's link function by

var style = window.getComputedStyle(element[0]),

And then access the value of any CSS rule like such:

var color = style.getPropertyValue('color');

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.