【问题标题】:How to update both model and view value in Angular directive?如何在 Angular 指令中同时更新模型和视图值?
【发布时间】:2016-11-30 10:25:50
【问题描述】:

提前道歉,指令不是我的强项!

我有一个简单的仅属性指令,其目的是在 blur'ing 字段时自动将字段中的字符串转换为 HH:mm 格式。这是指令:

(function () {

    'use strict';

    angular
        .module('app.format-as-time')
        .directive('formatAsTime', timeDirective);

    timeDirective.$inject = [
        'isValid'
    ];

    function timeDirective (isValid) {

        return {
            require: 'ngModel',
            restrict: 'A',
            link: LinkFunction
        };

        function LinkFunction (scope, elem, attrs, ngModel) {

            elem.bind('blur', function () {

                var currentVal = ngModel.$modelValue,
                    formattedVal = '';

                // Format something like 0115 to 01:15
                if (currentVal.length === 4) {
                    formattedVal = currentVal.substr(0, 2) + ':' + currentVal.substr(2, 2);

                // Format something like 115 to 01:15
                } else if (currentVal.length === 3) {
                    formattedVal = '0' + currentVal.substr(0, 1) + ':' + currentVal.substr(1, 2);

                // Format something like 15 to 00:15
                } else if (currentVal.length === 2) {
                    formattedVal = '00:' + currentVal;
                }

                // If our formatted time is valid, apply it!
                if (isValid.time(formattedVal)) {
                    scope.$applyAsync(function () {
                        ngModel.$viewValue = formattedVal;
                        ngModel.$render();
                    });
                }

            });
        }

    }

}());

以及相关的视图:

<div ng-controller="TestController as test">
    <input type="text"
           maxlength="5"
           placeholder="HH:mm"
           ng-model="test.startTime"
           format-as-time>
    <button ng-click="test.getStartTime()">Get Start Time</button>
</div>

以及相关的控制器:

(function () {

    'use strict';

    angular
        .module('app.testModule')
        .controller('TestController', TestController);

    function TestController () {

        var vm = this;

        vm.startTime = '';

        vm.getStartTime = function () {
            console.log(vm.startTime);
        }

    }

}());

目前,该指令对视图按预期工作,但我的控制器中的模型没有更新,即输入将包含 01:15 但模型将 console.log()115。

我尝试过使用:

scope: {
    ngModel: '='
}

在指令中,但这没有做任何事情。

我这样做是否正确?如果是,我需要添加什么以确保模型和视图保持同步?

如果我以错误的方式执行此操作,那么正确执行此操作的最佳方法是什么?

【问题讨论】:

  • isValid 服务是什么样的?
  • isValid 只是一个工厂,它公开了一些函数来检查值是否有效。 isValid.time() 只是 HH:mm 字符串的简单正则表达式。有趣的是,这就是问题所在。 isValid.time() 在上面的指令中呈现视图时返回 true。但是当随后尝试测试控制器模型 isValid.time() 时返回 false,并显示该模型包含预格式化的值。
  • 代替ngModel.$viewValue = formattedVal;,尝试ngModel.$setViewValue(formattedVal);,它应该通过设置ngModel的正常模型管道运行值。
  • 我以前试过这个,但没有用,但我现在又试了一次,效果很好!我不想承认,但我想我过去尝试这个时可能使用过ngModel.$setViewValue = formattedVal;,所以难怪它不起作用。你介意把这个作为答案,我会接受吗? :)
  • 添加了答案。我很高兴它奏效了,但我觉得你的指令不是我的强项,而且经常让我头晕目眩

标签: angularjs angularjs-directive angular-ngmodel


【解决方案1】:

问题在于这一行ngModel.$viewValue = formattedVal; Angular 有一个用于设置模型值的管道,其中包括通过注册的 $parsers 和 $validators 运行它。设置值的正确方法是调用$setViewValue(formattedVal),它将通过此​​管道运行值。

【讨论】:

  • 谢谢!我已经尝试过了,但它不起作用,但我的语法不正确:ngModel.$setViewValue = formattedVal;
猜你喜欢
  • 2016-08-13
  • 2020-03-03
  • 2014-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-26
  • 2015-11-02
  • 1970-01-01
相关资源
最近更新 更多