【问题标题】:How to Send Variable to Parent Controller from Directive without Isolate Scope如何在没有隔离范围的情况下从指令向父控制器发送变量
【发布时间】:2019-01-11 06:40:39
【问题描述】:

如何在控制器 AngularJS 中观察指令中的变量?

我有一个带有控制器和指令的组件

在我的指令中,我正在监听滚动,如果元素在视图中则返回 true,否则返回 false。

我希望能够在控制器中访问我的boolChangeClass 变量,以便只有当它为真时才能调用我的函数。

我的问题是如何在控制器中访问boolChangeClass

    'use strict';
    
    angular.module('myModule')
      .component('myComponent', {
        template: `
          <div class="component" inview ng-class="{min: boolChangeClass}">
          </div>
        `,
    
        controller: function ($scope) {
          let $ctrl = this;

          let func = () => {console.log('my function')}

      $scope.$watch('boolChangeClass', func);
    }
  })
  .directive('inview', ($window) => {
    return function(scope, element, attrs) {
        angular.element($window).bind("scroll", function() {
          let rect = element[0].getBoundingClientRect();
          scope.boolChangeClass =  rect.bottom > 0 &&
              rect.right > 0 &&
              rect.left < (window.innerWidth || document.documentElement.clientWidth) &&
              rect.top < (window.innerHeight || document.documentElement.clientHeight)
          scope.$apply();
        });
    };
  })

【问题讨论】:

    标签: angularjs angularjs-directive angularjs-components


    【解决方案1】:

    tl;博士;

    从使用scope:false的指令向父控制器发送变量:

    <div on-scroll="$ctrl.fn($event)"></div>
    
    scope.$apply( () => {
        scope.$eval(attrs.onScroll, {$event: event});
    });
    

    回答

    不要使用ng-class 设置类,而是让指令设置类:

    <div class="component" inview-class="min"  ̶n̶g̶-̶c̶l̶a̶s̶s̶=̶"̶{̶m̶i̶n̶:̶ ̶b̶o̶o̶l̶C̶h̶a̶n̶g̶e̶C̶l̶a̶s̶s̶}̶" >
    </div> 
    
    app.directive('inviewClass', ($window) => {
      return function(scope, elem, attrs) {
        angular.element($window).on("scroll", function(event) {
          let rect = elem[0].getBoundingClientRect();
          let boolChangeClass =  rect.bottom > 0 &&
              rect.right > 0 &&
              rect.left < (window.innerWidth || document.documentElement.clientWidth) &&
              rect.top < (window.innerHeight || document.documentElement.clientHeight);
          let className = attrs.inviewClass;
          boolChangeClass ? elem.addClass(className) : elem.removeClass(className);
        });
      };
    })
    

    这避免了涉及 AngularJS 摘要循环、修改 $scope 和添加观察者。


    更新

    我应该在我的控制器中做什么?检查类是否存在,然后调用他的方法?

    使用属性指定滚动事件要调用的函数:

    <div class="component" inview-class="min" on-scroll="$ctrl.fn($event)" >
    </div> 
    
    app.directive('inviewClass', ($window) => {
      return function(scope, elem, attrs) {
        angular.element($window).on("scroll", function(event) {
          let rect = elem[0].getBoundingClientRect();
          let boolChangeClass =  rect.bottom > 0 &&
              rect.right > 0 &&
              rect.left < (window.innerWidth || document.documentElement.clientWidth) &&
              rect.top < (window.innerHeight || document.documentElement.clientHeight);
          let className = attrs.inviewClass;
          boolChangeClass ? elem.addClass(className) : elem.removeClass(className);
          //
          event.inview = {};
          event.inview[className] = boolChangeClass;
          scope.$apply( () => {
              scope.$eval(attrs.onScroll, {$event: event});
          });
        });
      };
    })
    

    在每个滚动事件中,该指令会将 on-scroll 属性评估为 AngularJS 表达式,使用 $event 作为本地表达式。


    更新 #2

    但是,如果我想在滚动时调用控制器中的方法,但当我的变量为真时只调用一次呢?我尝试使用一次性绑定,但它并没有真正起作用。

    让控制器过滤事件会更明智:

    <div class="component" inview-class="min" on-scroll="$ctrl.fn($event)" >
    </div> 
    
    var minOnce;
    this.fn = (event) => {
        if (minOnce || !event.inview.min) return;
        //ELSE
        minOnce = true;
        //
        // ...
    };
    

    这种方式指令更通用,测试更容易。

    【讨论】:

    • 好的。我应该在我的控制器中做什么?检查类是否存在,然后调用他的方法?
    • 谢谢。它工作得很好。但是,如果我想在滚动时调用控制器中的方法但只在我的变量为真时调用一次呢?我尝试使用一次性绑定,但它并没有真正起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 2014-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多