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

AngularJS可以做的一件有趣的事情是将过滤器应用于特定的数据绑定表达式,这是一种方便的应用方式,例如,特定于区域性的货币或模型属性的日期格式。在作用域上具有计算属性也很好。问题在于,这两个功能都不适用于双向数据绑定方案 - 仅适用于从范围到视图的单向数据绑定。这似乎是一个优秀的图书馆中明显的遗漏 - 或者我错过了什么?

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

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

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

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

当用户开始键入时,输入元素会变得非常混乱。我通过将属性拆分为两个属性来改进它,一个用于未分析的值,另一个用于解析的值:

$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/)

这是对第一个版本的改进,但更详细一些,请注意,范围更改的属性仍然存在问题(在第二个输入中键入一些内容,直接更改。请注意,顶部输入不会更新)。这可能通过控制器操作或从数据服务加载数据时发生。parsedValueparsedValue

有没有更简单的方法来使用AngularJS实现这个场景?我是否缺少文档中的某些功能?


答案 1

事实证明,有一个非常优雅的解决方案,但它没有得到很好的记录。

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

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) {
            ...
        }
    };
});

3.在方法中,将自定义转换器添加到控制器linkngModel

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 文档还包含其他可用方法的简要说明和概述。


答案 2