2015-04-08 2 views
1

Я переместил свой простой пейджинг с контроллера на директиву и застрял в странной проблеме. Каждый раз, когда я обновляю родительскую область из директивы, она обновляется только при следующем изменении. Поэтому, если ng-options - [10,20,30], а I ng - изменить его на 10 - ничего не происходит. Затем я меняю его на 20, и он обновляется до предыдущего значения 10, следующее изменение на любое значение получает обновленную модель до той, которую я выбрал до ... и т. Д.Директива обновляет родительскую область на один шаг задерживается

Я только недавно начал использовать директивы и перемещение вещей от контроллера, поэтому я мало знаю об этом (пожалуйста, у меня со мной). Я пытался использовать $ scope. $ Apply, но это не помогает. Я все еще получаю задержанные обновления. Что мне не хватает? Я понимаю, что это связано с обновлением дайджеста и $ scope. $ Apply, но я не могу понять, где его использовать. Все, что я пробовал, просто не работает.

Соответствующие части контроллера:

vm.pages = 0; 
vm.articles = []; 

vm.load = { page: { batch: 10, current: 1 } 
      , sort: { _id: -1 } 
      , filter: {} 
      }; 

vm.getArticles = function() { 
    articleS.list(vm.load, function (data){ 
    vm.pages = data.pages; 
    vm.articles = data.articles; 
    }); 
} 

директива:

.directive("paging", function() { 

    var scope = { update: '&', current: '=', pages: '=', batch: '=' }; 

    function link(s, e, a) { 
    s.options = [10,20,50,100]; 

    s.toPage = function(p) { 

     switch(p) { 
     case "last": 
      if (s.current != s.pages) { 
      s.current = s.pages; 
      s.update(); 
      } 
      break; 
     case "next": 
      if (s.current < s.pages) { 
      s.current ++; 
      s.update(); 
      } 
      break; 
     case "prev": 
      if (s.current > 1) { 
      s.current --; 
      s.update(); 
      } 
      break; 
     default: 
      s.current = 1; 
      s.update(); 
     } 

    } 
    } 

    return { 
    replace: true, 
    scope: scope, 
    templateUrl: 'paging.tpl', 
    link: link 
    } 
}); 

Шаблон директивы:

<section class='pages'> 
    <select 
      ng-model="batch" 
      ng-change="toPage('first')" 
      ng-options="value for value in options"> 
    </select> 
    <div> 
     <button ng-click="toPage('first')"> 1 </button> 
     <button ng-click="toPage('prev')"> << </button> 
     <div>{{current}}</div> 
     <button ng-click="toPage('next')"> >> </button> 
     <button ng-click="toPage('last')"> {{pages}} </button> 
    </div> 
    </section> 

Директива вызова:

 <paging 
     update="vm.getArticles()" 
     current="vm.load.page.current" 
     batch="vm.load.page.batch" 
     pages="vm.pages"> 
     </paging> 

Большое спасибо

+0

попробуйте использовать $ scope. $ Apply() перед s.update(); предложение в директиве – Anita

+0

@ Анита Это первое, что я пробовал - не повезло. Разве не '=' в изолированной области действия должен заботиться о двухсторонней привязке? –

+0

'=' создает область выделения, поэтому он делает только один способ привязки. Вы можете попробовать '&' вместо '='. – Anita

ответ

6

OK. Я понял это. Если я правильно понял, $ apply будет генерировать ошибку already in progress, если вы запустите ее по изолированной переменной области видимости, связанной с ее родителем с помощью '='. Я думаю, что '=' запускает $ digest (это просто наблюдение от проб и ошибок при попытке решить это).

Моя проблема заключалась в том, что функция s.update() была запущена до следующего цикла дайджеста. Поэтому локальные переменные области «не успевали» копировать в родительскую область. Вот почему я мог видеть только обновление на следующей операции или на следующем курсе цикла дайджеста, всегда видя предыдущее изменение. Игра с setTimeout(function(){ s.update() }, 2000) доказала это. Если я задерживаю выполнение в течение нескольких секунд, я вижу обновление с правильными изменениями. Отсрочка - это не решение, хотя замедление работы приложения довольно глупо. Затем я нашел angular's $timeout(function() {}) Это позволяет пропустить параметр задержки, который по умолчанию равен 0 и фактически не задерживает что-либо, но он гарантирует, что обратный вызов будет выполняться в следующем цикле дайджеста, чтобы локальные переменные области могли быть обновлены до родителя.

if (s.current < s.pages) { 
    s.current ++; 
    $timeout(function() { 
    s.update(); 
    }); 
} 
+0

Это помогло, спасибо :) – 32teeths

+0

Отлично работает –

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