如果模型无效,如何使用最后一个有效的modelValue? [英] How to use the last valid modelValue if a model becomes invalid?

查看:178
本文介绍了如果模型无效,如何使用最后一个有效的modelValue?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个应用程序,当用户更改某些内容(例如输入字段的值)时,该更改会自动保存更改.我写了一个autosave指令,该指令已添加到所有应自动触发保存事件的表单字段中.

I'm working on an application that saves changes automatically when the user changes something, for example the value of an input field. I have written a autosave directive that is added to all form fields that should trigger save events automatically.

模板:

   <input ng-model="fooCtrl.name" autosave>
   <input ng-model="fooCtrl.email" autosave>

指令:

  .directive('autosave', ['$parse', function  ($parse) {

    return {
      restrict: 'A',
      require: 'ngModel',
      link: function (scope, element, attrs, ngModel) {

        function saveIfModelChanged () {
          // save object containing name and email to server ...
        }

        ngModel.$viewChangeListeners.push(function () {
          saveIfModelChanged();
        });
      }
    };
  }]);

到目前为止,这一切对我来说都很好.但是,当我将验证添加到组合中时(例如,将输入字段验证为有效的电子邮件地址),只要将viewValue更改为无效的电子邮件地址,就会将modelValue设置为undefined.

So far, this all works fine for me. However, when I add validation into the mix, for example validating the input field to be a valid email address, the modelValue is set to undefined as soon as the viewValue is changed to an invalid email address.

我想做的是:记住最后一个有效的modelValue,并在自动保存时使用它.如果用户将电子邮件地址更改为无效,则包含nameemail的对象仍应保存到服务器.使用当前有效的name和最后一个有效的email.

What I would like to do is this: Remember the last valid modelValue and use this when autosaving. If the user changes the email address to be invalid, the object containing name and email should still be saved to the server. Using the current valid name and the last valid email.

我首先保存了最后一个有效的modelValue,如下所示:

I started out by saving the last valid modelValue like this:

添加了验证的模板:

   <input type="email" ng-model="fooCtrl.name" autosave required>
   <input ng-model="fooCtrl.email" autosave required>

保存了lastModelValue的指令:

  .directive('autosave', ['$parse', function  ($parse) {

    return {
      restrict: 'A',
      require: 'ngModel',
      link: function (scope, element, attrs, ngModel) {

        var lastModelValue;

        function saveIfModelChanged () {

          // remeber last valid modelValue
          if (ngModel.$valid) {
             lastModelValue = ngModel.$modelValue;
          }

          // save object containing current or last valid
          // name and email to server ...
        }

        ngModel.$viewChangeListeners.push(function () {
          saveIfModelChanged();
        });
      }
    };
  }]);

我的问题是,如何在保存时使用lastModelValue,但在视图中保留无效值?

My question is, how to use lastModelValue while saving, but preserving the invalid value in the view?

另一种可能性是如下面Jugnu所建议的,那就是在验证器中包装和操纵构建.

Another possibility, as suggested by Jugnu below, would be wrapping and manipulating the build in validators.

我尝试执行以下操作:包装所有现有的验证器并记住上一个有效值,如果验证失败将其恢复:

I tried to following: wrap all existing validators and remember the last valid value, to restore it if validations fails:

Object.keys(ngModel.$validators).forEach(function(validatorName, index) {
    var validator = ngModel.$validators[validatorName];
    ngModel.$validators[validatorName] = createWrapper(validatorName, validator, ngModel);
});

function createWrapper(validatorName, validator, ngModel){

  var lastValid;

  return function (modelValue){

    var result = validator(modelValue);

    if(result) {
      lastValid = modelValue;
    }else{
        // what to do here? maybe asign the value like this:
      // $parse(attrs.ngModel).assign(scope, lastValid);
    }

    return result;
  };
}

但是我也不知道如何继续这种方法.我可以在不使用AngularJS的情况下设置模型值并尝试验证新设置的值吗?

But I'm not sure how to continue with this approach either. Can I set the model value without AngularJS kicking in and try to validate that newly set value?

推荐答案

我创建了一个简单的指令,用作 ng-model 指令的包装,并将始终保留最新的有效模型值.它被称为 valid-ng-model ,并且应该在您希望获得最新有效值的地方替换 ng-model 的用法.

I have created a simple directive that serves as a wrapper on the ng-model directive and will keep always the latest valid model value. It's called valid-ng-model and should replace the usage of ng-model on places where you want to have the latest valid value.

我已经创建了一个示例用例此处,希望您会喜欢.欢迎提出任何改进建议.

I've created an example use case here, I hope you will like it. Any ideas for improvements are welcomed.

这是 valid-ng-model 指令的实现代码.

app.directive('validNgModel', function ($compile) {
  return {
      terminal: true,
      priority: 1000,
      scope: {
        validNgModel: '=validNgModel'
      },
      link: function link(scope, element, attrs) {

        // NOTE: add ngModel directive with custom model defined on the isolate scope
        scope.customNgModel = angular.copy(scope.validNgModel);
        element.attr('ng-model', 'customNgModel'); 
        element.removeAttr('valid-ng-model');

        // NOTE: recompile the element without this directive
        var compiledElement = $compile(element)(scope);
        var ngModelCtrl = compiledElement.controller('ngModel');

        // NOTE: Synchronizing (inner ngModel -> outside valid model)
        scope.$watch('customNgModel', function (newModelValue) {
          if (ngModelCtrl.$valid) {
            scope.validNgModel = newModelValue;
          }
        });

        // NOTE: Synchronizing (outside model -> inner ngModel)
        scope.$watch('validNgModel', function (newOutsideModelValue) {
          scope.customNgModel = newOutsideModelValue;
        });
      }
    };
});

没有隔离范围的指令实现:柱塞.

这篇关于如果模型无效,如何使用最后一个有效的modelValue?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆