1

$rootScope.$apply()ラッピング呼び出し (SDK.api) によってラップされる関数があります。

SDK.api('/me', function(response) {
    //THIS callback, anonymous function, is wrapped by SDK in $rootScope.$apply
    $scope.form = {
       'first_name' : response.first_name,
       'last_name' : response.last_name,
       'email' : response.email
    };
    $scope.formEnabled = true;
    $scope.formFetching = false;
});

実際、これは Facebook JS SDK (プレーンな FB オブジェクトではない) のラッパーであり、そのような関数は のコンテキストで呼び出されます$rootScope.$apply()$scope.$apply()そのような関数の最後でを使用するとエラーが発生するため、これを確認でき"inprog"ます (つまり、 への呼び出し$apply内で呼び出すことはできません$apply)。

コード内のこの$scopeオブジェクト (つまり、ここに記述したコード チャンク) は、ngDialogプラグイン用に作成したコントローラーに属しています。ng-dialog は次のようになります。

        return ngDialog.open({
            template: url + 'partials/dialog-form.html',
            className: 'ngdialog-theme-plain',
            scope: $scope,
            closeByDocument: true,
            closeByEscape: true,
            showClose: true,
            cache: false,
            controller: ['$scope', '$http', function($scope, $http) {
                /* ... more ... */
                $scope.formFetching = true;
                $scope.formEnabled = false;
                $scope.success = false;
                SDK.api('/me', function(response) {
                    $scope.form = {
                        'first_name' : response.first_name,
                        'last_name' : response.last_name,
                        'email' : response.email
                    };
                    $scope.formEnabled = true;
                    $scope.formFetching = false;
                });
                /* ... more ... */
            }]
        })

$scopeinはメインコントローラーからのscope: $scopeスコープです (私のアプリにはコントローラーが 1 つしかありません - 大きすぎません)。

したがって、次のように言えます:$rootScope$scopeメイン コントローラーの親であり、同時に の の親でも$scopeあります。ngDialog$scope

grandchild$scopeでは、formデータが更新されます。

$scope.form = {
    'first_name' : response.first_name,
    'last_name' : response.last_name,
    'email' : response.email
};

url + 'partials/dialog-form.html'そして、実際に存在してレンダリングされるテンプレートがあります。内容は次のとおりです(不要なコードは省略します)。

<div id="pedido">
    <form novalidate ng-submit="submitForm()">
        <!-- more code -->
        <table width="100%">
            <!-- more code -->
            <tbody>
                <tr>
                    <td>Nombre:</td>
                    <td>
                        <input type="text" ng-model="form.first_name" />
                        <span ng-repeat="error in errors.first_name" class="error">{{ error }}</span>
                    </td>
                </tr>
                <tr>
                    <td>Apellido:</td>
                    <td>
                        <input type="text" ng-model="form.last_name" />
                        <span ng-repeat="error in errors.last_name" class="error">{{ error }}</span>
                    </td>
                </tr>
                <tr>
                    <td>Correo electr&oacute;nico:</td>
                    <td>
                        <input type="text" ng-model="form.email" />
                        <span ng-repeat="error in errors.email" class="error">{{ error }}</span>
                    </td>
                </tr>
                <!-- more code -->
            </tbody>
        </table>
        <!-- more code -->
    </form>
</div>

の値を仮定するとng-submitng-repeat存在します。

私の問題: のフィールドにng-model値が入力されていません$scope.form

私の質問:何が間違っていますか?フォームは正常に機能し、サーバー側のデータは正常に受信されます。*** での私の唯一の問題は、これらのフィールドが$rootScope.$apply呼び出されたときに反映されないことです-Facebook から事前に入力されたそのようなフィールドが必要です (Facebook からそのようなデータを取得するのに問題はありません: $window.console.log)。

付録の編集: API 呼び出し

var SDK = function($scope) {
    this.$scope = $scope;
    this._initialized = false;
    this._calls = [];
};
/* ... */
SDK.prototype.api = function(path, method, params, callback) {
    var c = this;
    this._makeCall(function(){
        FB.api(
            c.wrap(path),
            c.wrap(method),
            c.wrap(params),
            c.wrap(callback)
        );
    });
};
/* ... */
SDK.prototype.wrap = function(call) {
    var c = this;
    return (typeof call !== 'function') ? call : function(){
        c.$scope.$apply(call);
    };
};
/* ... */
FBModule.factory('AngularFB.SDK', ['$rootScope', sdk]);
4

2 に答える 2

1

エラーが見つかりました。$rootScope.$apply とは関係ありませんでした。

これでラップされた関数:

SDK.prototype.wrap = function(call) {
    var c = this;
    return (typeof call !== 'function') ? call : function(){
        c.$scope.$apply(call);
    };
};

パラメータをプロキシしませんでした。call$apply に渡され、$rootScope 自体である最初のパラメーターが渡されます。そのため、クロージャの「別のレイヤー」を使用し、ラッピング関数が受け取ったパラメーターを明示的に渡す必要がありました。

SDK.prototype.wrap = function(call) {
    var c = this;
    return (typeof call !== 'function') ? call : function(){
        /* copy the params into a new object */
        var args = [];
        angular.forEach(arguments, function(argument) {
            args.push(c.wrap(argument));
        });
        /* the applied call takes the params and creates a 0-arity function to be applied, which takes the task of calling the target function with the passed params */
        c.$scope.$apply(function(){
            call.apply(null, args);
        });
    };
};

だから-私が思ったように-Angularには何も問題はありませんでしたが、渡されたパラメーターが期待されたものではないことを理解するのに多くの時間がかかりました。

解決策: 呼び出しをプロキシして、渡されたパラメーターをブリッジしていることを確認します

于 2014-10-02T20:55:53.217 に答える
0

これが機能するかどうかはわかりませんが、API 呼び出しの前にフォーム オブジェクトを作成してみてください。

$scope.success = false;
$scope.form = {}; //try creating the object here
SDK.api('/me', function(response) {
    $scope.$apply(function () {
        //and update it here
        $scope.form.first_name = response.first_name;
        $scope.form.last_name = response.last_name;
        $scope.form.email = response.email;

        $scope.formEnabled = true;
        $scope.formFetching = false;
    });
});
于 2014-10-02T18:57:08.167 に答える