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 对话框如下所示:

        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范围(我的应用程序只有一个控制器 - 它不是太大)。

所以我们可以说:$rootScope$scope主控制器的父级,同时也是$scope' ngDialogs 的父级$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 回答