2015-06-23 54 views
17

我有一個角度的形式。這些字段使用ng-pattern屬性進行驗證。我也有一個重置按鈕。我使用的是​​3210處理reset事件,像這樣:如何重置表單,包括刪除所有驗證錯誤?

<form name="searchForm" id="searchForm" ui-event="{reset: 'reset(searchForm)'}" ng-submit="search()"> 
    <div> 
    <label> 
     Area Code 
     <input type="tel" name="areaCode" ng-model="areaCode" ng-pattern="/^([0-9]{3})?$/"> 
    </label> 

    <div ng-messages="searchForm.areaCode.$error"> 
     <div class="error" ng-message="pattern">The area code must be three digits</div> 
    </div> 
    </div> 

    <div> 
    <label> 
     Phone Number 
     <input type="tel" name="phoneNumber" ng-model="phoneNumber" ng-pattern="/^([0-9]{7})?$/"> 
    </label> 

    <div ng-messages="searchForm.phoneNumber.$error"> 
     <div class="error" ng-message="pattern">The phone number must be seven digits</div> 
    </div> 
    </div> 

    <br> 
    <div> 
    <button type="reset">Reset</button> 
    <button type="submit" ng-disabled="searchForm.$invalid">Search</button> 
    </div> 
</form> 

正如你所看到的,當表單被重置它呼籲$scopereset方法。這裏是整個控制器的樣子:

angular.module('app').controller('mainController', function($scope) { 
    $scope.resetCount = 0; 

    $scope.reset = function(form) { 
     form.$setPristine(); 
     form.$setUntouched(); 
     $scope.resetCount++; 
    }; 

    $scope.search = function() { 
     alert('Searching'); 
    }; 
}); 

我打電話form.$setPristine()form.$setUntouched,以下從another question這裏對堆棧溢出的意見。我添加計數器的唯一原因是要證明代碼正在被調用(它是什麼)。

問題是,即使重新設置窗體後,驗證消息也不會消失。您可以在Plunker上看到完整的代碼。下面是顯示該錯誤不會消失截圖:

Validation Errors

+2

只有似乎事爲我工作是手動重置每個表單變量(即'form.areaCode ='';'和'form.phoneNumber ='';')。這就是你通常會這樣做的方式。 – Brett

回答

19

我開始從@Brett評論,並在其建造的。我實際上有多種形式,每種形式都有很多領域(不僅僅是所示的兩個領域)。所以我想要一個通用解決方案。

我注意到角度form對象具有每個控件(input,select,textarea等)以及其他一些Angular屬性的屬性。每個Angular屬性都以一個美元符號開頭($)。所以最後我做這個(包括其他程序員的利益,評論):

$scope.reset = function(form) { 
    // Each control (input, select, textarea, etc) gets added as a property of the form. 
    // The form has other built-in properties as well. However it's easy to filter those out, 
    // because the Angular team has chosen to prefix each one with a dollar sign. 
    // So, we just avoid those properties that begin with a dollar sign. 
    let controlNames = Object.keys(form).filter(key => key.indexOf('$') !== 0); 

    // Set each control back to undefined. This is the only way to clear validation messages. 
    // Calling `form.$setPristine()` won't do it (even though you wish it would). 
    for (let name of controlNames) { 
     let control = form[name]; 
     control.$setViewValue(undefined); 
    } 

    form.$setPristine(); 
    form.$setUntouched(); 
}; 
+4

注意別人,這種方法可以有效地總結如下:「'form. $ setPristine()'不會清除錯誤,你必須將所有的表單控件明確地設置爲'undefined'」。 – rinogo

+0

'未定義'是不可能的!稍後再次讓該字段重新驗證自己,似乎不可能,只能訪問表單數據。不知道如果我錯過了...... :(我已經嘗試過'form.Field。$ setDirty(true); form.Field。$ validate(); form。$ setSubmitted();'它並不工作。 – user2173353

4

您可以添加驗證標誌和顯示或根據其與你的HTML ng-ifng-show值隱藏的錯誤。表單有一個$有效的標誌,你可以發送給你的控制器。

ng-if將刪除或重新創建元素到DOM,而ng-show將添加它,但不會顯示它(取決於標誌值)。

編輯:正如邁克爾指出的,如果表單被禁用,我指出的方式將無法工作,因爲表單從未提交。相應地更新了代碼。

HTML

<form name="searchForm" id="searchForm" ui-event="{reset: 'reset(searchForm)'}" ng-submit="search()"> 
    <div> 
    <label> 
     Area Code 
     <input type="tel" name="areaCode" ng-model="areaCode" ng-pattern="/^([0-9]{3})?$/"> 
    </label> 

    <div ng-messages="searchForm.areaCode.$error"> 
     <div class="error" ng-message="pattern" ng-if="searchForm.areaCode.$dirty">The area code must be three digits</div> 
    </div> 
    </div> 

    <div> 
    <label> 
     Phone Number 
     <input type="tel" name="phoneNumber" ng-model="phoneNumber" ng-pattern="/^([0-9]{7})?$/"> 
    </label> 

    <div ng-messages="searchForm.phoneNumber.$error"> 
     <div class="error" ng-message="pattern" ng-if="searchForm.phoneNumber.$dirty">The phone number must be seven digits</div> 
    </div> 
    </div> 

    <br> 
    <div> 
    <button type="reset">Reset</button> 
    <button type="submit" ng-disabled="searchForm.$invalid">Search</button> 
    </div> 
</form> 

JS

$scope.search = function() { 
    alert('Searching'); 
}; 

$scope.reset = function(form) { 
    form.$setPristine(); 
    form.$setUntouched(); 
    $scope.resetCount++; 
}; 

Codepen與工作液:http://codepen.io/anon/pen/zGPZoB

+0

使用此解決方案,您將看不到任何錯誤,因爲** Search **按鈕被禁用,您無法觸發「搜索」功能來顯示錯誤。另一個簡單的方法是檢查輸入字段是否髒:'ng-if =「searchForm.phoneNumber。$ dirty」' – Michael

+1

錯過了ng-disabled,我的錯誤,我會用你的建議Michael更新代碼。感謝您指出了這一點。 – Ariel

+0

我不想隱藏驗證消息,因爲@Michael指出,只要表單無效,我就會禁用提交按鈕。我需要表單在復位後實際上是有效的(而不僅僅是有效的)。 – battmanz

5

似乎有沒有在角重置$錯誤的簡單方法。最好的方法可能是重新加載當前頁面,以新的表單開始。另外,您都必須使用該腳本手動刪除所有$錯誤:

form.$setPristine(true); 
form.$setUntouched(true); 

// iterate over all from properties 
angular.forEach(form, function(ctrl, name) { 
    // ignore angular fields and functions 
    if (name.indexOf('$') != 0) { 
    // iterate over all $errors for each field   
    angular.forEach(ctrl.$error, function(value, name) { 
     // reset validity 
     ctrl.$setValidity(name, null); 
    }); 
    } 
}); 
$scope.resetCount++; 
0

你可以通過你的登錄表單對象插入功能ng-click="userCtrl.login(loginForm) 並在函數調用

this.login = function (loginForm){ 
    loginForm.$setPristine(); 
    loginForm.$setUntouched(); 
} 
+1

沒有解決手頭上的問題 – Vasily

2

它看起來像我該怎麼做在重置正確的行爲。不幸的是,使用標準重置失敗。我也不包括圖書館ui-event。所以我的代碼與你的代碼有一點不同,但它能滿足你的需求。

<form name="searchForm" id="searchForm" ng-submit="search()"> 
    pristine = {{searchForm.$pristine}} valid ={{searchForm.$valid}} 
    <div> 
    <label> 
     Area Code 
     <input type="tel" required name="areaCode" ng-model="obj.areaCode" ng-pattern="/^([0-9]{3})?$/" ng-model-options="{ allowInvalid: true }"> 
    </label> 

    <div ng-messages="searchForm.areaCode.$error"> 
     <div class="error" ng-message="pattern">The area code must be three digits</div> 
     <div class="error" ng-message="required">The area code is required</div> 
    </div> 
    </div> 

    <div> 
    <label> 
     Phone Number 
     <input type="tel" required name="phoneNumber" ng-model="obj.phoneNumber" ng-pattern="/^([0-9]{7})?$/" ng-model-options="{ allowInvalid: true }"> 
    </label> 

    <div ng-messages="searchForm.phoneNumber.$error"> 
     <div class="error" ng-message="pattern">The phone number must be seven digits</div> 
     <div class="error" ng-message="required">The phone number is required</div> 
    </div> 
    </div> 

    <br> 
    <div> 
    <button ng-click="reset(searchForm)" type="reset">Reset</button> 
    <button type="submit" ng-disabled="searchForm.$invalid">Search</button> 
    </div> 
</form> 

和JS:

$scope.resetCount = 0; 
$scope.obj = {}; 
$scope.reset = function(form_) { 
    $scope.resetCount++; 
    $scope.obj = {}; 
    form_.$setPristine(); 
    form_.$setUntouched(); 
    console.log($scope.resetCount); 
}; 

$scope.search = function() { 
    alert('Searching'); 
}; 

jsfiddle活生生的例子。

請注意指令ng-model-options="{allowinvalid: true}"。一定使用它,或者直到輸入字段無效,型號值不被記錄。因此,重置將不會運行。

P.S.將對象上的值(areaCode,phoneNumber)簡化爲純化。

+0

答案是完美的,只有我想給它添加一個點,如果你在你的reset中調用了'form _。$ setPristine();'和'form _。$ setUntouched();'函數,那麼'ng-invalid'類將消失,因此表單字段將不會被標記爲紅色 – Musa

+0

這對我有用ng-model-options =「{allowInvalid:true}」這非常有幫助。與此有一段時間。 –

4
 $scope.search = {areaCode: xxxx, phoneNumber: yyyy} 

結構表單中的所有車型在同一個地方像上面,這樣你就可以清除它是這樣的:

 $scope.search = angular.copy({}); 

之後,你可以叫這爲重新驗證:

 $scope.search_form.$setPristine(); 
     $scope.search_form.$setUntouched(); 
     $scope.search_form.$rollbackViewValue(); 
1

進一步來@battmanz的答案,但沒有使用任何ES6語法來支持舊版瀏覽器。

$scope.resetForm = function (form) { 

      try { 
       var controlNames = Object.keys(form).filter(function (key) { return key.indexOf('$') !== 0 }); 

       console.log(controlNames); 
       for (var x = 0; x < controlNames.length; x++) { 
        form[controlNames[x]].$setViewValue(undefined); 
       } 

       form.$setPristine(); 
       form.$setUntouched(); 
      } catch (e) {     
       console.log('Error in Reset'); 
       console.log(e); 
      } 

     }; 
2

繼爲我工作

let form = this.$scope.myForm; 
let controlNames = Object.keys(form).filter(key => key.indexOf('$') !== 0); 
for (let name of controlNames) { 
    let control = form [name]; 
    control.$error = {}; 
} 

在短:擺脫NG-信息的錯誤,你需要清除出$錯誤對象爲每個表單項目。

0

我有同樣的問題,並試圖做battmanz解決方案(接受的答案)。

我很確定他的回答非常好,但是對我而言這並不奏效。

我正在使用ng-model綁定數據,輸入的角度材質庫和ng-message指令的錯誤消息爲,所以也許我會說只對使用相同配置的人有用。

我花了很多時間來看待javascript中的formController對象,事實上battmanz提到了很多$ angular函數,還有一些字段名稱,它們是字段中的某些函數的對象。

那麼什麼是清理你的表單?

通常我會將表單看作json對象,並且所有字段都綁定到此json對象的鍵。

//lets call here this json vm.form 
vm.form = {}; 

//you should have something as ng-model = "vm.form.name" in your view 

因此,在第一次清楚,我只是做了submiting形式的回調形式:

vm.form = {}; 

而在這個問題上的解釋,NG的消息將不會與消失,這是非常糟糕的。

當我用battmanz的解決方案,因爲他寫的,這些消息沒有再出現,但該領域是不是空submiting後了,即使我寫

vm.form = {}; 

而且我發現這是正常的,因爲使用他的解決方案實際上是從表單中刪除模型綁定,因爲它將所有字段設置爲undefined。 所以文本仍然在視圖中,因爲不知何故,它們不再有任何約束力,它決定留在HTML中。

那麼我做了什麼?

其實我只是清除該字段(設置綁定到{}),並用剛剛

form.$setPristine(); 
form.$setUntouched(); 

其實這似乎是合乎邏輯的,因爲綁定是還在這裏,在表單中值現在是空的,並且角度ng-messages指令只在表單沒有被觸及時觸發,所以我認爲這是正常的。

決賽(很簡單)的代碼是:

function reset(form) { 
     form.$setPristine(); 
     form.$setUntouched(); 
}; 

一個大問題,我與遇到:

只有一次,回調似乎在什麼地方搞砸了,不知何故字段不是空的(就像我沒有點擊提交按鈕)。

當我再次點擊時,發送的日期是空的。這更奇怪,因爲我的提交按鈕應該被禁用,當一個必填字段沒有填充好的模式,空當然不是一個好的模式。

我不知道我的做法是最好甚至是正確的,如果您對我遇到的問題有任何批評意見或建議,請告訴我,我總是喜歡以angularJS 。

希望這會幫助別人,並對壞英語感到抱歉。

0

所以沒有任何答案完全爲我工作。 ESP,清除視圖值,所以我結合所有的答案清算視圖值,清除錯誤和清除的J查詢的選擇(提供的字段輸入名稱相同型號名稱)

var modelNames = Object.keys($scope.form).filter(key => key.indexOf('$') !== 0); 
        modelNames.forEach(function(name){ 
         var model = $scope.form[name]; 
         model.$setViewValue(undefined); 
         jq('input[name='+name+']').val(''); 
         angular.forEach(model.$error, function(value, name) { 
          // reset validity 
          model.$setValidity(name, null); 
         }); 
        }); 
        $scope.form.$setPristine(); 
        $scope.form.$setUntouched(); 
相關問題