[英]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
將可以作為thisIsAnAttribute
( thisIsAnAttribute
到駱駝大小寫的轉換)在 javascript 中訪問。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.