AngularJS:$scope.$watch 没有更新从 $resource 获取的自定义指令值 [英] AngularJS : $scope.$watch is not updating value fetched from $resource on custom directive

查看:29
本文介绍了AngularJS:$scope.$watch 没有更新从 $resource 获取的自定义指令值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了自定义指令的问题,这让我很抓狂.我正在尝试创建以下自定义(属性)指令:

angular.module('componentes', []).directive("seatMap", function (){返回 {限制:'A',链接:功能(范围,元素,属性,控制器){功能更新座位信息(范围,元素){var txt = "";for (var i in scope.seats)txt = txt + scope.seats[i].id + " ";$(element).text("座位编号:"+txt);}/*//这是有效的,但有点脏...$timeout(function(){updateSeatInfo(scope,element);}, 1000);*/scope.$watch('seats', function(newval, oldval){console.log(newval, oldval);更新座位信息(范围,元素);});}}});

这个属性类型"指令(称为seatMap)试图显示一个座位ID列表(例如,剧院),我将通过$resource服务(见下面的代码)从服务器获取到一个div(元素).

我将它与这个简单的部分 html 一起使用:

<!-- 这实际上是有效的--><ul><li ng-repeat="seat in座位">{{seat.id}}</li><!-- 这不是……--><div style="border: 1px dotted black" 座位图></div>

这是加载作用域的控制器:

function SeatsCtrl($scope, Seats) {$scope.sessionId = "12345";$scope.zoneId = "A";$scope.seats = Seats.query({sessionId: $scope.sessionId, zoneId: $scope.zoneId});$scope.max_seats = 4;}

其中座位"是一个使用 $resources 从服务器获取 JSON 的简单服务

angular.module('myApp.services', ['ngResource']).工厂('座位',功能($资源){return $resource('json/seats-:sessionId-:zoneId.json', {}, {});});

app.js(asientos_libres.html 是我一直在使用的部分):

angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'componentes']).配置(['$routeProvider',函数($routeProvider){$routeProvider.when('/view1', {templateUrl: 'partials/asientos_libres.html', 控制器: SeatsCtrl});$routeProvider.otherwise({redirectTo: '/view1'});}]);

问题是,即使我在指令的链接函数中设置了scope.$watch",以便范围可以检查seats"属性是否已更改以更新 id 列表,但它不是现在 $scope.seats 正在控制器中发生变化(当我们调用查询"时).

正如您在代码中看到的那样,我尝试使用 $timeout 来延迟updateSeatInfo"的启动,但恐怕这不是迄今为止最明智的解决方案...

我也尝试不发出 JSON 请求,而是在 $scope.seats 中使用硬编码字典并且它可以工作,因此似乎是同步问题.

注意:updateSeatInfo 只是一个测试函数,我将使用的实际函数有点复杂.

知道如何应对吗?

先谢谢你!

编辑 1: 添加了 app.js,我使用路由器调用 SeatsCtrl,感谢 Supr 的建议.但是,我仍然遇到同样的问题.

编辑 2:已解决!(?)好的!看来我找到了一个解决方案,它可能不是最好的,但它工作正常!:)据我在这里看到 http://docs.angularjs.org/api/ng.$超时,我们可以使用 $timeout(setTimeout 的包装器)没有延迟!这很棒,因为我们没有人为地延迟 $timeout 内代码的执行,而是让指令在异步请求完成之前不运行它.

希望它也适用于长时间等待的请求...

如果有人知道更好的修复方法,请告诉!

解决方案

问题是 watch 默认比较引用而不是对象.添加 ,true 到最后让它比较值.

scope.$watch('seats', function(newval, oldval){console.log(newval, oldval);更新座位信息(范围,元素);}, 真的);

I'm having an issue with custom directives that's driving me crazy. I'm trying to create the following custom (attribute) directive:

angular.module('componentes', [])
    .directive("seatMap", function (){
        return {
            restrict: 'A',
            link: function(scope, element, attrs, controller){

                function updateSeatInfo(scope, element){
                    var txt = "";
                    for (var i in scope.seats)
                        txt = txt + scope.seats[i].id + " ";
                    $(element).text("seat ids: "+txt);
                }

                /* 
                    // This is working, but it's kind of dirty...
                    $timeout(function(){updateSeatInfo(scope,element);}, 1000);
                */

                scope.$watch('seats', function(newval, oldval){
                    console.log(newval, oldval);
                    updateSeatInfo(scope,element);
                });
            }
        }
    });

This "attribute-type" directive (called seatMap) is trying to show a list of seat ids (e.g, for a theatre) which I'll fetch from the server via $resource service (see code below) into a div (element).

I'm using it with this simple partial html:

<div>
    <!-- This is actually working -->
    <ul>
        <li ng-repeat="seat in seats">{{seat.id}}</li>
    </ul>

    <!-- This is not... -->
    <div style="border: 1px dotted black" seat-map></div>
</div>

And this is the controller which is loading the scope:

function SeatsCtrl($scope, Seats) {
    $scope.sessionId = "12345";
    $scope.zoneId = "A";
    $scope.seats = Seats.query({sessionId: $scope.sessionId, zoneId: $scope.zoneId});
    $scope.max_seats = 4;
}

Where "Seats" is a simple service using $resources to fetch a JSON from the server

angular.module('myApp.services', ['ngResource'])
    .factory('Seats', function($resource){
        return $resource('json/seats-:sessionId-:zoneId.json', {}, {});
    })
;

app.js (asientos_libres.html is the partial I've been using):

angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'componentes']).
  config(['$routeProvider', function($routeProvider) {
    $routeProvider.when('/view1', {templateUrl: 'partials/asientos_libres.html', controller: SeatsCtrl});
    $routeProvider.otherwise({redirectTo: '/view1'});
  }]);

The problem is, even though I set up a "scope.$watch" in the link function of the directive so that the scope can check whether "seats" attribute has changed to update the list of ids, it isn't working at the moment $scope.seats is changing in the controller (when we call "query").

As you might see in the code, I made a try using $timeout to delay the launch of "updateSeatInfo", but I'm afraid it's not the smartest solution by far...

I also tried to not to make a JSON request, but use a hard-coded dictionary in $scope.seats and it works, so it seems it's a matter of synchrony.

Note: The updateSeatInfo is just a test function, the actual function I'll use is a bit more complex.

Any idea about how to cope with it?

Thank you a lot beforehand!

Edit 1: Added app.js, where I'm using router to call SeatsCtrl, thanks to Supr for the advice. However, I'm still having the same issue.

Edit 2: Solved!(?) Ok! It seems I found a solution, which may not be the best, but it's working properly! :) As far as I could see here http://docs.angularjs.org/api/ng.$timeout, we can use $timeout (a wrapper over setTimeout) with no delay! This is great because we aren't artificially delaying the execution of our code inside $timeout, but we're making the directive not to run it until the asynchronous request has finished.

Hope it will work for long-wait requests, too...

If someone knows a better way to fix it, please tell!

解决方案

The issue is that watch compares the reference instead of the object by default. Add ,true to the end to have it compare the value instead.

scope.$watch('seats', function(newval, oldval){
                console.log(newval, oldval);
                updateSeatInfo(scope,element);
            }, true);

这篇关于AngularJS:$scope.$watch 没有更新从 $resource 获取的自定义指令值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆