在Angular中,给定一个对象数组和一个输入,如何绑定输入以便它表示所有对象的给定属性?

时间:2014-03-26 11:04:53

标签: javascript angularjs

给定一个对象数组(例如,表示选择项目)和输入,如何绑定输入值以便它表示所有对象的给定属性?

输入应以以下方式显示状态:

  • 如果此属性的所有值在所有对象上都相同,则显示该值
  • 如果至少有一个值不相同,请将input.value设置为' multiple'
  • 如果所有值都未定义,请将input.value设置为' none'

我有一个函数聚合在范围上公开的给定属性的值:

// Return value (if all values are equal) or undefined (if not)
scope.getSelection('property')

我还有一个在所有对象上设置值的函数:

scope.setSelection('property', value)

我找不到组合ng-value,ng-model和ng-change,它允许我自动从.getSelection()获取并设置为.setSelection(),所以我假设我必须写一个新的指令。

解决这个问题的惯用方法是什么?

1 个答案:

答案 0 :(得分:2)

为了将来参考,让我写一个完整的答案:

在相当现代的浏览器中实现此目的的一种方法是使用属性getter / setters(spec)。一个示例,概念验证实现将是:

假设$scope包含以下集合:

$scope.items = [
    {id: 1, prop: "a"},
    {id: 2, prop: "a"},
    {id: 3, prop: "a"}
];

我们想要操纵item.prop属性的聚合。我们将另一个对象定义为:

$scope.form = {
    get aggregate() {
        var res, i;
        for( i=0; i < $scope.items.length; i++ ) {
            if( typeof(res) === "undefined" ) {
                res = $scope.items[i].prop;
            }
            else if( $scope.items[i].prop !== res ) {
                return "(multiple)";
            }
        }
        return res;
    },
    set aggregate(val) {
        var i;
        for( i=0; i < $scope.items.length; i++ ) {
            $scope.items[i].prop = val;
        }
    }
};

form.aggregate属性现在有一个getter和setter。这些函数通过迭代$scope.items来处理它们的值。 getter比较值并返回公共值,如果全部相同则返回"(multiple)"(如果至少有一个不同)。 setter只是将给定值设置为所有属性。

小提琴:http://jsfiddle.net/52HE6/

改进的(IMO)版本,使用占位符代替文字"(multiple)"http://jsfiddle.net/52HE6/1/

这种模式可能是通用的/参数化的(即没有固定名称prop),例如as(警告:UNTESTED):

function aggregatorFactory($scope, collectionName, propName) {
    return {
        get aggregate() {
            var res, i;
            for( i=0; i < $scope[collectionName].length; i++ ) {
                if( typeof(res) === "undefined" ) {
                    res = $scope[collectionName][i][propName];
                }
                else if( $scope[collectionName][i][propName] !== res ) {
                    return "(multiple)";
                }
            }
            return res;
        },
        set aggregate(val) {
            var i;
            for( i=0; i < $scope[collectionName].length; i++ ) {
                $scope[collectionName][i][propName] = val;
            }
        }
    };
}