我正在尝试为bootstrap-select:
创建一个指令http://silviomoreto.github.io/bootstrap-select/(它允许创建漂亮的选择)
根据以下教程,将jquery插件转换为angular指令应该是一项简单的任务:http://www.youtube.com/watch?v=9Bu73oQQSio 但事实上,目前我还没有坚持到第一步,我无法获得最基本的功能。我尝试了不同的方法:
<select multiple selectpicker>
<option selectpickeroption ng-repeat="MyModel in MyModels">
{{ MyModel.MyProperty }}
</option>
</select>
<selectpicker multiple="multiple">
<option ng-repeat="MyModel in MyModels">
{{ MyModel.MyProperty }}
</option>
</selectpicker>
与
一起Application.directive('selectpicker', [function () {
return {
restrict: 'A',
compile: function() {
return function(scope, element, attributes, controller) {
element.selectpicker(); // launch `.selectpicker()` plugin
// Lunching selectpicker at current point is way to early,
// at this point all <option ng-repeat="MyModel in MyModels">..</option>
// contain the following text `{{ MyModel.MyProperty }}`
};
}
};
}]);
但它们都没有奏效,它只是不想融入Angular。是否有一种简单的方法可以轻松地将这个简单的插件包装成角度?因为我花了半天时间试图让它发挥作用
:(
答案 0 :(得分:2)
这是一个时间问题 - 您的selectpicker
指令在创建<option>
元素之前正在运行。
要解决此问题,您需要将来电延迟到element.selectpicker()
,直到<option>
元素被创建。
对评论的回应:
@ Lu4#1:你是对的,一般在Angular中,可以避免使用$timeout
。
我已经更新了使用$watch
的答案(如果您使用的是Angular 1.2+,那么您可能希望使用$watchCollection
)。
@dluz#2:据我所知,$timeout
对于这种情况足够可靠,但更新后的答案应该解决任何问题。
使用document.ready()
在这里不合适,因为这与浏览器加载页面的状态有关,而不是Angular如何与DOM一起工作。因为我们的Angular代码已经运行,所以知道ready事件已经触发了 - document.ready()
必须在Angular运行之前触发。
Lu4遇到的问题是如何处理Angular进程指令 - 它从外部对每个元素进行操作,在转移到子元素及其指令之前初始化所有指令(为简单起见,我们忽略{{1指令)。因此,当调用terminal
指令时,Angular尚未处理子元素。
更新您的HTML,将selectpicker
作为您要观看的集合传递给selectpicker指令。
MyModels
然后更新指令以对<select multiple selectpicker="MyModels">
...
</select>
属性的值设置$watch
。
从我的快速测试中,selectpicker
会在DOM更新后触发,您应该可以调用$watch
。
selectpicker()
使用此方法,当在范围上设置集合或更换集合时,myApp.directive('selectpicker', [
return {
function(){
restrict: 'A',
scope: true,
link: function(scope, element, iAttrs, controller){
console.log('selectpicker::link: element=', element.eq(0).children().length);
scope.$watchCollection(iAttrs['selectpicker'], function(newValue){
console.log('selectpicker::$watch: element=', element.eq(0).children().length);
element.selectpicker();
});
}
};
}]);
将触发。在Angular 1.2中,您应该使用$watch
,以便在数组中的项目数更改时通知您。
要解决这个问题,您需要使用$watchCollection
服务将来电延迟到$timeout
,直到下一个“勾号”。
element.selectpicker()
这应该让事情开始,但你必须要小心 - 如果myApp.directive('selectpicker', ['$timeout',
function($timeout){
return {
restrict: 'A',
link: function(scope, element, iAttrs, controller){
// Log the number of children of the <select>.
// This will be 0 because Angular hasn't processed the children yet.
console.log('selectpicker::link: element=', element.eq(0).children().length);
var initSelectpicker = function(){
// Now the children have been created.
console.log('selectpicker::init: element=', element.eq(0).children().length);
element.selectpicker();
}
$timeout(initSelectpicker, 0, false);
}
};
}]);
发生变化,那么你将不得不确保selectpicker也保持最新状态。
答案 1 :(得分:1)
您需要使用指令的link:
函数调用插件。您只能在元素上注册任何侦听器,并在链接阶段设置具有范围的任何手表。 (不是编译阶段)
如果你仔细看看你提到的YouTube视频教程,他就会在link:
函数中做所有事情。
myApp.directive('selectpicker', [function () {
return {
restrict: 'A',
link: function (scope, element, iAttrs, controller) {
console.log(element);
element.selectpicker();
}
};
}]);
通常,如果需要转换/更改模板的DOM元素,则只需要使用compile
阶段。另一方面,link
函数将允许指令在特定的克隆DOM元素实例上注册侦听器,以及将内容从范围复制到DOM中。
您可以在此处了解更多信息 - http://docs.angularjs.org/guide/directive