簡體   English   中英

我可以使用asyncValidator阻止ng-model更新嗎?

[英]Can I prevent an ng-model update with an asyncValidator?

我有一個應用程序,其中某些選項不能很好地配合使用。 如果用戶選擇了一對可能導致性能不佳的選項,我們將顯示一個對話框 ,其中用戶必須同意承認他們正在請求大量數據,而我們可能無法滿足請求。

由於對話框服務返回的承諾可以根據用戶的意願執行或拒絕,因此在NgModelController上添加異步驗證器似乎是一個不錯的地方。 我寫了一個小插曲,以演示這種情況和我對解決方案的嘗試。

它的膽量是:

HTML

<body ng-controller="MainCtrl as ctrl">
  <br>
  Allow chili
  <input type="checkbox" ng-model="ctrl.allowChili">
  <br>
  <select
      ng-model="ctrl.val"
      ng-model-options="{allowInvalid: false}"
      validate-async="ctrl.validateAsync($modelVal)"
      ng-change="ctrl.tellMe()">
    <option value="very">very</option>
    <option value="chili">chili</option>
    <option value="jalepeno">jalepeno</option>
  </select>
  <br>
  <p>The food is {{ctrl.val}} spicy!</p>
</body>

JS

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

myApp.controller('MainCtrl', ['$q', '$scope', function($q, $scope) {
    this.val = 'very';
    this.allowChili = false;

    this.validateAsync = function(modelVal) {
      console.log(modelVal);
      if (modelVal != 'chili' || this.allowChili) {
        console.log('Accepting validation');
        return $q.when();
      } else {
        console.log('Rejecting validation');
        return $q.reject();
      }
    };

    this.tellMe = function() {
      // In my application, this actually issues an HTTP request to get new
      // data and update the view.
      alert('model value changed');
    };
}]);

myApp.directive('validateAsync', ['$q', function($q) {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: linkFn,
  };
  function linkFn(scope, element, attrs, ngModelCtrl) {
    ngModelCtrl.$asyncValidators.myValidator = function(modelVal, viewVal) {
      var args = {
        '$modelVal': modelVal,
        '$viewVal': viewVal,
      };
      return $q.when(scope.$eval(attrs['validateAsync'], args));
    };
  }
}]);

不幸的是,有一些問題。 當異步驗證器承諾被拒絕時,會發生兩件事:

  1. 更改監聽器(例如ng-change )仍然會觸發,並且我的視圖仍會更新。
  2. 新的模型值似乎是undefined而我想完全阻止它的更改。

NgModelController如何防止基於承諾狀態進行階段性更改?

是一個丑陋駭客 ,我認為我可以適應我的用例。 更改的內容在validateAsync指令中:

myApp.directive('validateAsync', ['$q', function($q) {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: linkFn,
  };
  function linkFn(scope, element, attrs, ngModelCtrl) {
    var ngModelCtrl$setViewValue = ngModelCtrl.$setViewValue;
    ngModelCtrl.$setViewValue = function(value, trigger) {
      var args = {
        '$val': value,
        '$trigger': trigger,
      };
      $q.when(scope.$eval(attrs['validateAsync'], args)).then(function() {
        ngModelCtrl$setViewValue.call(ngModelCtrl, value, trigger);
      });
    };
  }
}]);

(將模板更改為使用$val而不是$modelVal )。

基本上,我要劫持NgModelController.$setViewValue並且如果承諾被拒絕,則不會調用基本實現。 在演示插件中,您將看到select元素仍然更改。 我認為這對我的設計師來說是可以的(如果不是,我可以在用例中對其進行修復,因為我實際上並未使用<select>元素-我使用的是自定義指令來選擇我完全控制何時更新的值)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM