【问题标题】:observe a click event in a directive观察指令中的点击事件
【发布时间】:2015-10-07 12:41:35
【问题描述】:

在我的控制器的原始版本中,我在 dom 中添加了一个标头徽标,然后能够在调用函数时将其删除并替换为其他内容,就像这样

    $scope.addHeader('.blahClassName');

    $scope.removeHeaderFunction = function(){
          $('.blahClassName).html('');
          //do other stuff
    }

这很好用。但是,我读到最好不要在控制器中进行 DOM 操作,因此我创建了这样的指令

<div class='MyCtrl as vm'>
 <div header-dir myscope="vm" removeheaderflag="{{vm.headerflag}}"></div>

然后,在我的指令的链接函数中,我添加标题标志并监听标志的变化以将其删除,就像这样

  link: function(scope, elem, attrs){

       scope.myscope.addHeader('.blahClassName'); //calling the function addHeader on the controller available through myscope

       attrs.$observe('removeheaderflag', function(){
           angular.element(elem[0].querySelector('.blahClassName')).html('');
       });         
  }

然后在控制器中,我在页面加载时设置$scope.headerflag = null;,并在removeHeaerFunction 中将其设置为true,目的是仅当标志设置为true 时才会删除标题

 $scope.removeHeaderFunction = function(){
    $scope.headerflag = true;
  }

但是,我的代码的实际行为是立即添加和删除徽标,无论 $scope.headerflag 设置为什么。也就是说$attrs.observe('removeheaderflag', ...里面的代码是立即运行的。

问题:如何在该观察者中延迟代码的运行或以其他方式从指令中获得我想要的行为,即基本上能够在点击事件中删除某些内容

【问题讨论】:

  • 您使用的是标准点击事件还是 ng-click?听起来您没有从角度生命周期内设置控制器值,因此更改不会立即反映。

标签: javascript html angularjs angularjs-directive dom-manipulation


【解决方案1】:

$observe$watch 的工作方式相同,两者之间的唯一区别是 $observe 适用于插值表达式 {{}}$watch 适用于作为字符串的范围值。

目前发生的情况是,当您的变量 removeheaderflagundefinednull 时,您的 $observe 函数被调用,所以在这种情况下,$observe 回调函数被调用,您的 blahClassName 类被删除DOM。为了限制这种行为,您应该添加条件以在 removeheaderflag 将值更改为 true 时调用您想要的代码

代码

attrs.$observe('removeheaderflag', function(newVal, oldValue){
  if(newVal) //this will check values in not null & not false
   angular.element(elem[0].querySelector('.blahClassName')).html('');
});   

【讨论】:

  • 我以为我们只有$watch 中的newValueoldValue 的句柄,而$observe 只会为我们提供价值
  • 谢谢。您是否同意这种在控制器上设置状态并监听/观察指令中状态的变化然后进行 dom 操作的方法?
  • @Leahcim 我更喜欢在那里使用ng-class..将根据ng-class="{'blahClassName': headerflag}"等模型更改添加类
  • 但是我可以监听类变化并触发 dom 事件吗?
  • @Leahcim 虽然我提供了类似的答案来解决这个问题,但我也会考虑使用class="ng-hide"ng-show="removeheaderflag"。除非您需要完全移除 DOM 节点。 ng-if 也可能是另一种方法
【解决方案2】:

您能否检查您的$observe 中的返回值是否为您希望的值——在本例中为true?观察以下变化...

attrs.$observe('removeheaderflag', function(value) { // -- we know this
    if(value) {
        angular.element(elem[0].querySelector('.blahClassName')).html('');
    } 
}); 

此外,根据 cmets 中的讨论,您也许可以为此采取替代方法。由于您的 DOM 操作很简单(在此示例中),因此利用 ngClass 并允许 CSS 为我们处理这可能是一个可行的解决方案。为什么不将headerflag 绑定到具有display: none 规则的类?一个例子可能包括......(在这里就标记而言,这是一个例子)......

<header class="blahClassName" ng-class="{'remove': headerflag}">header</header>

.remove {
    display: none;
}

$scope.remove = function() {
    $scope.headerflag = true;
}

JSFiddle Link - ngClass 示例

ngIf 等其他方法也可能适用于此。也许您不需要自定义指令来完成此操作。

【讨论】:

  • 我打败了你 16 秒 :p
  • 也谢谢你@salniro(我给了你们两个赞成票,但会接受 PankajParker 的回答,因为他是第一个)。 .您是否同意这种在控制器上设置状态并监听/观察指令中状态的变化然后进行 dom 操作的方法?
  • @salniro 是的。在我们添加答案的地方,这确实是非常小的差异。我们都在 OP 问题上找到了一个很好的答案:)
  • 由于打开的对话框而评论了相邻的答案。看看这些建议是否有价值?
  • @Leahcim 我添加了一些可能对此有用的替代想法。请检查一下,让我知道你的想法
猜你喜欢
  • 1970-01-01
  • 2016-10-12
  • 1970-01-01
  • 1970-01-01
  • 2011-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多