AngularJS DOM manipulation using existing directive

I am trying to learn the Angular way of adding a DOM element with data returned from the service passing it to a directive by changing the scope variable from my controller.

My service

.factory('Poller', function($http,$q){
           return {
                poll : function(api){
                    var deferred = $q.defer();
                    $http.get(api).then(function (response) {
                            deferred.resolve(response.data);
                    });
                    return deferred.promise;
                }

            }
        });

My Controller

.controller('accordion',['$scope','Poller','$timeout',function($scope,Poller,$timeout){
$scope.newdata = null;

function Repeater ()  {
     $scope.$apply(function () {
     Poller.poll('api/getupdates')
       .then(function(data){
           $scope.newdata = data;                                   
            });
        });
     };
    $timeout(Repeater, 1000) ;             
    var timer = setInterval(Repeater, 11000);  

My Directive

.directive( 'newreading', function () {
  return {
    scope: {'newdata' : '='},
    templateURL : 'templatenewreading.html',
    link: function ( scope, element, attrs ) {
      var el;

      scope.$watch('newdata', function () {

          console.log(scope.newdata);

      });
    }
  };
}); 

HTML //NOTE: this is done by ng-repeat

 <accordion-group id="Device 1">  
     <newreading ></newreading> 
 </accordion-group> 

 <accordion-group id="Device 2">  
     <newreading ></newreading> 
 </accordion-group>      

 <accordion-group id="Device3">  
     <newreading ></newreading> 
 </accordion-group>      

 <accordion-group id="Device4">  
     <newreading ></newreading> 
 </accordion-group> 

My Sample JSON

{
    "readings": [                    
            "id": "Device2",
            "T01": "3",
            "L02": "35"
    ]
}

Everything til here works fine, and I want to stay away from using jQuery at all (I know Angular has jQuery Lite)

My Question

Firstly, Is this the right approach to add an element to the DOM using Angular JS? If yes, how will I reuse this directive? Currently, scope.watch triggers the function 4 times (obviously!!).

I am too confused because I cannot find a simple way to trigger the right directive to add an element.

I have been through few parts of the documentation and found StackOverflow questions suggesting to compile and add elements, which I can do but I need to add the element in the required div.

Any help is much appreciated.


In your directive definition, you wrote scope: {'newdata' : '='} . What this will do is create an isolated scope where $scope.newdata is two-way bound to the attribute newdata of the newreading element.

So if your HTML doesn't say <newreading newdata="someVariableOnTheScope"></newreading> this doesn't make sense. I don't know on what scope your accordion controller operates, so I can't give you more specific advice.

It appears you don't need an extra directive for new readings since you're using the same template. You just want extra readings to be shown. So you should update the underlying model and your view will update itself. That's the magic of Angular.

The extra readings can be added as follows (assuming newData contains the new readings):

// create an object so you can lookup a device by id
var devicesById = _.indexBy($scope.data,'_id');
_.each(newData,function(device) {
  // add the new readings to the readings of the device with the correct id
  Array.prototype.push.apply(devicesById[device._id].readings,device.readings);
});

A plunkr: http://plnkr.co/edit/iKtmrToz4fkJ46bVfcjX

Some extra tips:

  • Don't write code in the link function if you don't need access to attrs or element . Do that in the controller of the directive
  • You only need to wrap your code in a $scope.$apply if you're doing things outside of the AngularJS scope. You're basically saying to Angular: I'm doing stuff in here that might have changed the DOM that you're aware of, sync again. This is mostly useful when also using other libraries (eg JQuery)
  • 链接地址: http://www.djcxy.com/p/95240.html

    上一篇: AngularJS使用ng隐藏任何父div

    下一篇: 使用现有指令的AngularJS DOM操作