私のユースケースは非常に簡単です。ユーザーは、セルを編集した後(enableCellEdit:true)、データを「自動的に」サーバーに送信する必要があります(セルのぼかし)。さまざまなアプローチを試しましたが、どれも適切に機能していません。私は最小限のグリッドを持っています:
// Configure ng-grid
$scope.gridOptions = {
data: 'questions',
enableCellSelection: true,
selectedItems: $scope.selectedRow,
multiSelect: false,
columnDefs: [
{field: 'id', displayName: 'Id'},
{field: 'name', displayName: 'Name'},
{field: 'answers[1].valuePercent', displayName: 'Rural', enableCellEdit: true}
]
};
たとえば、グリッドに渡されたデータモデルを監視しようとしました。しかし、そうしても編集されたセルは返されません:
$scope.$watch('myData', function (foo) {
// myModel.$update()
}, true);
「ngGridEventData」データイベントをいじろうとしましたが、セルの編集後に起動しません
$scope.$on('ngGridEventData', function (e, gridId) {
// myModel.$update()
});
最後に、セルを観察しようとしました。ただし、これはグリッドの「selectedCell」プロパティの平均によってのみ行に対して機能します。
$scope.selectedRow = [];
$scope.gridOptions = {
selectedItems: $scope.selectedRow,
}
$scope.$watch('selectedRow', function (foo) {
console.log(foo)
}, true);
ng-gridプラグイン 必要ですか?私はそれがすぐに使えるものではないとは信じられません。
自動保存を解決してサーバーに送信する方法を示すポインター/スニペットがありますか?
たぶんこれは新しいかもしれませんが、ng-gridは実際にイベントを発行し、これを使用して変更に関する簡単な更新を実装できます。
イベントリファレンス: https://github.com/angular-ui/ng-grid/wiki/Grid-Events
サンプルコード(グリッドをセットアップするコントローラーに追加):
$scope.$on('ngGridEventEndCellEdit', function(evt){
console.log(evt.targetScope.row.entity); // the underlying data bound to the row
// Detect changes and send entity to server
});
注意すべきことは、変更が行われていなくてもイベントがトリガーされるため、サーバーに送信する前に変更を確認したい場合があることです(たとえば、「ngGridEventStartCellEdit」を使用)
私ははるかに優れたソリューションだと思うものを見つけました:
cellEditableTemplate = "<input ng-class=\"'colt' + col.index\" ng-input=\"COL_FIELD\" ng-model=\"COL_FIELD\" ng-change=\"updateEntity(row.entity)\"/>"
この方法でng-changeを使用すると、変更されたオブジェクト(行)全体でupdateEntityが呼び出され、サーバーにポストバックできます。新しいスコープ変数は必要ありません。以前のソリューションの欠点は、クリックしてフィールドの編集を開始すると、編集を開始する前の元の値ではなく常に空白になることでした。
これにより、各キーストロークでupdateEntity()が呼び出されます。これが頻繁すぎる場合は、サーバーに投稿する前にタイムアウトを使用するか、updateEntity()を使用してプッシュするIDを記録し、ng-blurを使用して記録されたIDを投稿できます。
Angular メーリングリスト のおかげで解決策を見つけたようです。 「単純な」ディレクティブを追加することで克服できます。
angular.module('myApp.ngBlur', [])
.directive('ngBlur', function () {
return function (scope, elem, attrs) {
elem.bind('blur', function () {
scope.$apply(attrs.ngBlur);
});
};
});
情報として、ぼかしイベントディレクティブ here に関連する実装の別の例があります。
次に、コントローラー内の残りのコードは次のようになります。
// Define the template of the cell editing with input type "number" (for my case).
// Notice the "ng-blur" directive
var cellEditableTemplate = "<input style=\"width: 90%\" step=\"any\" type=\"number\" ng-class=\"'colt' + col.index\" ng-input=\"COL_FIELD\" ng-blur=\"updateEntity(col, row)\"/>";
// Configure ng-grid
$scope.gridOptions = {
data: 'questions',
enableCellSelection: true,
multiSelect: false,
columnDefs: [
{field: 'id', displayName: 'Id'},
{field: 'name', displayName: 'Name'},
// Notice the "editableCellTemplate"
{field: 'answers[0].valuePercent', displayName: 'Rural', enableCellEdit: true, editableCellTemplate: cellEditableTemplate}
]
};
// Update Entity on the server side
$scope.updateEntity = function(column, row) {
console.log(row.entity);
console.log(column.field);
// code for saving data to the server...
// row.entity.$update() ... <- the simple case
// I have nested Entity / data in the row <- the complex case
// var answer = new Answer(question.answers[answerIndex]); // answerIndex is computed with "column.field" variable
// answer.$update() ...
}
Ng-grid 2.xのこの部分をまとめるのに時間を費やしました。行を編集するために2回クリックする必要があるという問題がまだありますが、それはbootstrapの問題であり、ngGridの問題ではなく、サンプルコードでは発生しません(これはt bootstrap yet)を持っています。
Ui-grid 3.0のチュートリアルでも同様のロジックを実装しました。これはまだベータ版ですが、すぐに推奨バージョンになります。これは次の場所にあります: http://technpol.wordpress.com/2014/08/23/upgrading-to-ng-grid-3-0-ui-grid/ この機能のためのより簡単でクリーンなAPI。
2.xバージョンでは、すべてのビットを説明するために、ドロップダウンと入力フィールドの両方を備えた編集可能なグリッドを持ち、ngBlurディレクティブを使用し、$ timeoutを使用して重複する保存を回避する実行中のプランカーを作成しました更新: http://plnkr.co/edit/VABAEu?p=preview
コードの基本は次のとおりです。
var app = angular.module('plunker', ["ngGrid"]);
app.controller('MainCtrl', function($scope, $timeout, StatusesConstant) {
$scope.statuses = StatusesConstant;
$scope.cellInputEditableTemplate = '<input ng-class="\'colt\' + col.index" ng-input="COL_FIELD" ng-model="COL_FIELD" ng-blur="updateEntity(row)" />';
$scope.cellSelectEditableTemplate = '<select ng-class="\'colt\' + col.index" ng-input="COL_FIELD" ng-model="COL_FIELD" ng-options="id as name for (id, name) in statuses" ng-blur="updateEntity(row)" />';
$scope.list = [
{ name: 'Fred', age: 45, status: 1 },
{ name: 'Julie', age: 29, status: 2 },
{ name: 'John', age: 67, status: 1 }
];
$scope.gridOptions = {
data: 'list',
enableRowSelection: false,
enableCellEditOnFocus: true,
multiSelect: false,
columnDefs: [
{ field: 'name', displayName: 'Name', enableCellEditOnFocus: true,
editableCellTemplate: $scope.cellInputEditableTemplate },
{ field: 'age', displayName: 'Age', enableCellEdit: false },
{ field: 'status', displayName: 'Status', enableCellEditOnFocus: true,
editableCellTemplate: $scope.cellSelectEditableTemplate,
cellFilter: 'mapStatus'}
]
};
$scope.updateEntity = function(row) {
if(!$scope.save) {
$scope.save = { promise: null, pending: false, row: null };
}
$scope.save.row = row.rowIndex;
if(!$scope.save.pending) {
$scope.save.pending = true;
$scope.save.promise = $timeout(function(){
// $scope.list[$scope.save.row].$update();
console.log("Here you'd save your record to the server, we're updating row: "
+ $scope.save.row + " to be: "
+ $scope.list[$scope.save.row].name + ","
+ $scope.list[$scope.save.row].age + ","
+ $scope.list[$scope.save.row].status);
$scope.save.pending = false;
}, 500);
}
};
})
.directive('ngBlur', function () {
return function (scope, elem, attrs) {
elem.bind('blur', function () {
scope.$apply(attrs.ngBlur);
});
};
})
.filter('mapStatus', function( StatusesConstant ) {
return function(input) {
if (StatusesConstant[input]) {
return StatusesConstant[input];
} else {
return 'unknown';
}
};
})
.factory( 'StatusesConstant', function() {
return {
1: 'active',
2: 'inactive'
};
});
このプランカーを実行し、フォーカスを失うと、更新トリガーの起動がコンソールに表示されます。
README.mdをプランカーに含めて、ここで再現した、私に困難を与えたものについてのいくつかの考えを入れました。
ここでの機能は、私が人々のリストを持っているということです、それらの人々は名前、年齢とステータスを持っています。実際のアプリでできることと一致して、ステータスはコードであり、デコードを表示したいと思います。したがって、ステータスコードリスト(実際のアプリではデータベースから取得される可能性があります)があり、コードをデコードにマップするフィルターがあります。
私たちが望んでいるのは2つのことです。入力ボックスで名前を編集し、ドロップダウンでステータスを編集できるようにします。
このプランクで学んだことに対するコメント。
GridOptionsレベルには、enableCellEditOnFocusとenableCellEditの両方があります。両方を有効にしないで、選択する必要があります。 onFocusはシングルクリック、CellEditはダブルクリックを意味します。両方を有効にすると、編集したくないグリッドのビットで予期しない動作が発生します
ColumnDefsレベルでは、同じオプションがあります。ただし、今回はCellEditとonFocusの両方を設定する必要があり、編集したくないセルではcellEditをfalseに設定する必要があります-これはデフォルトではありません
ドキュメントには、編集可能なセルテンプレートは次のようにできることが記載されています。
<input ng-class = "'colt' + col.index" ng-input = "COL_FIELD" />
実際にはそれが必要です:
<input ng-class = "'colt' + col.index" ng-input = "COL_FIELD" ng-model = "COL_FIELD" />
フォーカスを失ったときに保存イベントをトリガーするために、私はstackoverflowで見つけたロジックであるblurディレクティブを作成しました: AngularJS and ng-grid-セルが変更された後、サーバーにデータを自動保存 =
これは、編集可能な各セルテンプレートを変更してng-blurを呼び出すことも意味します。これは、編集可能なセルテンプレートの最後に表示されます。
フィールドを離れると(少なくともChromeで)2つのblurイベントが発生するため、タイマーを使用して、そのうちの1つだけが処理されるようにします。 glyいですが、動作します。
また、このコードのより詳細なウォークスルーを行うブログ投稿を作成しました。 http://technpol.wordpress.com/2013/12/06/editable-nggrid-with-both-dropdowns-and- select /
UI Grid 3.0を使用している場合、そのイベントは次のとおりです。 uiGridEventEndCellEdit
$scope.$on('uiGridEventEndCellEdit', function (data) {
console.log(data.targetScope.row.entity);
}
これは、いくつかの欠陥がある回答の改善です。-回答のコメントの1つに示されているように、JS例外をトリガーします-セルのデータ入力はグリッドに保持されません-updateEntityメソッドは保存方法を示しません入力データ
例外を削除するには、スコープ属性を作成してcellEditableTemplateに追加します。
$scope.cellValue;
...
var cellEditableTemplate = "<input style=\"width: 90%\" step=\"any\" type=\"number\" ng-class=\"'colt' + col.index\" ng-input=\"COL_FIELD\" ng-blur=\"updateEntity(col, row, cellValue)\" ng-model='cellValue'/>";
UpdateEntityへのng-blur呼び出しに、引数としてcellValueが含まれるようになりました。次に、updateEntity blurハンドラーを更新して引数を含め、グリッドを更新します。
$scope.updateEntity = function(column, row, cellValue) {
console.log(row.entity);
console.log(column.field);
row.entity[column.field] = cellValue;
// code for saving data to the server...
// row.entity.$update() ... <- the simple case
// I have nested Entity / data in the row <- the complex case
// var answer = new Answer(question.answers[answerIndex]); // answerIndex is computed with "column.field" variable
// answer.$update() ...
};
画面に変更を表示できるようになり、セルベースのバックエンド更新をトリガーできるようになりました。
PaulLがコメントの1つで言及したように、ui-gridには、編集が完了したときに行全体を保存できるように設計されたrowEdit機能があります。 http://ui-grid.info/docs/#/tutorial/205_row_editable を参照してください。