2013-11-27 52 views
17

我正在嘗試關注this SO answer explaining how to render a recursive JSON structure using a directive。但是,與提供的答案不同,我的數據是而不是在DOM加載並且Angular第一次運行時已知。更新服務更改時的Angular JS指令

取而代之,我的數據從HTML輸入字段中檢索並存儲在Angular Service中(當用戶提交表單時)。

當服務的數據被修改時,我怎樣才能保持Angular Directive最新?響應


更新回答

@musically_ut提供了絕佳的答案,它幫助,但透露了一個相關的問題,防止執行(此更新)。

指令呈現HTML,其中包含訪問存儲在$scope中的數據的Angular {{expressions}}。由於服務已準備好數據,因此原始解決方案爲$watch。我如何確保在指令之前將「新」數據添加到$scope之前?

的架構和流程的概要是:

  1. ControllerA - >從用戶獲取輸入
  2. ControllerA - >使用服務轉換數據
  3. ControllerB - 在>$watch更改服務
  4. Directive - >$watch for cha在服務nges
  5. ControllerB - >顯示變換後的數據(從服務)使用 指令

的問題是步驟5和6之間 - >到$scope

  • Directive添加數據。在ControllerB將數據添加到$scope之前,指令呈現{{expressions}}。即使這樣做確實有效,但它感覺太複雜,而且'hacky'。

    實際上,爲了迴歸,我在ControllerB中使用$watch來監聽轉換數據何時準備好在服務中。即使這感覺有點矯枉過正(服務不進行異步調用)。

  • +0

    我在角度新,以及關於看着指示服務改變搜索信息到您的文章。據我瞭解你(根據我最近閱讀的內容),你不應該'在你的** ControllerB **中向範圍添加數據',你最好應該向**服務**報告它,將自動報告給** controllerB **範圍。順便說一句,您將能夠跟蹤** ** ** **(我的意思是輕鬆地跟蹤'external'** 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

    謝謝。但是,問題在於**指令**呈現**表達式**,它們使用$ scope中的JSON數據。你的**指令**的代碼在**服務**更新時運行,但是如果它在**服務**數據可以放在$ scope中之前運行呢?發生這種情況是因爲我的數據是從ControllerA中檢索的,但是指令是在ControllerB中呈現的。我在ControllerB中觀察'myService.getData()'並將數據設置在$ scope中。但是,我的指令在ControllerB將更新後的數據添加到$ scope之前進行渲染。 – Jack

    0

    我已經寫了一個簡短的函數,可以讓你把數據放入Object而不需要替換它。 你可以在你的服務中使用它。這種方式youu不需要使用手錶。您可以使用Angular的正常摘要循環。 例如,看到這個簡單的控制器&服務:

    演示:JSFidde - http://jsfiddle.net/y09kx7f7/1/斷言測試

    控制器:

    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] 
         } 
        } 
    }