如何在 AngularJS 中进行双向滤波?

AngularJS 可以做的一件有趣的事情是对特定的数据绑定表达式应用过滤器,这是一种方便的应用方式,例如,特定于文化的货币或模型属性的日期格式。在作用域上拥有计算属性也很不错。问题是,这两个特性都不适用于双向数据绑定场景——从作用域到视图的只有单向数据绑定。这似乎是一个明显的遗漏,在一个其他优秀的图书馆-或我错过了什么?

帅哥中,我可以创建一个读/写计算属性,它允许我指定两个函数,一个被调用来获取属性的值,另一个在设置属性时被调用。这允许我实现,例如,文化感知输入——让用户输入“ $1.24”并将其解析为 ViewModel 中的浮点数,并在输入中反映 ViewModel 中的更改。

我能找到的与此类似的最接近的方法是使用 $scope.$watch(propertyName, functionOrNGExpression);,这允许我在 $scope中的属性发生变化时调用一个函数。但这并不能解决,例如,文化感知输入问题。请注意在尝试修改 $watch方法本身的 $watched属性时出现的问题:

$scope.$watch("property", function (newValue, oldValue) {
$scope.outputMessage = "oldValue: " + oldValue + " newValue: " + newValue;
$scope.property = Globalize.parseFloat(newValue);
});

(http://jsfiddle.net/gyZH8/2/)

当用户开始输入时,input 元素会变得非常混乱。我对它进行了改进,将该属性分割为两个属性,一个用于未解析的值,另一个用于解析的值:

$scope.visibleProperty= 0.0;
$scope.hiddenProperty = 0.0;
$scope.$watch("visibleProperty", function (newValue, oldValue) {
$scope.outputMessage = "oldValue: " + oldValue + " newValue: " + newValue;
$scope.hiddenProperty = Globalize.parseFloat(newValue);
});

(http://jsfiddle.net/XkPNv/1/)

与第一个版本相比,这是一个改进,但是有点冗长,并且注意,范围更改的 parsedValue属性仍然存在问题(在第二个输入中输入一些内容,这会直接更改 parsedValue)。注意顶部输入没有更新)。这可能发生在控制器操作或从数据服务加载数据时。

使用 AngularJS 是否有更简单的方法来实现这个场景? 我是否遗漏了文档中的一些功能?

43204 次浏览

事实证明,这个问题有一个非常优雅的解决方案,但是没有很好的文档记录。

用于显示的格式化模型值可以由 |操作符和角 formatter处理。事实证明,ngModel 不仅有一个格式化程序列表,而且还有一个解析器列表。

1. 使用 ng-model创建双向数据绑定

<input type="text" ng-model="foo.bar"></input>

2.在角度模块中创建一个指令,该指令将应用于相同的元素,并且依赖于 ngModel控制器

module.directive('lowercase', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attr, ngModel) {
...
}
};
});

link方法中,将自定义转换器添加到 ngModel控制器

function fromUser(text) {
return (text || '').toUpperCase();
}


function toUser(text) {
return (text || '').toLowerCase();
}
ngModel.$parsers.push(fromUser);
ngModel.$formatters.push(toUser);

4. 将新指令添加到已经具有 ngModel的同一元素

<input type="text" lowercase ng-model="foo.bar"></input>

下面是一个 工作范例,它将 input中的文本转换为小写,然后在模型中转换回大写

模型控制器的 API 文档也有一个简短的解释和其他可用方法的概述。