在AngularJs模型中声明计算字段的正确方法是什么?

时间:2015-03-20 23:03:38

标签: angularjs

如何在AngularJs模型中声明计算字段?如果我这样做:

 $scope.model = {
        id: null,
        calculatedField: function() {
            return 1+2;
        }
    };

然后将整个对象发送到Web服务器,如下所示:

$http.post(url, $scope.model)...

它总是为calculatedField字段值发送null。在将对象序列化为Json时,它似乎需要属性,而不是函数。

更新:我希望每次在Json中序列化模型时自动调用computedField()

4 个答案:

答案 0 :(得分:5)

如果calculatedField的行为与某个值相同,那么只需将其设为getter

$scope.model = {
    id: null,
    get calculatedField() {
        return 1+2;
    }
};

除了不能为其赋值外,您可以像使用常规值属性一样使用它。当然,它也可以正确序列化。

var x = $scope.model.calculatedField; // x = 3

$scope.model.calculatedField = 4; //doesn't change calculatedField

JSON.stringify($scope.model); // "{"id":null,"calculatedField":3}"

Getters是常规的JavaScript btw。

答案 1 :(得分:1)

您已经发现JavaScript和Angular并不真正提供开箱即用的情况。您将不得不在应用程序中以最佳方式做出决定。

控制对象序列化为JSON的最简单方法是添加toJSON() method。这与toString()方法类似,但不是返回字符串表示,而是返回要转换为JSON的对象表示

以下是模型的示例,它将从模型复制到返回对象。但是,对于每个函数,它将输出调用该函数的结果:

$scope.model = {
    id: null,
    calculatedField: function() {
        return 1+2;
    },

    /**
     * Return an object that represents this model 
     * instance and will be converted to JSON.
     */
    toJSON: function(){
        var o = {};
        angular.forEach(this, function(value, key){
            if (angular.isFunction(value)){
                o[key] = value();
            } else {
                o[key] = value;
            }
        }, this);

        return o;
    }
};

JSON序列化结果:

console.log(angular.toJson($scope.model));

/*
{
    "id": null,
    "calculatedField": 3
}
*/

请注意,当对象序列化为JSON时,会自动调用toJSON()方法。这意味着您可以在将其发布到服务器之前忘记调用它

另一件好事是,如果您使用toJSON()方法嵌套对象,它们也会在对象图中一直被调用。

这应该为您提供了一个制定序列化模型的最佳方法的起点。

从这里你可以调整上面的toJSON()示例 - 即是否应该从JSON输出中排除某些方法或属性。

以下是如何过滤掉特定属性/功能的示例:

$scope.model = {
    id: null,
    calculatedField: function() {
        return 1+2;
    },

    // Example function we don't want serialised at all.
    myNonCalculatedField: function(param1, param2){
        return param1 + param2;
    },

    /**
     * Return an object that represents this model 
     * instance and will be converted to JSON.
     */
    '@exclude': {
        '@exclude': false,
        'myNonCalculatedField': false
    },
    toJSON: function(){
        var o = {};

        var excludeMap = this['@exclude'];
        angular.forEach(this, function(value, key){
            // Skip any property that we've marked as excluded.
            if (excludeMap[key] === false){
                return;
            }

            // Copy everything else to the return object.
            if (angular.isFunction(value)){
                o[key] = value();
            } else {
                o[key] = value;
            }
        }, this);

        return o;
    }
};

答案 2 :(得分:0)

使用常规函数而不是匿名函数。

实施例。

    var field = function(){
        return 1+2;
    }
   $scope.model = {
        id: null,
        calculatedField: field()
    };

答案 3 :(得分:0)

var myFun = function() {
                return 1+2;
            };

如果您想发送返回值:

 $scope.model = {
        id: null,
        calculatedField: myFun()
    };

如果您想发送函数的定义:

 $scope.model = {
        id: null,
        calculatedField: myFun.toString()// convert the function to string.
    };

重新计算:

$scope.calculatedField = myFun();
$http.post(url, $scope.model)...

在JS中,如果你想要自动更新之类的东西,可以使用对象首选项:

var var_1 = {a: 123};
var var_2 = var_1;
var_1.a = 456;//change value 'a' in var_1.
console.log(var_2.a)//the value 'a' in var_2 is 456 also.

更新:如果您希望每次更改模型时自动调用computedField(),您可以尝试在angularjs中使用$ watch:

$scope.$watch('modelToWatch', function(newVal, oldVal) {
calculatedField();
});