Angular.JS:click-to-edit指令表单更新模型,但http.post仍然使用“旧”值

时间:2013-07-23 20:35:34

标签: angularjs angularjs-directive angularjs-scope

我在使用angular.js创建一个click-to-edit指令时遇到了一个奇怪的问题:

模型在表单提交时更新,但更新的模型未在以下http.post中使用,旧的使用旧模型。

例如,在表格中:如果我将第一条记录的“note”字段从“secret”编辑为“myNote”,则bowsers控制台会将“myNote”显示为我项目的comment属性的值,但服务器仍然收到“秘密”。

为了证明这一点,我在github上创建了一个小例子:https://github.com/madmarkus/angular.js-Sample 我将尝试在此处仅显示相关代码。

我的控制器看起来像

function ListCtrl($scope, $http) {
    $http.get('./items.json').success(function (data) {
        $scope.items = data;
    }).error(
        function(){
            console.log("Failed to load items.");
        });

    $scope.saveEditor = function () {

        $scope.saveItem(this.item);
    };

    $scope.saveItem = function (w) {
        console.log("Attempt to safe: ");
        console.log(w);       
        $http.post("http://localhost:8888", w, {}).success(function () {
                console.log("post successfully sent");
        }).error(function (data, status, headers, config) {
                    console.log("Error on save.");
        });

    };
}

和app.js一样

app = angular.module('planner', []).
    config(['$routeProvider', function ($routeProvider) {
        $routeProvider.
            when('/items', {templateUrl: 'item-list.html', controller: ListCtrl}).
            otherwise({redirectTo: '/items'});
    }]);

app.directive("clickToEdit", function() {
    var editorTemplate = '<div>' +
                            '<div ng-hide="view.editorEnabled" ng-click="enableEditor()" class="editable" ' +
                                'style="width: 100%; min-height: 1.5em; display:inline-block" >' +
                                '{{value}} ' +
                            '</div>' +
                            '<form ng-show="view.editorEnabled">' +
                                '<input ng-model="view.editableValue"><br />' +
                                '<button class="btn" ng-click="save()" type="submit">Save</button>' +
                                ' or ' +
                                '<a ng-click="disableEditor()">cancel</a>.' +
                            '</form>' +
                        '</div>';

    return {
        restrict: "A",
        replace: true,
        template: editorTemplate,
        scope: {
            value: "=clickToEdit",
            saveCallback: "&saveFunction"
        },
        controller: function($scope) {
            $scope.view = {
                editableValue: $scope.value,
                editorEnabled: false
            };

            $scope.enableEditor = function() {
                $scope.view.editorEnabled = true;
                $scope.view.editableValue = $scope.value;
            };

            $scope.disableEditor = function() {
                $scope.view.editorEnabled = false;
            };

            $scope.save = function() {
                $scope.value = $scope.view.editableValue;
                $scope.disableEditor();
                $scope.saveCallback();
            };
        }
    };
});

如上所述,当我使用click&amp; edit将第一条记录的音符值从secret更改为myNote时,bowser和控制台中的js调试器显示正确的编辑后值:

[22:24:20.026] Attempt to safe: 
[22:24:20.026] ({id:"977", datetime:"21.07.2013 10:00", note:"myNote", remark:"important", comment:"editme", $$hashKey:"004"})

但是服务器仍然收到“旧”值:

Received body data:
{"id":"977","datetime":"21.07.2013 10:00","note":"secret","remark":"important","comment":"editme"}

从我发现和阅读的内容来看,这可能是我面临的一个范围问题,但我无法找到正确的方法来处理它。还使用$ scope。$ apply()...

任何提示?

对代码的任何评论也非常感谢; - )

非常感谢

Markus

1 个答案:

答案 0 :(得分:1)

你有时间问题。您需要知道,当您要打印的对象发生更改时,chrome会更新console.log中的消息。

当你的指令调用回调时,它没有更新你绑定的值。您可以通过添加带有chrome的断点来看到这一点(将它们放在console.log调用上)。这个问题的一个快速解决方案是在$ timeout内调用回调函数,因为它会导致执行另一个摘要,然后你知道值已经更新了:

controller: function($scope, $timeout) {
    //...

    $scope.save = function() {
        $scope.value = $scope.view.editableValue;
        $scope.disableEditor();
        $timeout(function() {
           $scope.saveCallback();
        });
    };
}