【问题标题】:AngularJS override directive controller functionAngularJS 覆盖指令控制器功能
【发布时间】:2016-08-12 17:10:54
【问题描述】:

这就是问题所在。我有一些名为 ma​​in-directive 的第三方指令。

app.directive('mainDirective', function() {
  return {
    scope: {
      foo: '&'
      // attrs
    },
    controller: function($scope) {

      $scope.click = function() {
        window.alert($scope.foo());
      }

    },
    template: '<button ng-click="click()">Click me</button>'
  }
});

所以我想创建自己的指令,称为 parent-directive,它将应用程序特定的默认值分配给第三方指令属性。

app.directive('parentDirective', function() {
  return {
    scope: {
      foo: '&?',
      attr2: '='
        // lots of attrs
    },
    controller: function($scope) {


      $scope.attr1 = "some default value"

      $scope.foo = function() {
        return "not overrided"
      }

      if (this.foo) {
        $scope.foo = this.foo
      }

    },
    template: '<div class="some-styling"><main-directive foo="foo()" attr1="attr1" attr2="attr2"></main-directive></div>'
  }
});

如果我想制作另一个 child-directive 来保持 parent-directive 逻辑。 重载属性很容易我可以使用“编译”功能。但是是否可以覆盖函数呢?

app.directive('childDirective', function() {

  return {
    scope: false,
    require: 'parentDirective',
    link: function(scope, element, attr, controller) {

      controller.foo = function() {
        return "overrided";
      }

    },
    compile: function(element, attr) {
      attr.attr2 = "attr2";
    }
  }
});

使用子作用域而不是孤立作用域可以轻松完成整个事情。 或者通过使用模板扩展。但是,如果我使用模板扩展指令,我将不得不将父“范围”和“模板”定义复制到子指令并转发所有非默认属性,这似乎不是一个优雅的解决方案。

所以关键问题是,有没有一种方法可以在不使用转发属性的情况下使用隔离范围覆盖父指令函数。

这里是DEMO

【问题讨论】:

  • 你试过使用$parent吗?如果您的函数在父范围内,您可以使用 $parent 访问它们,然后覆盖它们。
  • 确实是的,但是如果在父子指令之间的某个地方会有 ng-if 指令怎么办。在这里使用 $parent 恕我直言不是解决方案。尽管 $parent 被认为是不好的做法。

标签: javascript angularjs


【解决方案1】:

好的,我做了一些研究,结果发现可以有几种方法

作用域继承

由于子指令没有创建自己的作用域,它只是在父指令的父作用域创建新方法。所以我们可以在编译时修改属性并指定重写的 foo 方法。

app.directive('parentDirective', function() {
  return {
    scope: {
      fooImpl: '&?',
      // lots of attrs
    },
    controller: function($scope) {

      $scope.foo = function() {
        if ($scope.fooImpl) {
          return $scope.fooImpl();
        }
        return "not overrided";
      }

    },
    template: '<div class="some-styling"><main-directive foo="foo()"></main-directive></div>'
  }
});

app.directive('childDirective', function() {

  return {
    scope: false,
    require: 'parentDirective',
    controller: function($scope) {

      $scope.foo = function() {
        return "overrided";
      }

    },
    compile: function(element, attr) {
      attr.fooImpl = "foo()";
    }
  }
});

这里是DEMO1

添加到隔离范围

Angular 提供了特殊的功能。这可以从元素中获得孤立的范围。所以我们可以在链接阶段重写我们的方法。

app.directive('parentDirective', function() {
  return {
    scope: {
      fooImpl: '&?',
      // lots of attrs
    },
    controller: function($scope) {

      $scope.foo = function() {
        if ($scope.fooImpl) {
          return $scope.fooImpl();
        }
        return "not overrided";
      }

    },
    template: '<div class="some-styling"><main-directive foo="foo()"></main-directive></div>'
  }
});

app.directive('childDirective', function() {

  return {
    scope: false,
    require: 'parentDirective',
    link: function(scope, element, attr) {
      var innerScope = angular.element(element[0]).isolateScope();
      innerScope.foo = function() {
        return "overrided";
      }
    }
  }
});

这里是DEMO2

控制器方法

如果我们使用 controllerAs 语法。这意味着我们将控制器对象变量公开为范围。我们可以在链接阶段覆盖子指令中的函数。

app.directive('parentDirective', function() {
  return {
    scope: {
      fooImpl: '&?',
      // lots of attrs
    },
    controller: function($scope) {

      var vm = this;

      vm.foo = function() {
        return "not overrided";
      }

    },
    controllerAs : 'vm',
    template: '<div class="some-styling"><main-directive foo="vm.foo()"></main-directive></div>'
  }
});

app.directive('childDirective', function() {

  return {
    scope: false,
    require: 'parentDirective',
    link: function (scope, element, attr, controller) {

       controller.foo = function() {
        return "overrided";
      }


    }
  }
});

这里是DEMO3

嵌入

实际上,您可以使用单独的父子指令和使用嵌入来做同样的事情。但无论如何,这将是上述方法的组合。感谢"Extending an existing directive in AngularJS"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-15
    • 2013-03-15
    • 1970-01-01
    • 2016-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多