AngularJS简单指令

时间:2013-10-17 22:41:22

标签: jquery angularjs bootstrap-select

我正在尝试为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。是否有一种简单的方法可以轻松地将这个简单的插件包装成角度?因为我花了半天时间试图让它发挥作用

:(

2 个答案:

答案 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,以便在数组中的项目数更改时通知您。


Orignal答案:

要解决这个问题,您需要使用$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