简体   繁体   English

使用现有指令的AngularJS DOM操作

[英]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. 我正在尝试通过从控制器更改范围变量来学习使用从服务返回的数据添加DOM元素的Angular方法,并将其传递给指令。

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 : 'template\newreading.html',
    link: function ( scope, element, attrs ) {
      var el;

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

          console.log(scope.newdata);

      });
    }
  };
}); 

HTML //NOTE: this is done by ng-repeat HTML //注意:这是通过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 我的样本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) 到目前为止一切正常,我想远离使用jQuery(我知道Angular有jQuery Lite)

My Question 我的问题

Firstly, Is this the right approach to add an element to the DOM using Angular JS? 首先,这是使用Angular JS向DOM添加元素的正确方法吗? If yes, how will I reuse this directive? 如果是,我将如何重用此指令? Currently, scope.watch triggers the function 4 times (obviously!!). 目前,scope.watch触发函数4次(显然是!!)。

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. 我已经通过文档的几个部分,发现StackOverflow问题建议编译和添加元素,我可以做,但我需要在所需的div中添加元素。

Any help is much appreciated. 任何帮助深表感谢。

In your directive definition, you wrote scope: {'newdata' : '='} . 在您的指令定义中,您编写了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. 这将做的是创建一个隔离的范围,其中$scope.newdatanewreading元素的newdata属性双向绑定。

So if your HTML doesn't say <newreading newdata="someVariableOnTheScope"></newreading> this doesn't make sense. 因此,如果你的HTML没有说<newreading newdata="someVariableOnTheScope"></newreading>这没有意义。 I don't know on what scope your accordion controller operates, so I can't give you more specific advice. 我不知道你的accordion控制器的作用范围,所以我不能给你更具体的建议。

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. 这是Angular的神奇之处。

The extra readings can be added as follows (assuming newData contains the new readings): 额外的读数可以添加如下(假设newData包含新的读数):

// 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 一个傻瓜: 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 . 如果您不需要访问attrselement请不要在链接函数中编写代码。 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. 您只需将代码包装在$scope.$apply如果您在AngularJS范围之外执行操作,则需要$scope.$apply 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. 你基本上是对Angular说:我在这里做的事情可能已经改变了你所知道的DOM,再次同步。 This is mostly useful when also using other libraries (eg JQuery) 这在使用其他库(例如JQuery)时非常有用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM