2016-08-11 120 views
0

這是問題所在。我有一些第三方的指令稱爲主指令AngularJS覆蓋指令控制器功能

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

所以我想讓叫我自己的指令家長指令其分配專用默認值第三方指令屬性。

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

如果我不想再拍兒童指令,保持家長指令邏輯。 重載屬性是很容易,我可以使用「編譯」功能。但是重寫函數又有什麼可能呢?

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

+0

您是否嘗試過使用$ parent?如果你的函數在父範圍內,你可以使用$ parent來訪問它們,然後覆蓋它們。 – acostela

+0

是的,但是如果在父指令和子指令之間會有ng-if指令會怎麼樣。使用$父母恕我直言,這不是一個解決方案。儘管美元父母被認爲是不好的做法。 – dagi12

回答

0

好吧,我做了一些研究和事實證明,可以有幾種方法有

範圍繼承

由於兒童指令也沒有創造自己它只是在父指令父範圍中創建新方法。所以我們可以在編譯期間修改屬性並指定重寫的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

添加到隔離範圍

角提供的特殊功能。這可以從元素中獲得孤立的範圍。所以我們可以在鏈接階段重寫我們的方法。

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

Transclusion

實際上你可以用單獨的家長和孩子的指令,並使用transclusion同樣的事情。但無論如何,這將是上述方法的組合。感謝"Extending an existing directive in AngularJS"

相關問題