9

ng-resource を使用してサーバーからデータを取得し、そのデータを次のようにテーブル グリッドに配置しました。

<div ng-form name="grid">
      <button type="submit" data-ng-disabled="grid.$pristine">Save</button>
        <div class="no-margin">
            <table width="100%" cellspacing="0" class="form table">
                <thead class="table-header">
                    <tr>
                        <th>ID</th>
                        <th>Title</th>
                    </tr>
                </thead>
                <tbody class="grid">
                    <tr data-ng-repeat="row in grid.data">
                        <td>{{ row.contentId }}</td>
                        <td><input type="text" ng-model="row.title" /></td>
                    </tr>
                </tbody>
            </table>
        </div>
</div>

[送信] ボタンをクリックすると、変更された行をグリッドでチェックし、そのputEntity(row)行を引数として関数を呼び出すようにする方法はありますか?

4

4 に答える 4

12

いくつかの方法がありますが、すべての NgModelController には、入力が変更されたかどうかを確認するために使用できる $dirty フラグがあることを覚えておいてください。しかし、最も簡単な方法はこれを行うことだと思います:

HTML に編集:

<input type="text" ng-model="row.title" ng-change="row.changed=true" />
<button ng-click="save()">Save</button>

JS で:

$scope.save = function () {
    // iterate through the collection and call putEntity for changed rows
    var data = $scope.grid.data;
    for (var i = 0, len = data.length; i < len; i++) {
        if (data[i].changed) {
            putEntity(data[i]);
        }
    }
}
于 2013-07-18T08:55:27.060 に答える
3

ここにうまくいくものがあります。最初のコメントの JSFiddle をベースに構築されています。

まず、コントローラーにdata-ng-disabled属性を変更しchanges.length <= 0て追加$scope.changes = []しました。

$scope.changes = [];

次に、時計を追加しました$scope.data

$scope.$watch('data', function(newVal, oldVal){
    for(var i = 0; i < oldVal.length; i++){
        if(!angular.equals(oldVal[i], newVal[i])){
            console.log('changed: ' + oldVal[i].name + ' to ' + newVal[i].name);

            var indexOfOld = $scope.indexOfExisting($scope.changes, 'contentId', newVal[i].contentId);

            if(indexOfOld >= 0){
                $scope.changes.splice(indexOfOld, 1);
            }

            $scope.changes.push(newVal[i]);
        }
    }
}, true); // true makes sure it's a deep watch on $scope.data

基本的に、これは配列全体を実行し、angular.equalsを使用して何かが変更されたかどうかを確認します。オブジェクトが変更された場合、それが$scope.changes既に存在するかどうかがチェックされます。存在する場合は、削除されます。その後にnewVal[i]プッシュされます$scope.changes

$scope.indexOfExistingこのSOの質問から取得されます

$scope.indexOfExisting = function (array, attr, value) {
    for(var i = 0; i < array.length; i += 1) {
        if(array[i][attr] === value) {
            return i;
        }
    }
};

最後に私はそのように$scope.checkChange()見えるようにしました

$scope.checkChange = function(){
    for(var i = 0; i < $scope.changes.length; i++){
        console.log($scope.changes[i].name);
        //putEntity($scope.changes[i])
    }
    $scope.changes = [];
};

これにより、変更された行のみを送信できます。

于 2013-07-17T09:18:57.437 に答える
2

私はこれを次のようにすることにしました:

データを取得してコピーを作成する場所は次のとおりです。

getContents: function ($scope, entityType, action, subjectId, contentTypeId, contentStatusId) {
    entityService.getContents(entityType, action, subjectId, contentTypeId, contentStatusId)
    .then(function (result) {
        $scope.grid.data = result;
        $scope.grid.backup = angular.copy(result);
        $scope.grid.newButtonEnabled = true;
    }, function (result) {
        alert("Error: No data returned");
        $scope.grid.newButtonEnabled = false;
    });
},

その後、保存に関しては、angular.equals を使用してバックアップと比較します。

$scope.saveData = function () {
   var data = $scope.grid.data;
            for (var i = 0, len = $scope.grid.data.length; i < len; i++) {
                if (!angular.equals($scope.grid.data[i], $scope.grid.backup[i])) {
                    var rowData = $scope.grid.data[i]
                    var idColumn = $scope.entityType.toLowerCase() + 'Id';
                    var entityId = rowData[idColumn];
                    entityService.putEntity($scope.entityType, entityId, $scope.grid.data[i])
                        .then(function (result) {
                            angular.copy(result, $scope.grid.data[i]);
                            angular.copy(result, $scope.grid.backup[i]);
                        }, function (result) {
                            alert("Error: " + result);
                        })
                }
            }
            $scope.grid.newButtonEnabled = true;
            $scope.grid.saveButtonEnabled = false;
            $scope.$broadcast('tableDataSetPristine');
    }
于 2013-07-22T15:28:18.757 に答える
2

私は自分で非常に似たようなことをしましたが、別の方法を使用しました。すべての ng-models をデータに直接バインドすることにしました。これにより、すべての行をチェックする必要がある場合にインデックスを操作できましたが、データ全体をサーバーに送信する

次に、すべてのインデックスに加えられたすべての変更を監視し (大きなデータであっても、整数を追加/削除するだけです)、それらを配列に格納するだけです。

完了したら、送信ボタンをクリックします。これは、私が触れたすべてのインデックスでループし、コンテンツが元のコンテンツと本当に異なるかどうかを確認します。その後、必要なことを行うことができます (putEntity 関数を呼び出すなど)。 、私が持っていれば)

私はあなたのHTMLコードに基づいてフィドルを作りました。ここでコードをコピー/ペーストするよりも簡単にプレイできます: http://jsfiddle.net/DotDotDot/nNwqr/1/

HTML の主な変更点は、モデルをデータにバインドし、変更リスナーを追加するこの部分です。

<td><input type="text" ng-model="data[$index].title" ng-change="notifyChange($index)"/></td>

JavaScriptの部分は非常に理解しやすいと思います。データが変更されている間にインデックスをログに記録し、後で送信ボタンをクリックすると、ログに記録されたインデックスに基づいて、変更された行のみで適切な関数を呼び出すことができます

于 2013-07-23T15:37:11.340 に答える