2013-11-27 3 views
17

Я пытаюсь следовать this SO answer explaining how to render a recursive JSON structure using a directive. Однако, в отличие от предоставленного ответа, мои данные - , а не, известные при загрузке DOM, и Угловые пробеги в первый раз.Обновление Угловой директивы JS при изменении Сервиса

Вместо этого мои данные извлекаются из поля ввода HTML и сохраняются в Угловой службе (когда пользователь отправляет форму).

Как сохранить актуальную угловую директиву при изменении данных Сервиса?


Обновления в ответ на ответ

@musically_ut при условии, отличный ответа, что помогло, но выявил связанную проблему, предотвращая реализацию (обновление здесь).

директива делает HTML, который содержит угловую {{expressions}} которые доступ к данным, хранящимся в $scope. Поскольку исходное решение было $watch, когда сервис имел свои данные в готовности. Как я могу обеспечить добавление «новых» данных в $scopeдо Директива оказывает?

Обзор архитектуры и потока:

  1. ControllerA -> Получить информацию от пользователя
  2. ControllerA -> Используйте сервис для преобразования данных
  3. ControllerB ->$watch изменений в обслуживание
  4. Directive ->$watch для cha НГРЭС в службы
  5. ControllerB -> Добавить данные в $scope
  6. Directive -> Показать преобразованные данные (из службы) с использованием директивы

Проблема заключается между шагами 5 и 6. Директива оказывает {{expressions}} до того, как контроллер DataB добавил данные в $scope. Даже если это действительно сработало, это кажется слишком сложным и «взломанным».

Фактически, для регресса я использую $watch в ControllerB для прослушивания, когда преобразованные данные готовы к использованию. Даже это чувствует себя немного переполненным (услуга не делает асинхронных вызовов).

+0

Я новичок в угловой, и получить на свой пост при поиске информации о просмотре изменений услуги в директивах. Насколько я понимаю вас, pb (и в соответствии с тем, что я читал недавно), вы не должны «добавлять данные в область видимости» в вашем ** ControllerB **, вам лучше сообщить об этом ** службе **, и это будет автоматически сообщаться в область ** controllerB **. Кстати, вы сможете отслеживать ** служебные ** изменения в вашей ** директиве ** (я имею в виду, что легко отслеживать «внешний» ** контроллер. **). Но, возможно, я ошибаюсь. –

ответ

17

Вы можете ввести услугу при определении директивы, а затем установить данные $watch.Так что в вашем случае:

.directive('tree', function ($compile, myService) { 
    return { 
     // ... 
     link: function (scope, element, attrs) { 
      scope.$watch(function() { 
       return myService.getData(); 
      }, 
      function (newVal) { 
       if (typeof newVal !== 'undefined') { 
        // ... 
       } 
      } 
     }); 
    } 
}); 

Это смотреть данные для изменения и запуска кода при каждом изменении данных.


Однако если данные не меняется после того, как устанавливается один раз, лучший способ (более эффективный) будет возвращать обещание от службы ($http метод возвращает обещание прямо или вы можете создать используя службу $q), а затем добавьте свои вычисления в качестве продолжения данных.

.directive('tree', function ($compile, myService) { 
    return { 
     // ... 
     link: function (scope, element, attrs) { 
      myService.getData().then(function (data) { 
       // ... 
      }, function (err) { 
       // Handle error 
      }); 
     } 
    } 
}); 
+1

Спасибо. Однако проблема заключается в том, что ** директива ** отображает ** выражения **, которые используют данные JSON в области $. Код для вашей ** директивы ** запускается при ** обновлении ** **, но что, если он работает до того, как данные ** службы ** могут быть помещены в $ scope? Это происходит потому, что мои данные извлекаются из ControllerA, но директивы отображаются в ControllerB. I $ смотрите 'myService.getData()' в ControllerB и задайте данные в $ scope. Тем не менее, мои директивы представляют собой рендеринг, прежде чем ControllerB добавит обновленные данные в $ scope. – Jack

0

Я написал короткую функцию, которая позволяет помещать данные в объект без его замены. Вы можете использовать его в своем сервисе. Таким образом, вам не нужно использовать часы. Вы можете использовать обычный цикл дайджеста Angular. Например, увидеть этот простой контроллер & службы:

Demo: JSFidde - http://jsfiddle.net/y09kx7f7/1/ с Assert испытаний

Контроллер:

app.controller('dem',function($scope,me){ 
    $scope.user=me.user; // {name:'user name'} 
}) 

Контроллер будет chnage автоматически без часов каждый раз, когда имя пользователя изменилось!

Сервис

.factory('me',function($timeout){ 
    var obj={} 
    obj.user={name:'hello'} 
    $timeout(function(){ //Example of change the data 
     newUser={name:'israel'} 
     cloneInto(obj.user,newUser) 
    },1000) 
    return obj 
}) 

Функция cloneInto, что я написал:

// The function it is like a=b, 
// but keeping the object in his original memory position. 
function cloneInto(a,b){ 
    var i 
    for (i in a){ 
     if(typeof a[i]!='object') //For supporting deep-copy 
      delete a[i] 
    } 
    for (i in b){ 
     if (typeof b[i]=='object'){ 
      if(!a[i]) a[i]={} 
      cloneInto(a[i],b[i]) 
     } 
     else{ 
      a[i]=b[i] 
     } 
    } 
} 
Смежные вопросы