【问题标题】:Angular directive change ngmodel value from null to undefined breaks validationAngular 指令将 ngmodel 值从 null 更改为未定义的中断验证
【发布时间】:2016-10-14 14:05:39
【问题描述】:

我创建了一个 plnkr 来描述我的问题:Link to plnkr

问题描述: 我有一个数字字段,其中的值被写入模型。首先,我像第一个输入一样实现了这个功能。这个实现的问题是,如果我输入一些东西然后删除,我有以下模型:

{"firstNumber":null,"secondNumber":64}

不幸的是,对我来说这种表示是不可接受的,我需要以下结果:

{"secondNumber":64}

为此,我采用了指令并实施了第二个字段。现在我收到了正确的输出,但是当我删除该值时,表单变得无效。

我还添加了第三个和第四个输入来证明该指令也破坏了所需的验证。

所以,问题是: 如何改进输入字段以不具有模型

{"firstNumber":null,"secondNumber":64}

但是

{"secondNumber":64}

并且不要破坏 Angular 表单的验证机制。

供参考: 我有以下 HTML:

<body ng-controller="MainCtrl as vm">
<h1>Validating input inside ng-repeat with Angular 1.3</h1>

<form name="vm.myForm" novalidate>
  <input type="number" ng-model="vm.fields.firstNumber" name="firstNumber">
  <input type="number" ng-model="vm.fields.secondNumber" name="secondNumber" null-to-undefined>
  <br>
  <input type="number" ng-model="vm.fields.thirdNumber" name="thirdNumber" ng-required = "true">
  <input type="number" ng-model="vm.fields.fourthNumber" name="fourthNumber" null-to-undefined ng-required="true">
</form>
</body>

以及以下控制器和指令代码:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  var vm = this;

  vm.fields = {};
  vm.fields.firstNumber = 12;
  vm.fields.secondNumber = 24;
  vm.fields.thirdNumber = 64;
  vm.fields.fourthNumber = 128;

});

app.directive('nullToUndefined', function($timeout) {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, elem, attrs, ctrl) {
      ctrl.$parsers.push(function(viewValue, modelValue) {
        if (viewValue === null) {
          $timeout(function() {
            //ctrl.$setValidity('number', true);
          });
          return undefined;
        }
        return viewValue;
      });
    }
  };
});

附言我尽可能地削减代码以从我的主要项目中重现问题。我将不胜感激任何解决方案,但如果有人可以提出解决方案,那就太酷了: 1.表现良好 2. 有角度的行为。

【问题讨论】:

    标签: javascript angularjs angularjs-validation angularjs-forms


    【解决方案1】:

    您可能应该专注于其他解决方案,而不是编写指令。

    您有带有道具的对象(firstNumber,secondNumber,...)。

    您需要使用 Angular 验证属性(是 null 吗?是正确的数字吗?)。

    然后,您需要使用非空值过滤对象道具,而不改变您的模型:您的输入绑定到模型属性,如果您破坏一个属性,Angular 将无法验证并失败。

    我们可以做到:

    • 选择 a.fields 的所有键
    • 迭代所有键、过滤器
    • 我们得到了所有非空键
    • 将非空键减少到一个新对象,而不改变“a”
    const a = {
      fields: {
        a: 1,
        b: 2,
        c: null,
      },
    };
    
    // After form validation
    const newA = Object
      .keys(a.fields)
      .filter(k => a.fields[k] !== null)
      .reduce(
        (accumulator, k) => 
          Object.assign(
            accumulator,
            { 
              fields: Object.assign(accumulator.fields, { [k]: a.fields[k] }) 
            }
          ),
        { fields: {} }
      );
    

    如果您需要过滤 undefined + null,只需对过滤器进行少量检查:

      .filter(k => a.fields[k] != null)
    

    编辑:修复代码。

    【讨论】:

    • 感谢您的回复。不幸的是,我尝试了这段代码并得到错误'prev is undefined'。但是,我检查了另一个代码以从我的对象中删除 null 和 undefiend 值。
    • 它奏效了。但是,对我来说,如果带有指令的选项按建议工作,那么应用它会更好。因此,我将上述解决方案作为临时解决方案。
    • 如果人们需要,我已经修复了“prev is undefined”错误:)。
    猜你喜欢
    • 1970-01-01
    • 2020-06-05
    • 2014-05-03
    • 2016-10-02
    • 1970-01-01
    • 2017-01-02
    • 2015-03-06
    • 2015-01-01
    • 2015-10-18
    相关资源
    最近更新 更多