2014-09-16 4 views
1

Я пытаюсь реализовать сортируемое drag-n-drop. Я попробовал ng-sortable и несколько других, но у меня есть некоторые угловые случаи, когда я не смог настроить их для своих нужд и решил сделать это сам.

У меня есть директивы для draggable, droppable и основного ui-router view/controller.

Я передаю функцию (handleDrop() '), принимающую некоторые параметры от контроллера к директиве droppable. Я хочу, чтобы функция обновляла модель в области основного представления/контроллера при вызове из директивы.

Он отлично работает, но генерирует ошибку $ digest.

Это потому, что в директиве я завершаю вызов handleDrop() с помощью $ apply, а затем внутри handleDrop, я завершаю часть функции в другой $ apply. Явно не правильно, но это единственный способ заставить его работать, потому что тогда все работает отлично, за исключением ошибки.

Если я удалить $ применять в handleDrop(), то вид только получает частично обновляется (например, я получаю ли-элемент, прикрепленный к моему списку, но пустой -. Без соответствующих данных

Я попытался заменить $ примените в handleDrop() с $ timeout на основе ответов на аналогичные вопросы, а затем он работает до тех пор, пока я не ввешиваю $ timeout, но очевидно, что «$ timeout не определен» - но он также работает.

If Я ввожу $ timeout в контроллер. Я не получаю такой ошибки (как и ожидалось), но затем dom не обновляется должным образом снова.

Ниже разделенные версии моей директивы и контроллера, я думаю, являются импортными частями. drop() указан в html для handleDrop().

Любая помощь на то, что я делаю неправильно высоко оценили

Директива:

app.directive('droppable', function() { 
    return { 
    scope: { 
     drop: '&', 
     bin: '=' 
    }, 
    link: function(scope, element) { 
    var el = element[0]; 

    el.addEventListener(
    'drop', 
    function(e) { 
     if (e.stopPropagation) e.stopPropagation(); 

     var item = document.getElementById(e.dataTransfer.getData('text/plain')); 
     // Putting additional data into variables newStage etc 

     // call the passed drop function 
     scope.$apply(function(scope) { 
     var fn = scope.drop(); 
     if ('undefined' !== typeof fn) {    
      fn(item, newStage, prevStage, newIndex); 
      document.getElementById(someHtmlElementIdIHave).appendChild(item); 
      } 
     } 
     }); 

     return false; 
    }, 
    false 
); 

И контроллер:

.controller('funnelCtrl', function ($scope, $state, $http, someObject) { 
    $scope.handleDrop = function(item, newStage, prevStage, newIndex) { 

     $http.put('/api/funnel/' + item.id, {some object}). 
     success(function (data) { 
        $timeout(function(){ 
         $scope.someObject[newStage].splice(newIndex, 0, item.optyId) ; 
         $scope.someObect[prevStage].splice(prevIndex,1);        
        });       
     }). 
     error(function (data) {alert('Error Saving');}); 
    }; 
+0

Correct @maurycy, оказывается, мне не нужно никаких $ применять вообще, моя ошибка была ошибка при добавлении нового элемента в массив .. I» m все еще запутался относительно того, почему он работал ранее с двойным применением. – kns

ответ

1

Вместо если $apply() использовать $timeout, как применять триггеры переваривать но тайм-аут будет планировать его для следующего процесса обработки дайджеста, хотя я не уверен, что вам даже понадобится его код, вы не назначаете anythi нг до объема в текущем $apply

$timeout(function(scope) { 
    var fn = scope.drop(); 
    if ('undefined' !== typeof fn) {    
    fn(item, newStage, prevStage, newIndex); 
    document.getElementById(someHtmlElementIdIHave).appendChild(item); 
    } 
}) 
+0

Спасибо. Я получаю «Не могу прочитать свойство« drop »undefined», запускающего этот код. Я ввел $ timeout и попробовал это, но тогда переменная области видимости теперь не доступна, какие-либо идеи? – kns

+0

Фрагмент кода не решил его, но верно, что ошибка не была вызвана двойным $ apply – kns

Смежные вопросы