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

IT技术 javascript angularjs data-binding angularjs-scope
2021-01-24 22:23:09

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

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

我能找到的与此类似的最接近的事情是使用$scope.$watch(propertyName, functionOrNGExpression);This 允许我在$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/ )

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

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

1个回答

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

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

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

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

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

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

3. 在该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 文档也有一个简短的解释和其他可用方法的概述。

此技术记录在docs.angularjs.org/guide/forms的自定义验证部分。
2021-03-18 22:23:09
您是否有任何理由使用“ngModel”作为链接函数中第四个参数的名称?这不就是指令的通用控制器,基本上与 ngModel 属性无关吗?(仍然在这里学习 angular 所以我可能完全错了。)
2021-03-23 22:23:09
@rajkamal,由于 loadData2()$scope直接修改,这就是模型将设置为......直到用户与文本框交互。此时,任何解析器都可以影响模型值。除了解析器之外,您还可以向控制器添加 $watch 以转换模型值。
2021-04-09 22:23:09
即,foo.bar的控制器,这是一个实例- ,逻辑函数的第四个参数将是ngModel指令的控制器:因为“‘ngModel’规定”的ngModelController您可以随意命名第 4 个参数。(我会命名它ngModelCtrl。)
2021-04-10 22:23:09
提供的小提琴中的@Mark Rajcok,同时单击“加载数据”-全部小写,我预计模型值将全部大写,但模型值很小。你能请。解释原因以及如何使模型始终大写
2021-04-11 22:23:09