web-dev-qa-db-ja.com

Angular JS:約束にバインドする方法

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

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

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

編集:解決策:それはあなたを証明しましたcan約束を直接バインドします。元のコードには2つの問題がありました。

  1. アンギュラーの$ timeoutの代わりにsetTimeout()を使用することは問題でした。 Angularは、タイムアウトがトリガーされたときにUIを更新する必要があることを知りません(setTimeout内で$ scope。$ applyを使用することで解決できます。
  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;
    };
}
65
Adam Tegen

[〜#〜] warning [〜#〜]:この回答は書かれた時点では正確でしたが、1.2ではAngularテンプレートエンジンはプロミスを透過的に処理しません!-@ Malvolio

はい、テンプレートエンジン(および式)はプロミスを透過的に処理しますが、新しいプロミスを返す関数を呼び出すたびにプロミスをコントローラーのスコーププロパティに割り当てます(新しいプロミスのため、解決されたプロミスは失われます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 = [];
        }
    });
}​
29
Guillaume86

Angular 1.2、 テンプレートでpromiseを直接使用することはできなくなりました
代わりに、結果を$scope内部then、通常のように-魔法ではありません。

古い動作を得るための一時的な回避策として、次を呼び出すことができます。

$parseProvider.unwrapPromises(true)

ただし、この機能は後で削除されるため、それに依存しないでください。

71
Dan Abramov

Angular 1.3-$parseProvider.unwrapPromises(true)動作しなくなります 現在。

代わりに、約束を直接アンラップする必要があります。

myApiMethod().then(function(value){
    $scope.item = value; 
});

Promiseのアンラップは、通常どおりngResourceで引き続き機能することに注意してください。

27

リストを保持するスコープ変数への参照を返すだけで十分です。

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

    $scope._regions = [];

    $scope.getRegions = function () {

        $timeout(function () {
            var countryRegions = regions[$scope.countryCode];
            console.log(countryRegions);
            if(countryRegions === undefined) {
                $scope._regions = []
            } else {
                $scope._regions = countryRegions
            }
        }, 1000);

        return $scope._regions;
    };
}
0
David Fulgham