2014-07-11 74 views
6

我在表單中遇到一些基本問題。這就是我所做的。Angularjs setValidity導致modelValue不更新​​

我鉤住從這裏這個很酷的指令:https://github.com/TheSharpieOne/angular-input-match

它看起來像這樣:

directive('match', function() { 
    return { 
     require: 'ngModel', 
     restrict: 'A', 
     scope: { 
     match: '=' 
     }, 
     link: function(scope, elem, attrs, ngModel) { 
     scope.$watch(function() { 
      return (ngModel.$pristine && angular.isUndefined(ngModel.$modelValue)) || scope.match === ngModel.$viewValue; 
     }, function(currentValue, previousValue) { 
      ngModel.$setValidity('match', currentValue); 
     }); 
     } 
    }; 
    }); 

從本質上講,這個指令手錶它連接到模型值的元素,並將其與模型匹配屬性中的值。

所以...例如,下面我們拭目以待,看看這兩個密碼相匹配:

Password: <input ng-model="password" type="password" /> 
Confirm: <input ng-model="passwordConfirm" type="password" match="password" /> 

該指令似乎是工作,因爲它集NG-有效匹配和NG-無效適當匹配。

但是,一旦設置爲無效,passwordConfirm模型將不會再次更新。我已經做了一噸console.loggin,在指令看着ngModel,這裏是個什麼樣子當兩個密碼匹配,如:

Constructor {$viewValue: "asdf", $modelValue: undefined, $validators: Object, $parsers: Array[0], $formatters: Array[0]…} 
$$debounceViewValueCommit: function (trigger, revalidate) { 
$$invalidModelValue: "asdf" 
$$lastCommittedViewValue: "asdf" 
$$runValidators: function (modelValue, viewValue) { 
$$validityState: ValidityState 
$$writeModelToScope: function() { 
$commitViewValue: function (revalidate) { 
$dirty: true 
$error: Object 
$formatters: Array[0] 
$invalid: false 
$isEmpty: function (value) { 
$modelValue: undefined 
$name: "passwordConfirmation" 
$parsers: Array[0] 
$pristine: false 
$render: function() { 
$rollbackViewValue: function() { 
$setPristine: function() { 
$setTouched: function() { 
$setUntouched: function() { 
$setValidity: function (validationErrorKey, isValid) { 
$setViewValue: function (value, trigger, revalidate) { 
$touched: true 
$untouched: false 
$valid: true 
$validate: function() { 
$validators: Object 
$viewChangeListeners: Array[0] 
$viewValue: "asdf" 
__proto__: Object 

注意$ viewValue是正確的,但$ modelValue是列爲未定義,$ invalidModelValue仍然有一個值。

這裏的HTML是什麼樣子,又當兩個密碼匹配:

<input type="password" class="form-control ng-isolate-scope ng-dirty ng-valid-required ng-valid ng-valid-match ng-touched" id="passwordConfirmation" name="passwordConfirmation" placeholder="Confirm your password" ng-model="passwordConfirmation" required="" match="password" style=""> 

我缺少的東西的地方?我一直在圈子裏跑幾個小時。

+0

只要值是無效的模型返回未定義的,當它符合標準,則模型更新 – maurycy

+0

權,但形式元素被越來越設置爲有效,所以我希望模型值得到適當更新。 – CTC

+0

「$ modelValue」的設置方式發生了重大變化。如果模型無效,它會將該值設置爲'$$ invalidModelValue' https://github.com/angular/angular.js/commit/f3cb2741161353f387d02725637ce4ba062a9bc0 – TheSharpieOne

回答

3

它看起來也許使用$ setValidity不是去這裏的方式。我發現this question提出了一個不同的解決方案,使用$ validators和$ validate(),這對我來說很好。新代碼如下所示:

directive('match', function() { 
    return { 
    require: 'ngModel', 
    restrict: 'A', 
    scope: { 
     match: '=' 
    }, 
    link: function(scope, elem, attrs, ngModel) { 
     scope.$watch('match', function(pass){ 
     ngModel.$validate(); 
     }); 
     ngModel.$validators.match = function(modelValue, viewValue){ 
     var value = modelValue || viewValue; 
     var match = scope.match; 
     return value === match; 
     }; 
    } 
    }; 
}); 
1

也許您正在使用

scope: { 
    match : "=" 
} 

,對你的指令創建隔離範圍,並從那裏你ngModel是父範圍不herite進行相關的事實。

我建議嘗試刪除指令的範圍部分,然後從屬性訪問它。

它將成爲類似:

directive('match', function() { 
    return { 
     require: 'ngModel', 
     restrict: 'A', 
     link: function(scope, elem, attrs, ngModel) { 
     scope.match = attrs.match; 
     scope.$watch(function() { 
      return (ngModel.$pristine && angular.isUndefined(ngModel.$modelValue)) || scope.match === ngModel.$viewValue; 
     }, function(currentValue, previousValue) { 
      ngModel.$setValidity('match', currentValue); 
     }); 
     } 
    }; 
    }); 
+0

這似乎不工作,因爲attrs.match不是'密碼'的值,它實際上只是字符串'密碼'本身。當我在那裏離開那個範圍聲明時,scope.match等於密碼的模型值,所以這看起來似乎正在工作。 – CTC

+0

你試過範圍嗎?$ eval(attrs.match)? –

6

recent update,一個變化的$modelValue是基於字段的有效性填充的方式進行。如果該字段無效,則$modelValue將設置爲undefined,並且將使用該值填充新屬性$$invalidModelValue。 。

作爲解決與1.2工作* 1.3 *我想出了這一點:

.directive('match', function() { 
    return { 
     require: 'ngModel', 
     restrict: 'A', 
     scope: { 
      match: '=' 
     }, 
     link: function(scope, elem, attrs, ctrl) { 
      scope.$watch(function() { 
       modelValue = ctrl.$modelValue || ctrl.$$invalidModelValue; 
       return (ctrl.$pristine && angular.isUndefined(modelValue)) || scope.match === modelValue; 
      }, function(currentValue) { 
       ctrl.$setValidity('match', currentValue); 
      }); 
     } 
    }; 
}); 

Plunkr

雖然這種解決方案有兩個版本,1.3工作*有新$validators管道,推薦用於新版本。