AngularJS:从控制器访问指令数据
假设我有一个如下所示的AngularJS指令:AngularJS:从控制器访问指令数据,angularjs,angularjs-directive,angularjs-scope,Angularjs,Angularjs Directive,Angularjs Scope,假设我有一个如下所示的AngularJS指令: app.directive('psDIR', [ function() { return { template: "<div style='padding: 5px; border: 1px solid red; margin-bottom: 10px;'><p>This is a direcive:</p> <textarea rows='5' cols='
app.directive('psDIR', [
function() {
return {
template: "<div style='padding: 5px; border: 1px solid red; margin-bottom: 10px;'><p>This is a direcive:</p> <textarea rows='5' cols='50' ng-model='md'></textarea></div>",
restrict: 'AEC',
scope: {}
}
}
]);
Plunker演示:
非常感谢您的建议。因为您正在创建独立的作用域,否则您也无法从父作用域访问子作用域 解决方法是将模型作为参数从类父对象传递
然后在指令中使用属性绑定更新它们。请参阅更新plunkr
一个可能的解决方案是使用
require
:
app.directive('psDIR', [
function() {
return {
...,
require: "ngController",
link: function(scope, elem, attrs, ngCtrl) {
ngCtrl.hook(scope);
}
}
}
]);
以及对控制器进行必要的更改:
app.controller('MainCtrl', ['$scope',
function($scope) {
console.log("init");
$scope.add = function() {
var i;
for( i=0; i < psDirs.length; i++ ) {
console.log(i + " -> " + psDirs[i].md);
}
}
var psDirs = [];
this.hook = function(scope) {
psDirs.push(scope);
};
}
]);
指令本身使用上一个ng控制器的代码:
app.directive('wrapperDirective', function() {
return {
restrict: "A",
// YOU MAY WANT ISOLATED SCOPE, JUST ADD scope: {},
controller: ["$scope", function($scope) {
// SAME CODE AS BEFORE
console.log("init");
$scope.add = function() {
var i;
for( i=0; i < psDirs.length; i++ ) {
console.log(i + " -> " + psDirs[i].md);
}
}
var psDirs = [];
this.hook = function(scope) {
psDirs.push(scope);
};
}]
};
});
当您想要在作用域(即指令和其他控制器)之间通信时,通常正确的做法是使用服务 您可以在此处查看一个简单的plunker:
psDirs
服务保留指令的注册表:
app.service('psDirs', function() {
var psDirs = {
dirs: [],
register: function (dir) {
psDirs.dirs.push(dir);
}
};
return psDirs;
});
指令会自动注册并在更改时更新值:
link: function (scope, elm, attr) {
var dir = { val: "" };
psDirs.register(dir);
scope.$watch('md', function (n, o) {
if (n !== o) {
dir.val = n;
}
});
}
然后,控制器可以注入psDirs服务,并根据需要访问指令注册表。这可以防止脆弱的范围关系,并允许在其他地方使用指令注册表服务,在应用程序的多个控制器和部分中。请详细了解包装器控制器的详细信息。
wrapperDirectiveCtrl
comming from在哪里?它是wrapperDirective
的控制器。这是一种命名约定。临界值在要求中:“XXX”
,其中XXX
必须与指令名称匹配。是的,这是正确的。此外,您可能需要许多控制器。我在上面的语法中有一个错误,正确的是require:“^wrapperDirective”
(意思是搜索我的父母以查找指定的指令)-我将在答案中更正它。阅读详细信息。此解决方案清晰有效,易于理解。然而,我忍不住认为AngularJS团队已经看到了这种情况,他们实施了这种情况——我只是没有意识到!)在国际海事组织(IMO)看来,在服务中保持这样的状态通常是一个坏主意——如果有的话,必须谨慎行事。例如,上面的代码从未从服务中注销指令数据,这意味着它从未被垃圾收集,随着时间的推移,随着指令的销毁和重新创建,服务将积累越来越多的冗余数据。以及应用程序无意中重复使用“死”数据的风险,如果您碰巧注册了包含关闭的任何内容,您可能会导致相当严重的内存泄漏!这是我第一次在指令上看到模型。你能给我提供一个链接,也许我可以在那里多读一些书。这是我随便取的名字。你可以取任何名字。阅读指令api的编译文档此解决方案看起来最干净。让我做一些实验。
app.directive('psDIR', [
...
require: "^wrapperDirective",
link: function(scope, elem, attrs, wrapperDirectiveCtrl) {
wrapperDirectiveCtrl.hook(scope);
}
app.service('psDirs', function() {
var psDirs = {
dirs: [],
register: function (dir) {
psDirs.dirs.push(dir);
}
};
return psDirs;
});
link: function (scope, elm, attr) {
var dir = { val: "" };
psDirs.register(dir);
scope.$watch('md', function (n, o) {
if (n !== o) {
dir.val = n;
}
});
}