68

約束をビューにバインドしようとしています。あなたがそれを直接できるかどうかはわかりませんが、それが私がやろうとしていることです. 私が間違っていることは何ですか?

注: ソースはタイムアウトが少し工夫されており、静的データを使用していますが、これはコードの診断を容易にするためです。

編集: JSFiddle ページ: http://jsfiddle.net/YQwaf/27/

編集: 解決策: Promiseを直接バインドできることが判明しました。元のコードには 2 つの問題がありました。

  1. angular の $timeout の代わりに setTimeout() を使用すると問題が発生しました。Angular は、タイムアウトがトリガーされたときに UI を更新する必要があることを認識していません ( setTimeout 内で $scope.$apply を使用してこれを解決するか、単に $timeout を使用することができます)。
  2. promise を返す関数へのバインディングは問題でした。2 回目に呼び出された場合は、さらに別の約束をします。スコープ変数をプロミスに設定し、必要に応じて新しいプロミスを作成することをお勧めします。(私の場合、これは国コードで $scope.$watch を呼び出していました)

HTML:

<div ng:controller="addressValidationController">
    Region Code <select ng:model="regionCode" ng:options="r.code as r.name for r in getRegions()"/>
    Country Code<select ng:model="countryCode"><option value="US">United States</option><option value="CA">Canada</option></select>
</div>

JS:

function addressValidationController($scope, $q) {
    var regions = {
        US: [{code: 'WI',name: 'Wisconsin'}, {code: 'MN',name: 'Minnesota'}], 
        CA: [{code: 'ON',name: 'Ontario'}]
    };
    $scope.getRegions = function () {
        var deferred = $q.defer();
        setTimeout(function () {
            var countryRegions = regions[$scope.countryCode];
            console.log(countryRegions);
            if(countryRegions === undefined) {
                deferred.resolve([]);
            } else {
                deferred.resolve(countryRegions);
            }
        }, 1000);
        return deferred.promise;
    };
}
4

4 に答える 4

29

警告: この回答は作成時には正確でしたが、1.2 の時点では、Angular テンプレート エンジンは透過的にプロミスを処理しません! -- @マルヴォリオ

はい、テンプレートエンジン(および式)は約束を透過的に処理しますが、私は約束をコントローラーのスコーププロパティに割り当て、新しい約束を返す関数を毎回呼び出すのではありません(私はそれがあなたの問題だと思います、解決された約束は新しいpromise は毎回返されます)。

JSFiddle: http://jsfiddle.net/YQwaf/36/

HTML:

<div ng:controller="addressValidationController">
    Region Code <select ng:model="regionCode" ng:options="r.code as r.name for r in regions"/>
    Country Code<select ng:model="countryCode"><option value="US">United States</option><option value="CA">Canada</option></select>
</div>

JS:

function addressValidationController($scope, $q, $timeout) {
    var regions = {
        US: [{
            code: 'WI',
            name: 'Wisconsin'},
        {
            code: 'MN',
            name: 'Minnesota'}],
        CA: [{
            code: 'ON',
            name: 'Ontario'}]
    };

    function getRegions(countryCode) {
        console.log('getRegions: ' + countryCode);
        var deferred = $q.defer();
        $timeout(function() {
            var countryRegions = regions[countryCode];
            if (countryRegions === undefined) {
                console.log('resolve empty');
                deferred.resolve([]);
            } else {
                console.log('resolve');
                deferred.resolve(countryRegions);
            }
        }, 1000);
        return deferred.promise;
    };

    $scope.regions = [];

    // Manage country changes:
    $scope.$watch('countryCode', function(countryCode) {
        if (angular.isDefined(countryCode)) {
            $scope.regions = getRegions(countryCode);
        }
        else {
            $scope.regions = [];
        }
    });
}​
于 2012-10-23T15:23:24.990 に答える