AngularJS覆盖指令控制器功能 [英] AngularJS override directive controller function

查看:48
本文介绍了AngularJS覆盖指令控制器功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是问题所在.我有一些称为 main-directive 的第三方指令.

Here is the problem. I have some 3rd party directive called main-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 的指令,该指令将应用程序特定的默认值分配给第三方指令属性.

So I want to make my own directive called parent-directive which assign application specific default values to third party directive attributes.

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>'
  }
});

如果我想再做一个子代指令,该子指令保持父代指令的逻辑,该怎么办?重载属性很容易,我可以使用编译"功能.但是有可能覆盖功能吗?

What if I want to make another child-directive that keeps parent-directive logic. Overloading attribute is easy i can use "compile" function. But what about overriding functions is it possible?

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";
    }
  }
});

通过使用子作用域而不是孤立作用域,可以轻松完成整个操作.或通过使用扩展模板.但是,如果我使用模板扩展指令,则必须将父作用域"和模板"定义复制到子指令并转发所有非默认属性,这似乎不是一个很好的解决方案.

Whole thing can be easily done by using child scope instead of isolated. Or by using extending by template. But if I extends directive with template I would have to copy parent "scope" and "template" definition to child-directive and forward all the non-default attributes this doesn't seem like an elegant solution.

所以关键问题是,有没有一种方法可以使用隔离的作用域来覆盖父指令功能而无需转发属性.

So the key question, is there a way to override parent-directive function using isolated scope without forwarding attributes.

这是 DEMO

推荐答案

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

Ok, I have done some research and it turns out that there can be several approaches there

范围继承

由于子指令不创建自己的作用域,因此它仅在父指令的父作用域中创建新方法.因此,我们可以在编译期间修改属性并指定覆盖的foo方法.

Since child-directive is not creating own scope it just creating new methods at parent-directive parent scope. So we can modify attributes during compile and specify overridden foo method.

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提供特殊功能.那可以从元素中获得孤立的范围.因此,我们可以在链接阶段覆盖我们的方法.

Angular provides special function. That can get isolated scope from element. So we can override our method during linking phase.

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语法.这意味着我们将控制器对象变量作为作用域公开.在链接阶段,我们可以在子指令中覆盖函数.

If we use controllerAs syntax. That means we exposing controller object variables as a scope. We can override function in child directive during linking phase.

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

包含

实际上,您可以使用单独的父代和子代指令并使用包含来执行相同的操作.但是无论如何,这将是上述方法的组合.感谢您在AngularJS"

Practically you can do the same thing with seperate parent and child directive and using transclusion. But anyway it would be combination of above approaches. Thanks for "Extending an existing directive in AngularJS"

这篇关于AngularJS覆盖指令控制器功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆