服务更改时更新Angular JS指令

时间:2013-11-27 22:36:34

标签: angularjs angularjs-directive

我正在尝试关注this SO answer explaining how to render a recursive JSON structure using a directive。但是,与提供的答案不同,当加载DOM并且Angular第一次运行时,我的数据已知。

相反,我的数据从HTML输入字段中检索并存储在Angular服务中(当用户提交表单时)。

如何在修改服务数据时保持Angular Directive的最新状态?


回复时更新

@musically_ut提供了一个很好的答案,但却揭示了一个相关问题,阻止了实施(在此更新)。

指令呈现包含Angular {{expressions}}的HTML,其访问存储在$scope中的数据。由于服务已准备好数据,原始解决方案为$watch。在 指令呈现之前,如何确保将“新”数据添加到$scope

架构和流程概述如下:

  1. ControllerA - >获取用户的意见
  2. ControllerA - >使用服务转换数据
  3. ControllerB - > {strong}
  4. 中的更改$watch
  5. Directive - > {strong}
  6. 中的更改$watch
  7. ControllerB - >将数据添加到$scope
  8. Directive - >使用显示转换后的数据(来自服务指令
  9. 问题出在第5步和第6步之间。指令在ControllerB将数据添加到{{expressions}}之前呈现$scope。即使这确实有效,但感觉太复杂和“黑客”。

    事实上,为了回归,我在ControllerB中使用$watch来监听转换后的数据何时在服务中准备就绪。即使这感觉有点矫枉过正(服务没有异步调用)。

2 个答案:

答案 0 :(得分: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') {
                    // ...
                }
            }
        });
    }
});

这将观察要更改的数据,并在每次数据更改时运行代码。


但是,如果数据在设置一次后没有改变,更好的方法(更有效)是从服务返回一个promise($http方法直接返回一个promise或者您可以使用$q服务创建一个),然后将您的计算添加为数据的延续。

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

答案 1 :(得分:0)

我编写了一个简短的函数,可以将数据放入Object而无需替换它。 您可以在服务中使用它。这样你就不需要使用手表了。您可以使用Angular的正常摘要循环。 例如,看到这个简单的控制器&服务:

演示:JSFidde - http://jsfiddle.net/y09kx7f7/1/ 断言测试

<强>控制器:

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

每次更改用户名时,控制器将自动进行无人值守!

<强>服务

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