如何在 AngularJS 中进行双向过滤? [英] How to do two-way filtering in AngularJS?

查看:24
本文介绍了如何在 AngularJS 中进行双向过滤?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

One of the interesting things AngularJS can do is apply a filter to a particular databinding expression, which is a convenient way to apply, for example, culture-specific currency or date formatting of a model's properties. It is also nice to have computed properties on the scope. The problem is that neither of these features work with two-way databinding scenarios - only one-way databinding from the scope to the view. This seems to be a glaring omission in an otherwise excellent library - or am I missing something?

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

In KnockoutJS, I could create a read/write computed property, which allowed me to specify a pair of functions, one which is called to get the value of the property, and one which is called when the property is set. This allowed me to implement, for example, culture-aware input - letting the user type "$1.24" and parsing that into a float in the ViewModel, and have changes in the ViewModel reflected in the input.

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

The closest thing I could find similar to this is the use of $scope.$watch(propertyName, functionOrNGExpression); This allows me to have a function invoked when a property in the $scope changes. But this doesn't solve, for example, the culture-aware input problem. Notice the problems when I try to modify the $watched property within the $watch method itself:

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

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

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

The input element gets very confused when the user starts typing. I improved it by splitting the property into two properties, one for the unparsed value and one for the parsed value:

$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.注意顶部输入不会更新).这可能发生在控制器操作或从数据服务加载数据时.

This was an improvement over the first version, but is a bit more verbose, and notice that there is still an issue of the parsedValue property of the scope changes (type something in the second input, which changes the parsedValue directly. notice the top input does not update). This might happen from a controller action or from loading data from a data service.

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

Is there some easier way to implement this scenario using AngularJS? Am I missing some functionality in the documentation?

推荐答案

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

It turns out that there's a very elegant solution to this, but it's not well documented.

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

Formatting model values for display can be handled by the | operator and an angular formatter. It turns out that the ngModel that has not only a list of formatters but also a list of parsers.

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

2.在您的 angular 模块中创建一个指令,该指令将应用于相同的元素并且取决于 ngModel 控制器

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

3.在 link 方法中,将您的自定义转换器添加到 ngModel 控制器

3. Within the link method, add your custom converters to the ngModel controller

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

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

4.将您的新指令添加到已经具有 ngModel

的同一元素

4. Add your new directive to the same element that already has the ngModel

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

这是一个工作示例,可将输入 并在模型中返回大写

Here's a working example that transforms text to lowercase in the input and back to uppercase in the model

模型控制器的 API 文档也有简要说明和其他可用方法的概述.

The API Documentation for the Model Controller also has a brief explanation and an overview of the other available methods.

这篇关于如何在 AngularJS 中进行双向过滤?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆