AngularJS指令股范围与NG-重复 - 错误行为(AngularJS directive sh

2019-10-19 10:13发布

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

我创建了行之有效一个指令。 同时,控制器事件做合适的工作。 问题始于组合方法时(按钮添加+拖动正滴+按钮再次添加)。 KA-BOOM!

我整理了这篇plnkr: http://plnkr.co/edit/DumufP1kDdkz1INAXwmF?p=preview

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

让我分享一些指令只是为了好玩的代码,但请访问链接查看整个实现。 还有就是如何重现该问题的更多信息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);
                }
            });*/


        }
    }
})

帮助表示赞赏。

Answer 1:

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

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

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

.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理解指令是如何调用,它的目的。 我可能有一些东西,忘了过了这么重的工厂删除..但好像现在做正确的事..至少它没有制动,就像是之前。

谢谢。



文章来源: AngularJS directive shares scope with ng-repeat - misbehavior