web-dev-qa-db-ja.com

AngularJSでどの入力フィールドが変更されたかを示すにはどうすればよいですか

APIにデータをPUTする編集フォーム(user.html)で作業していますが、フォーム内のすべてのデータをPUTしないようにしたいと思います。変更したアイテムだけをPUTしたいです。

フォームを操作するときにダーティで自然のままの使用を見てきましたが、これはフォームのすべての変更に適用されます。 ng-changeの使用も確認しましたが、1つの要素への変更に対してアクションをトリガーしたくありません。変更された要素がPUTに含まれていることを示すだけです。

誰もが変更された入力フィールドのみを示す方法を見つけましたか?

36
brock

入力を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を使用して、anyフィールドが変更されたかどうかを確認し、フォーム上の各入力のプロパティの$pristineプロパティでその入力が変更されました。 myFormオブジェクトを繰り返し処理することもできます(非入力フィールドオブジェクトには、$というプレフィックスが付いたキーがあります)。

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

ユーザーに設定/情報の更新を許可する場合、より多くの機能が必要になることがよくあります。情報をリセットしたり、編集をキャンセルして元に戻す機能など。これはリクエストの一部ではなかったと思いますが、これを考慮すると、他のことが簡単になります。

保存された値を保存し、編集された値も持っています。変更されていないため、保存された値にリセットできます。次に、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つの参照ではなく、実際には2つのオブジェクトになるようにします。

19
TheSharpieOne

古いスレッドですが、TheSharpieOneの答えに基づいて構築するには、「===」の代わりにangle.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;
}
8
ARN

$scope.$watch('scopeVariable', function(oldValue, newValue)...)を使用して、newValuesとは異なるoldValuesのみを含むオブジェクトを作成できます。

link to Angular $ watchに関するドキュメント。

2

ARNとTheSharpieOneの答えを構築します。プロジェクトでアンダースコアを使用している場合は、この方法を使用してオブジェクトの配列の違いを見つけることができます。

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

Submitイベントで値が変更されたオブジェクトのみを取得する簡単な方法:

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

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

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;
}
0
Venkat Kotra