我正在尝试编辑由其他人编写的角度指令,我遇到了一个问题。它是一个属性指令,我想看到传入的值作为属性的更改值。
当我给它一个隔离范围并使用范围观察属性时,这是有效的。$ 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>
请帮助我,谢谢!
答案 0 :(得分:1)
我有更多的游戏,并在下面的代码片段中展示了一个可能的解决方案。
不使用隔离范围(因为这会导致其他问题),基本上我们需要的是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
是一个自动提供给您的链接函数的参数,并且应该在其中包含您的指令所使用的元素上的属性集合。获取所需的属性,并将其分配给与$ watch表达式中相关的范围变量匹配的范围变量(在这种情况下为myGridsterItem
,看起来像)。
请记住,angular的命名约定意味着HTML中的一个名为this-is-an-attribute
的属性可以在javascript中以thisIsAnAttribute
(snake-to camel-case conversion)的形式访问。