AngularJS指令股范围与NG-重复 - 行为不检 [英] AngularJS directive shares scope with ng-repeat - misbehavior

查看:268
本文介绍了AngularJS指令股范围与NG-重复 - 行为不检的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到一个奇怪的局面。我需要有一个应该交换通过拖放正下降元素或添加/删除事件2排序列表。

I'm experiencing a weird situation. I need to have two sortable lists that should interchange elements by drag-n-drop or Add/Remove events.

我创建了行之有效的指令。同时,控制器事件做正确的工作。问题始于合并方法时,(按钮添加+拖N - 降+按钮重新添加)。
KA-BOOM!

I created a directive that works well. Also the controller event do the right job. The problem begins when methods are combined (button Add + drag-n-drop + button Add again). KA-BOOM!

我放在一起这plnkr: http://plnkr.co/edit/DumufP1kDdkz1INAXwmF p = preVIEW

I put together this plnkr: http://plnkr.co/edit/DumufP1kDdkz1INAXwmF?p=preview

点击上的元素之前单击按钮操作(添加/删除)。

Click on the elements before click the button action (Add/Remove).

让我分享一些指令只是为了好玩的code,但请访问该链接以查看整个执行。还有就是如何重现该问题在 plnkr

Let me share some of the code of the directive just for fun but please visit the link to see the entire implementation. There is more information of how to reproduce the issue in the plnkr

.directive('sortableList', function ($log) {
    return {
        restrict: 'A',
        scope: {
            fromList: '=',
            toList: '='
        },
        link: function (scope, elm, attrs) {                        

            var callback = {
                receive: function (event, ui) {

                    //-- Get the scope of the list-item
                    var scopeItem = ui.item.scope();
                    //-- Get new list index
                    var newIdx = ui.item.index();

                    //-- Find position in the list
                    var prevIdx = scope.fromList.indexOf(scopeItem.obj);                    

                    //-- Remove from source list
                    scope.fromList.splice(prevIdx, 1);
                    //-- Add to target list
                    if (newIdx >= scope.toList.length) {
                        scope.toList.push(scopeItem.obj);
                    }
                    else {
                        scope.toList.splice(newIdx, 0, scopeItem.obj);
                    }

                    //ui.item.removeClass('selectedSortListItem').addClass('sortListItem');

                    scope.$apply();
                },
                stop: function (event, ui) {
                    //$log.log(ui);
                }
            };            

            //-- Apply jquery ui sortable plug-in to element
            elm.sortable({
                handle: ".handle",
                connectWith: '.sortColumnsConnect',
                dropOnEmpty: true,
                cancel: ".ui-state-disabled",
                receive: callback.receive,
                stop: callback.stop
            }).disableSelection();

            //-- Sniff for list changes 
            /*scope.$watch(attrs.sortableList, function (newVal) {
                //-- Apply callback

                //if (angular.isUndefined(newVal)) return;

                elm.sortable('option', 'receive', callback.receive);

                if (!angular.isUndefined(attrs.trackSorting) && Boolean(attrs.trackSorting)) {
                    elm.sortable('option', 'stop', callback.stop);
                }
            });*/


        }
    }
})

帮助是AP preciated。

Help is appreciated.

推荐答案

我终于做到了工作。我在这个 plunker 这一切的工作。
我认为这是关系到这两个指令的范围(定制+ NG重复),但它竟然是我需要离开NG-重复做整个工作,从来没有删除NG重复意见,否则角指令将制动。

I finally made it work. I have it all working in this plunker. I thought it was related to the scope of both directives (custom + ng-repeat) but it turned out to be that I needed to leave ng-repeat do the whole job and never remove the ng-repeat comments, otherwise the angular directive will brake.

但有一件事,我的指令,需要照顾的是$破坏甚至,由于本身持有,更好地为以后删除当页面叶子什么的,以避免内存泄漏情况的对象引用的指令。

One thing though that my directive needs to take care is the $destroy even, as the directive itself is holding a reference of an object that better is removed later when the page leaves or something in order to avoid a memory leak situation.

现在,让我们再次在这里分享一些code的乐趣..

Now, let's share some code here for fun.. again..

.directive('sortableList', function ($log, $parse,$timeout) {
return {
    restrict: 'A',
    scope: {
        list: '='
    },
    link: function (scope, elm, attrs) {                        

        /*
         * We need to preserve a copy of ng-repeat comments
         * in order to not brake the ng directive. Lets made a copy and
         * and insert it back to the html list in the remove even.
         */
        var comments = elm.contents().filter(function(){ 
          return this.nodeType == 8;
        });

        var comment = undefined;
        if (comments.length > 0){
          comment = comments[0];
        }

        var callback = {
            start: function(event, ui){

              ui.item.sortable = {
                received: false,
                startIndex: ui.item.index()
              };

            },
            receive: function (event, ui) {
              ui.item.sortable.received = true;
            },
            update: function (event, ui) {
              //$log.log(elm);
              $log.log('update');

              var scopeItem = ui.item.scope();

              //-- Get new list index. Index in array not in html list
              var newIdx = ui.item.index(); 

              if (ui.item.sortable.received){

                $log.log('received');

                ui.sender.sortable('cancel');
                ui.item.sortable.received = false;
                //ui.item.sortable.doremove = true;

                scope.$apply(function(){

                  //-- Add to target list
                  if (newIdx >= scope.list.length) {
                    scope.list.push(scopeItem.obj);
                  }
                  else {
                    $log.log(newIdx);
                    scope.list.splice(newIdx, 0, scopeItem.obj);
                  }

                  ui.item.removeClass('selectedSortListItem').addClass('sortListItem');

                });
              }
              else {
                //-- Sort list
                if (ui.item.sortable.startIndex != newIdx){

                  $log.log('sort list');

                  scope.$apply(function(){

                    var idx = scope.list.indexOf(scopeItem.obj);

                    //-- end destroy
                    if (idx > -1){
                      scope.list.splice(idx, 1);  
                    }    
                    //-- Add to the new position
                    scope.list.splice(newIdx, 0, scopeItem.obj);

                  });
                }
              }


            },
            remove: function( event, ui ) {
              var scopeItem = ui.item.scope();

              /* Do the normal node removal  */
              //-- Seek
              var idx = scope.list.indexOf(scopeItem.obj);

              //-- end destroy
              if (idx > -1){
                scope.list.splice(idx, 1);  
              }

              /*
               * Insert back ng-repeat comments to the html list to avoid braking
               * the angular directive.
               */
              if (elm.children("li:not('.ui-state-disabled')").length === 0 && angular.isDefined(comment)){
                $log.log('insert comment');
                $log.log(comment);
                elm.append(comment);
                //$log.log(elm);
              }

              //$log.log('I have childrens: ' + elm.children("li:not('.ui-state-disabled')").length);
              //$log.log('remove me please at:' + idx);
            },
            stop: function (event, ui) {
              $log.log('stop');
            }
        };            

        scope.$watch('list.length', function() {
          // Timeout to let ng-repeat modify the DOM
          $timeout(function() {
            $log.log('epa!');
            //-- need to unselect those selected, otherwise Vishal will go like: Leo there is an error.. what? what? what?
            elm.children("li.selectedSortListItem").toggleClass('selectedSortListItem').toggleClass('sortListItem');
            elm.sortable('refresh');
          });
        });

        //-- Apply jquery ui sortable plug-in to element
        elm.sortable({
            handle: ".handle",
            connectWith: '.sortColumnsConnect',
            dropOnEmpty: true,
            cancel: ".ui-state-disabled",
            helper: "clone",
            start: callback.start,
            receive: callback.receive,
            update: callback.update,
            stop: callback.stop,
            remove: callback.remove
        }).disableSelection();



    }
}

})

看一看的plunker了解该指令是如何调用,它的目的。我可能有一些东西,忘了过了这么重的工厂删除..但好像现在做正确的事情..至少它没有刹车,就像是之前。

Take a look at the plunker to understand how the directive is invoked and the purpose of it. I might have some stuff that forgot to remove after so many re-factories.. but seems like now is doing the right thing.. at least it's not braking like it was before.

感谢。

这篇关于AngularJS指令股范围与NG-重复 - 行为不检的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆