Daa*_*ron 4 javascript angularjs angularjs-directive
我有一个指令,它将转录它的内容.并且在被抄送的内容中是一个指令,它需要transcluding指令的控制器.如果我在transcluding指令中创建了一个transclude函数,则抛出一个错误.我认为这是因为当你提供一个transclude函数时,被克服的内容会被克隆(https://github.com/angular/angular.js/blob/master/src/ng/compile.js#L846).
我也有一个描述我的问题的傻瓜:http://plnkr.co/edit/rRKWW6zfjZuUiw1BY4zs?p = preview
我想要做的是我想要转换内容并解析所有被转换的内容,然后将它放在DOM中的正确位置并自己编译.被抄送的内容实际上是我的指令的配置.
我也尝试清空我在transcluding函数中收到的克隆数组,因为我实际上不需要自动转换内容.我只需要解析它并在稍后的时间点手动转换它.Angular不需要对我的被抄送的内容做任何事情.但这不起作用,因为在调用transcluding函数时已经识别出指令.所以当我清空数组时,我收到一个错误(https://github.com/angular/angular.js/blob/master/src/ng/compile.js#L961).
亲切的问候,
大安
当您使用时,require: "^controller"您告诉Angular该指令需要controller在链接函数运行时附加到祖先DOM元素.
当你在不使用ngTransclude指令的情况下进行转换时,你的父指令链接函数get传递了一个transclude方法.(你已经知道了;这只是为了完整性.)这个transclude方法执行以下操作:
cloneAttachFn传入了a,则克隆内容并调用cloneAttachFn$compile()使用调用transclude提供的作用域编译和链接内容(或克隆的内容)(默认为从指令作用域的$ parent继承的新作用域).如果您调用transclude,并且最终没有将内容作为具有所需控制器的元素的后代附加(或者根本不将内容添加到DOM),则内容将不具有所需控制器的父级.因为它找不到所需的控制器,所以会出错.
在您的示例中,如果您使用kmBar require: "^kmFoo",则只能将已转换的内容添加到DOM节点,这些DOM节点是具有kmFoo的节点的后代.
最简单的解决方法是继续将其附加到kmFoo的元素以用于$ compile()和链接,但立即将其分离.
分离(而不是删除)维护单击处理程序等,因此如果稍后附加元素,一切都将继续有效.如果您使用的是AngularJS的早期版本,则可能需要包含jQuery以进行分离,因为它未包含在早期版本的jqLite中.
这是我放在一起的Plunk的片段
app.directive('kmFoo', function() {
return {
restrict: 'A',
scope: true,
template: '<div></div>',
transclude: true,
controller: function() {
// ...
},
link: function(scope, $element, attrs, ctrl, transcludeFn) {
console.log('linking foo');
// We are going to temporarily add it to $element so it can be linked,
// but after it's linked, we detach it.
transcludeFn(scope, function(clone) {
console.log('transcluding foo');
$element.append(clone);
c = clone;
}).detach();// <- Immediately detach it
}
};
});
app.directive('kmBar', function() {
return {
restrict: 'A',
scope: true,
require: '^kmFoo',
link: function(scope, $element, attrs, fooCtrl) {
console.log('linking bar');
// Right now it's a child of the element containing kmFoo,
// but it won't be after this method is complete.
// You can defer adding this element to the DOM
// for as long as you want, and you can put it wherever you want.
}
};
});
Run Code Online (Sandbox Code Playgroud)
首先,为什么需要 transclude 函数?这还不够吗?
app.directive('kmFoo', function() {
return {
'restrict': 'A',
'scope': true,
'controller': function() {
this.tryMe = function() { console.log("Success!") };
},
'link': function(scope, element, attrs, ctrl) {
console.log('linking foo');
var innerHtml = element.html();
// do something with innerHtml
element.html("<div>Empty</div>");
}
};
});
app.directive('kmBar', function() {
return {
'restrict': 'A',
'scope': true,
'require': '^kmFoo',
'link': function(scope, element, attrs, fooCtrl) {
fooCtrl.tryMe();
}
};
});
Run Code Online (Sandbox Code Playgroud)
但是,如果您确实想访问 fooController 并在 kmFoo 中具有 transclude 函数,则可以element.controller()在完成所有链接并初始化所有控制器后通过 访问控制器。
app.directive('kmFoo', function() {
return {
'restrict': 'A',
'scope': true,
'template': '<div ng-transclude></div>',
'transclude': true,
'controller': function() {
this.tryMe = function() { console.log("Success!") };
},
'link': function(scope, $element, attrs, ctrl, transcludeFn) {
console.log('linking foo');
// when you put the transclude function in comments it won't throw an error
transcludeFn(scope, function(clone) {
console.log('transcluding foo');
});
}
};
});
app.directive('kmBar', function() {
return {
'restrict': 'A',
'scope': true,
'template': "<button ng-click='tryMe()'>Feeling lucky?</button>",
'link': function(scope, element, attrs) {
scope.getFooCtrl = function() {
return element.parent().controller('kmFoo');
};
console.log('linking bar');
console.log('parent not yet known: ' + element.parent().toString());
},
'controller': function($scope) {
$scope.tryMe = function() {
$scope.getFooCtrl().tryMe();
};
}
};
});
Run Code Online (Sandbox Code Playgroud)
使用plnkr查看它的实际效果。
| 归档时间: |
|
| 查看次数: |
3035 次 |
| 最近记录: |