簡體   English   中英

Angular Directive - 我可以從父級繼承隔離范圍嗎?

[英]Angular Directive - can I have an isolate scope inherit from parent?

我正在嘗試編輯其他人編寫的角度指令,但遇到了一個問題。 它是一個屬性指令,我想觀察作為更改屬性值傳入的值。

當我給它一個隔離范圍並使用 scope.$watch 監視屬性時,這會起作用。 但是,使用隔離作用域會破壞指令,因為它最初將作用域設置為 true,這是其他事情所需的(據我所知,這意味着它繼承了父作用域)。

所以我的問題是,如何繼承父作用域,同時還要觀察屬性的值?

為了幫助澄清,這里是該指令的一個基本示例:

return {
            scope: {
                myGridsterItem: "=gridsterItem"
            },
            restrict: 'EA',
            controller: 'GridsterItemCtrl',
            controllerAs: 'gridsterItem',
            require: ['^gridster', 'gridsterItem'],
            link: function(scope, $el, attrs, controllers) {

                .....

                // need to dynamically update draggable/resizable of individuaol gridster item if properties change
                scope.$watch("myGridsterItem.draggable", function(newVal) {
                    draggable.updateDraggable(newVal);
                }, true);
                scope.$watch("myGridsterItem.resizable", function(newVal) {
                    resizable.updateResizable(newVal);
                }, true);

                .....
            }
    }

由於它沒有繼承父作用域,這會引發錯誤。 如果我設置

scope: true

我的錯誤已解決,但監視處理程序從未運行。

HTML 的粗略輪廓:

<div gridster="gridsterOpts">
    <ul>
        <li gridster-item="getPrefs(portlet.id)", ng-repeat="portlet in getPortlets()">
            .....
        </li>
    </ul>
</div>

請幫幫我,謝謝!

更新答案

我已經玩了更多的游戲,並在下面的代碼片段中演示了一種可能的解決方案。

如果不使用隔離的作用域(因為這會給您帶來其他問題),基本上我們需要的是getPrefs(portlet.id)在您的指令的鏈接函數嘗試將其分配給作用域時進行插值或解析。 如果不這樣做,如果您將attrs.gridsterItem的值輸出到控制台,您將看到它是getPrefs(portlet.id) ,而不是調用該函數的結果。

我遇到的最簡潔的解決方案是使用$parse 在您的鏈接函數中,它允許我們在將屬性分配給作用域時評估包含在屬性中的函數。 這樣,它是分配該函數的結果,這允許觀察者函數正確觸發。

請注意,必須將$parse添加為指令聲明的依賴項並作為參數傳遞。

 (function() { "use strict"; var myApp = angular.module("myApp", []) .directive("gridsterItem", ["$parse", GridsterItemDirective]); // Make sure to DI '$parse' function GridsterItemDirective($parse) { return { restrict: 'EA', controller: 'GridsterItemCtrl', controllerAs: 'gridsterItem', require: ['^gridster', 'gridsterItem'], link: function(scope, $el, attrs, controllers) { scope.output = ""; //for demo'ing scope.myGridsterItem = $parse(attrs.gridsterItem)(scope); //evaluating the value of attrs.gridsterItem in the context of 'scope' // need to dynamically update draggable/resizable of individuaol gridster item if properties change scope.$watch("myGridsterItem.draggable", function(newVal) { console.log("myGridsterItem.draggable: ", newVal); scope.output += "Draggable updated (" + newVal + ")... "; }, true); scope.$watch("myGridsterItem.resizable", function(newVal) { console.log("myGridsterItem.resizable: ", newVal); scope.output += "Resizable updated (" + newVal + ")... "; }, true); } }; } //------------------------------- //Supporting mockups... myApp.controller("myController", ["$scope", MyController]) //supporting mocks .directive("gridster", [GridsterDirective]) .controller("GridsterCtrl", ["$scope", GridsterCtrl]) .controller("GridsterItemCtrl", ["$scope", GridsterItemCtrl]); function MyController($scope) { var _portlets = [{ id: "1" }, { id: "2" }, { id: "3" }]; $scope.getPortlets = function getPortlets() { return _portlets; }; var _prefs = { "1": { draggable: true, resizable: true }, "2": { draggable: true, resizable: true }, "3": { draggable: true, resizable: true }, }; $scope.getPrefs = function getPrefs(id) { return _prefs[id]; } $scope.setPrefs = function setPrefs(id, prefName, value) { _prefs[id][prefName] = value; } } function GridsterDirective() { return { restrict: 'EA', controller: 'GridsterCtrl', controllerAs: 'gridster' }; } function GridsterCtrl($scope) { //mock } function GridsterItemCtrl($scope) { //mock } })();
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script> <style type="text/css"> li { border: 1px solid #ccc; padding: 10px; margin: 10px; font: 0.8em Arial, sans-serif; } </style> <div ng-app="myApp"> <div ng-controller="myController"> <div gridster> <ul> <li gridster-item="getPrefs(portlet.id)" ng-repeat="portlet in getPortlets()"> <p><strong>portlet.id:</strong> {{portlet.id}}</p> <p>{{getPrefs(portlet.id)}}</p> <p><strong>Output:</strong> {{output}}</p> <button ng-click="setPrefs(portlet.id, 'draggable', !getPrefs(portlet.id).draggable)">Toggle Draggable</button> <button ng-click="setPrefs(portlet.id, 'resizable', !getPrefs(portlet.id).resizable)">Toggle Resizable</button> </li> </ul> </div> </div> </div>

舊答案:

在您的鏈接函數(具有非隔離作用域)中,試試這個:

scope.myGridsterItem = attrs.gridsterItem;

attrs是一個自動提供給您的鏈接函數的參數,並且應該在其中包含您的指令所使用的元素上的屬性集合。 獲取您需要的屬性,並將其分配myGridsterItem $watch 表達式中的相關變量相匹配的范圍變量(在本例中為myGridsterItem ,它看起來像)。

請記住,angular 的命名約定意味着 HTML 中名為this-is-an-attribute將可以作為thisIsAnAttributethisIsAnAttribute到駱駝大小寫的轉換)在 javascript 中訪問。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM