1

我遇到了一個奇怪的情況。我需要有兩個可排序的列表,這些列表應該通過拖放或添加/刪除事件來交換元素。AngularJS指令共享範圍與ng重複 - 行爲不端

我創建了一個很好的指令。控制器事件也做正確的工作。問題在方法合併時開始(按鈕Add +拖放+按鈕再次添加)。 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); 
       } 
      });*/ 


     } 
    } 
}) 

說明問題認識的更多信息。

回答

0

我終於做到了。我已經在plunker中工作了。 我認爲它與兩個指令(自定義+ ng-repeat)的範圍有關,但事實證明,我需要離開ng-repeat來完成整個工作,並且永遠不要刪除ng-repeat注​​釋,否則,angular指令會剎車。

雖然我的指令需要注意的一件事情是甚至是$ destroy,因爲指令本身持有對象的引用,稍後在頁面離開或更新時移除更好的對象以避免內存泄漏情況。

現在,讓我們在這裏分享一些代碼的樂趣..再次..

.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理解指令是如何調用,它的目的。我可能會有一些東西在經過這麼多的重新工廠之後忘了刪除......但是現在看起來像是在做正確的事情......至少它不像以前那樣剎車。

謝謝。