【问题标题】:Angular filter not working角度过滤器不起作用
【发布时间】:2023-04-03 05:26:01
【问题描述】:

我正在编写一个过滤器,它将在我建立的联系表单中格式化电话号码,但是由于某种原因,输入中的值永远不会更新,我不确定我做错了什么。

这是我的 HTML:

<div class='form-group'>
    <input name='phone' ng-model='home.contact.phone' placeholder='(Area code) Phone' required ng-bind='home.contact.phone | phone' />
</div>

这是我的过滤器:

(function () {
    'use strict'

    angular
        .module('Allay.phoneFilter', [])
        .filter('phone', function () {
            return function (phone) {
                if(!phone) return '';

                var res = phone + '::' // Since this isn't working, I'm doing something super simple, adding a double colon to the end of the phone number.
                return res;
            }
        });
})();

我不确定你是否需要这个,但这是控制器:

(function () {
    'use strict'

    angular
        .module('Allay', [
            'Allay.phoneFilter'
        ])
        .controller('HomeController', function () {
            var home = this;
        });
})();

如果我在过滤器中的 'return res' 之前添加一个 alert(res),我会看到我期望的值 '123::',但是输入中它自身的值仍然只是 123。

【问题讨论】:

  • 我会在哪里做呢?我在文档中没有看到任何关于需要 $scope.$apply() 和过滤器的内容。
  • 好的,由于您只是更改了问题的内容以使我的答案无效,因此我将假设其他答案之一会有所帮助。

标签: angularjs data-binding filter angular-ngmodel


【解决方案1】:

您需要创建指令来更改您的 ngModel,如下所示:

.directive('phoneFormat', function() {
     return {
         require: 'ngModel',
         link: function(scope, elem, attrs, ctrl) {

             var setvalue = function() {
                 elem.val(ctrl.$modelValue + "::");
             };

             ctrl.$parsers.push(function(v) {
                 return v.replace(/::/, '');
             })


             ctrl.$render = function() {
                 setvalue();
             }

             elem.bind('change', function() {
                 setvalue();
             })

         }
     };
 });

在html中使用:

<input name='phone' ng-model='contact.phone' placeholder='(Area code) Phone' required phone-format />

JS 小提琴:http://jsfiddle.net/57czd36L/1/

【讨论】:

  • 不需要创建指令,他使用过滤器的方法是正确的。
  • @Cyber​​delphos 这是您的解决方案jsfiddle.net/wuxfurdn,在控制台中出现错误 - 不可分配的模型表达式:contact.phone |电话 ()
  • 我认为这个想法是使用指令来修改 DOM 行为或向控制器添加行为,并在转换值时使用过滤器,例如我正在做的。
  • 我试过了,但是它似乎没有观察 home.contact.phone 的变化,因为 :: 仅添加到初始化值中,并且在您编辑值时不会添加。
  • 既然是输入,那么就需要一个指令,你是对的Bartosz
【解决方案2】:

您应该删除您的“ng-bind”,因为您正在过滤它,并且呈现的是 ng-model 中的内容。改为使用值。

    <input name='phone' ng-model='home.contact.phone | phone' value="{{contact.phone | phone}}"  />

查看工作示例:JsFiddle

【讨论】:

  • 他已经更改/更正了他的问题中的双模块定义......所以这里只有你的第一点适用......
  • 由于某种原因,您的示例中的输入无法更改。它被固定为它初始化的任何值。
  • 我看到它可以使用 $scope 工作,这很奇怪,但无论如何角度最佳实践都说不要以这种方式使用 $scope,因此 var home = this; (最佳实践)
  • @efarley - 更新了我的小提琴。现在它不使用 $scope。
【解决方案3】:

虽然过滤器模块是一个很好的方法,但我使用'A' 指令来完成这项繁琐的工作,因为更改元素值会影响其 ng-model。

但是,如果您的实际数据操作可以总结为 3-4 行代码,我只会建议这种解决方案;否则,需要更彻底的方法。 这是一个将删除任何非整数的示例:

(function () {
    'use strict'
    angular.module('Allay').directive('phoneValidator', function () {
        return {
            restrict: 'A',
            link: function(scope, element, attrs) {
                angular.element(element).on('keyup', function() {
                    element.val(element.val().replace(/[^0-9\.]/, ''));
                });
            }
        }
    });
})();

比在你的 HTML 模板中:

<input name="phone" ng-model="home.contact.phone" placeholder="(Area code) Phone" phoneValidator required/>`

【讨论】:

    【解决方案4】:

    您在输入中对ngBind 的使用并不完全正确。从文档中,

    ngBind 属性告诉 Angular 将指定 HTML 元素的文本内容替换为给定表达式的值,并在该表达式的值更改时更新文本内容

    您不需要替换&lt;input&gt; 元素的文本内容,那没有意义。您可以改为使用类似的指令扩展NgModelController 的格式化程序管道

    app.directive('phoneFormat', function () {
        return {
            restrict: 'A',
            require: 'ngModel',
            link: function (scope, element, attrs, ngModel) {
                ngModel.$formatters.push(function (value) {
                    if (value)
                        return value + '::';
                });
            }
        }
    });
    

    然后,在您的 HTML 中,

    <input ng-model='home.contact.phone' phone-format />
    

    如果您想保留您编写的过滤器(用于其他用途),您实际上可以在指令中重新使用它,例如

    app.directive('phoneFormat', [ '$filter', function ($filter) {
        return {
            restrict: 'A',
            require: 'ngModel',
            link: function (scope, element, attrs, ngModel) {
                ngModel.$formatters.push($filter('phone'));
            }
        }
    }]);
    

    $filter('phone') 只是返回'phone' 下注册的过滤函数。这是Plunker


    注意,这个解决方案只有在你更改NgModelController$modelValue时才会格式化数据,例如像

    $scope.$apply('home.contact.phone = "123-456-7890"');
    

    如果您正在寻找在用户输入时更新/格式化输入值的东西,这是一项更复杂的任务。我建议使用 angular-ui/ui-mask 之类的东西。

    【讨论】:

    • @xRoyDot,同意你的观点,这是一个正确的方向。但是,在用户键入时“屏蔽”输入值是一项众所周知的难以做好的任务。如果操作不当,对用户来说非常非常烦人。例如,您必须担心在编辑输入的中间时保留光标位置。 ui-mask 确实能很好地完成任务。
    猜你喜欢
    • 2016-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-09
    • 2016-09-26
    • 1970-01-01
    • 2021-08-12
    • 2014-09-01
    相关资源
    最近更新 更多