2013-09-05 24 views
32

我正在編寫一個將數據發送到API的編輯表單(user.html),但我想避免在表單中填寫所有數據。我想把PUT只是改變的項目。我如何表示在AngularJS中哪些輸入字段發生了變化

我在使用窗體時看到了使用髒和純淨的東西,但這適用於窗體中的任何更改。我也看到了ng-change的用法,但我不想觸發對一個元素進行更改的操作,只是表示更改後的元素應該包含在PUT中。

任何人都找到一種方法來表示只有輸入字段已更改?

回答

49

如果將輸入form的屬性設置爲name,然後輸入name屬性,則還可以訪問輸入的$pristine屬性。

<div ng-controller="MyController"> 
    <form name="myForm"> 
    <input type="text" name="first" ng-model="firstName"> 
    <input type="text" name="last" ng-model="lastName"> 
    </form> 
</div> 
app.controller('MyController', function($scope) { 
    // Here you have access to the inputs' `$pristine` property 
    console.log($scope.myForm.first.$pristine); 
    console.log($scope.myForm.last.$pristine); 
}); 

您可以使用$scope.myForm.$pristine看是否任何領域已經改變,看到$pristine屬性窗體上的每個輸入的財產,如果該輸入已經改變。你甚至可以遍歷myForm對象(非輸入字段對象有一個$前綴鍵):

angular.forEach($scope.myForm, function(value, key) { 
    if(key[0] == '$') return; 
    console.log(key, value.$pristine) 
}); 
// first, true 
// last, false 
+3

假設用戶進入該頁面,並且'firstName'字段爲空。 '$ scope.firstName。$ pristine'在這一點上被設置爲'true'。用戶然後輸入「foo」。 '$ scope.firstName。$ pristine'現在被設置爲'false'。用戶然後退回三次,以保持輸入爲空,就像原來的那樣。 '$ scope.firstName。$ pristine'繼續被設置爲'false'。 –

+2

@WalterRoman這是正確的。 '$ pristine'在[docs](https://docs.angularjs.org/api/ng/type/form.FormController)中定義爲:「如果用戶尚未與表單交互,則返回true」 –

+0

我希望設置焦點或更新更新元素的背景顏色。我如何使用'value'對象來做到這一點?或者我應該使用哪個對象以及哪個屬性? –

2

您可以使用$scope.$watch('scopeVariable', function(oldValue, newValue)...)並構建一個只包含newValue的對象,該對象與oldValue不同。

以下是有關$ watch的Angular文檔的link

17

我經常發現,允許用戶更新設置/信息時,你會想更多的功能。如重置信息或取消編輯並恢復的能力。我知道這不是要求的一部分,但是當你考慮這一點時,這會讓其他事情變得更容易。

您可以存儲已保存的值並且也具有已編輯的值,您可以重置爲保存的值,因爲它們不會更改。然後你可以比較2來確定改變了什麼。

工作實例http://jsfiddle.net/TheSharpieOne/nJqTX/2/

查看控制檯日誌,看看當你在例如提交表單是什麼改變了。這是一個可以通過PUT輕鬆發送的對象。

function myCtrl($scope) { 
    $scope.user = { 
     firstName: "John", 
     lastName: "Smith", 
     email: "[email protected]" 
    }; 
    $scope.reset = function() { 
     angular.copy($scope.user, $scope.edit); 
    }; 
    $scope.submitForm = function(){ 
     console.log(findDiff($scope.user, $scope.edit)); 
     // do w/e to save, then update the user to match the edit 
     angular.copy($scope.edit, $scope.user); 
    }; 

    function findDiff(original, edited){ 
     var diff = {} 
     for(var key in original){ 
      if(original[key] !== edited[key]) 
       diff[key] = edited[key]; 
     } 
     return diff; 
    } 
} 

注意:findDiff很簡單,它假設兩個對象具有相同的鍵,只有值已經改變。我們複製這些對象,以便它們不會成爲對同一對象的2個引用,但實際上是2個對象。

+7

您可以使用'angular.copy(source,dest)'而不是自己寫克隆功能。儘管我喜歡你的方法。 –

+2

我忘了那個。給你+1好先生。 (編輯回答這個反射) – TheSharpieOne

7

舊的線程,但要建立在TheSharpieOne的答案上,您可能希望檢查使用angular.equals而不是「===」的相等性,否則這將不適用於數組。

function findDiff(original, edited){ 
    var diff = {} 
    for(var key in original){ 
     if(!angular.equals(original[key], edited[key])) 
     diff[key] = edited[key]; 
    } 
    return diff; 
} 
0

建立關閉ARN和TheSharpieOne的答案。如果您在項目中使用下劃線,則可以採用此方法來查找對象數組中的差異。

function findDiff(original, edited){ 
    _.filter(original, function(obj){ return !_.findWhere(edited, obj); }); 
} 
0

一個簡單的方法只對提交事件改變的值檢索對象:

var dirtyInput = $('#myForm .ng-dirty'); 
var change = {}; 

for (var i = 0; i < dirtyInput.length; i++) { 
    change[dirtyInput[i].name] = dirtyInput[i].value; 
} 
0

TheSharpieOne's answer添加更多。原始和編輯之間的差異也可能是由於在編輯的對象中添加了新字段。因此,額外檢查相同

function findDiff(original, edited){ 
    var diff = {} 
    for(var key in original){ 
     if(!angular.equals(original[key], edited[key])) 
     diff[key] = edited[key]; 
    } 
    for(var key in edited){ 
     if(!angular.equals(original[key], edited[key])) 
     diff[key] = edited[key]; 
    } 

    return diff; 
} 
相關問題