【问题标题】:Angular.js - ngModel value is undefined when ng-pattern is set in directiveAngular.js - 在指令中设置 ng-pattern 时,ngModel 值未定义
【发布时间】:2017-05-09 03:36:27
【问题描述】:

可能已经回答了类似的问题(ng-pattern + ng-change),但所有响应都无法解决此问题。

我有两个用于创建表单输入的复合指令,一个用于控制名称、标签、验证器等的父指令和一个用于设置模式和输入类型特定内容的子指令。

但是,在设置模式时,当 ng-pattern 返回 false 时,我的模型上的值设置为 undefined。

指令:

<input-wrapper ng-model="vm.customer.phone" name="phone" label="Phone number">
    <input-text type="tel"></input-text>
</input-wrapper>

生成的 HTML:

<label for="phone">Phone number:</label>
<input type="text" name="phone" 
  ng-model="value"
  ng-model-options="{ updateOn: \'blur\' }"
  ng-change="onChange()"
  ng-pattern="/^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/">

JS:

angular.module('components', [])
    .directive('inputWrapper', function() {
    return {
        restrict: 'E',
        require: 'ngModel',
        scope: true,
        link: function (scope, element, attrs, ngModel) {
          scope.name = attrs.name;
          scope.label = attrs.label;

          scope.onChange = function () {
            ngModel.$setViewValue(scope.value);
          };

          ngModel.$render = function () {
            scope.value = ngModel.$modelValue;
          };
        }
    }
    })
  .directive('inputText', function() {
    return {
        restrict: 'E',
        template: '<label for="{{name}}">{{label}}:</label><input type="text" name="{{name}}" ng-model="value" ng-model-options="{ updateOn: \'blur\' }" ng-change="onChange()" ng-pattern="pattern">',
        link: function (scope, element, attrs) {

          if (attrs.type === 'tel') {
            scope.pattern = /^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/;
          }
        }
    }
    });

angular.module('app',['components'])
        .controller('ctrl',function($scope){
          var vm = this;

          vm.customer = {
            phone: '010203040506'
          };
        });

我做错了什么?

用例的代码笔:https://codepen.io/Yosky/pen/yVrmvw

【问题讨论】:

  • 当 ng-pattern 返回 false 时你想要/期望什么行为?
  • 好吧,我的模型值应该是文本输入的当前值,而不是 undefined,因此,我的正则表达式验证失败。
  • 当您传递的值不符合模式时,这是正常的。该模型没有“保存”,因此它没有价值 - 它是未定义的。和官方文档的例子一模一样:docs.angularjs.org/api/ng/directive/ngPattern
  • 你是对的,但是在转储 ngModel.$error 时它显示一个空对象,知道为什么吗?如果我添加一个 required 验证器,它会在输入为空或模式错误时显示 required: true
  • $error 基本上是一个错误条件的容器。例如,如果您检查 $error.pattern 在您的情况下,当您提供不符合模式的值时,它将输出 true 。如果我得到你想要的,即查看用户输入的“错误”值,我认为这样做的方法是在提交值时检查 ngmodel 的 $viewValue

标签: javascript angularjs angularjs-directive angularjs-scope


【解决方案1】:

我有一些要求,这意味着我真的不希望 ng-model 在验证无效时将 undefined 写入范围,我也不想要无效值,所以 allowInvalid 没有帮助。相反,我只是希望 ng-model 不写任何东西,但我找不到任何选项。

所以除了对 ng-model 控制器进行猴子修补之外,我看不到任何前进的方向。

所以我首先在我正在构建的组件中需要 ngModel require: { model: 'ngModel' },然后我在 $onInit 钩子中执行此操作:

const writeModelToScope = this.model.$$writeModelToScope;
const _this = this;
this.model.$$writeModelToScope = function() {
    const allowInvalid = _this.model.$options.getOption('allowInvalid');
    if (!allowInvalid && _this.model.$invalid) {
        return;
    }
    writeModelToScope.bind(this)();
};

我也不想在值无效且组件具有焦点时接受新的模型值,所以我这样做了:

const setModelValue = this.model.$$setModelValue;
this.model.$$setModelValue = function(modelValue) {
    _this.lastModelValue = modelValue;
    if (_this.model.$invalid) {
        return;
    }
    if (_this.hasFocus) {
        return;
    }
    setModelValue.bind(this)(modelValue);
};

element.on('focus', () => {
    this.hasFocus = true;
});

element.on('blur', (event) => {
    this.hasFocus = false;
    const allowInvalid = this.model.$options.getOption('allowInvalid');
    if (!allowInvalid && this.model.$invalid) {
        this.value = this.lastModelValue;
    }
    event.preventDefault();
});

请随意评判我,只要知道我已经感到肮脏。

【讨论】:

    【解决方案2】:

    默认情况下,如果验证器失败,则为 ng-model 分配未定义的值,您可以按如下方式更改此设置:

     <div ng-model-options="{ allowInvalid: true}">
    

    read here for detail docs

    【讨论】:

    • 非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-03
    • 1970-01-01
    • 2016-07-15
    • 1970-01-01
    • 2012-12-14
    相关资源
    最近更新 更多