source

AngularJS 및 ng-grid - 셀 변경 후 데이터를 서버에 자동 저장

itover 2023. 3. 28. 21:41
반응형

AngularJS 및 ng-grid - 셀 변경 후 데이터를 서버에 자동 저장

사용 사례는 매우 간단합니다.셀을 편집한 후(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()
});

마침내, 나는 감방을 관찰하려고 했다.단, 이는 그리드의 "selected Cell" 속성의 평균에 의한 행에만 적용됩니다.

$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가 지목된 것은JS에 onBlur 이벤트(및 onFocus)가 없습니다.그러나 이는 "단순한" 지시문을 추가하면 극복할 수 있습니다.

angular.module('myApp.ngBlur', [])
.directive('ngBlur', function () {
    return function (scope, elem, attrs) {
        elem.bind('blur', function () {
            scope.$apply(attrs.ngBlur);
        });
    };
});

참고로 여기에서는 블러 이벤트 디렉티브와 관련된 구현의 또 다른 예를 제시되어 있습니다.

다음으로 컨트롤러의 나머지 코드는 다음과 같습니다.

// 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의 경우 이 부분을 정리하는 데 시간이 걸렸습니다.행을 편집하기 위해 두 번 클릭해야 하는 문제는 여전히 있지만, 이는 부트스트랩 문제이지 ngGrid 문제가 아니라고 생각합니다. 샘플 코드(부트스트랩은 아직 없습니다)에서는 발생하지 않았습니다.

저는 ui-grid 3.0의 튜토리얼에도 비슷한 로직을 실장했습니다.이것은 아직 베타판이지만 곧 선호 버전이 될 것입니다.이 기능은 http://technpol.wordpress.com/2014/08/23/upgrading-to-ng-grid-3-0-ui-grid/,에서 확인할 수 있으며, 이 기능을 위해 훨씬 쉽고 깔끔한 API를 제공합니다.

2.x 버전에서는 모든 비트를 표시하기 위해 드롭다운 필드와 입력 필드 모두 편집 가능한 그리드를 가진 실행 중인 플런커를 작성했습니다.ngBlur 디렉티브를 사용하고 업데이트 시 중복 저장을 피하기 위해 $120을 사용합니다.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를 플런커에 포함시켰습니다.여기서 재현한 것처럼, 곤란했던 것에 대해 몇 가지 생각을 하고 있습니다.

여기서 기능하는 것은 이름, 나이 및 지위를 가진 사람 목록이 있다는 것입니다.실제 앱에서 수행할 수 있는 작업에 따라 상태는 코드이며 디코딩을 보여 줍니다.따라서 상태 코드 목록(실제 앱의 경우 데이터베이스에서 가져올 수 있음)과 코드를 디코딩에 매핑하는 필터가 있습니다.

우리가 원하는 건 두 가지야입력란에서 이름을 편집하고 드롭다운에서 상태를 편집할 수 있도록 하고 싶습니다.

이 플렁크에서 배운 거에 대한 댓글.

  1. gridOptions 레벨에는 enableCellEditOnFocus와 enableCellEdit이 있습니다.둘 다 활성화하지 말고 선택해야 합니다.onFocus는 원클릭, CellEdit은 더블클릭을 의미합니다.둘 다 활성화하면 그리드의 비트에서 편집하고 싶지 않은 예기치 않은 동작이 발생합니다.

  2. columnDefs 수준에서도 동일한 옵션을 사용할 수 있습니다.그러나 이번에는 CellEdit과 onFocus를 모두 설정해야 하며 편집하지 않는 셀에서는 cellEdit을 false로 설정해야 합니다.기본값이 아닙니다.

  3. 매뉴얼에서는 편집 가능한 셀템플릿은 다음과 같습니다.

    <input ng-class='colt' + col.인덱스" ng-input="COL_FILD" />

    실제로 필요한 것은 다음과 같습니다.

    <input ng-class='colt' + col.인덱스" ng-input="COL_FILD" ng-model="COL_FILD" />

  4. 초점을 잃었을 때 저장 이벤트를 트리거하기 위해 stackoverflow에서 찾은 논리인 흐림 지시문을 만들었습니다.각진JS 및 ng-grid - 셀 변경 후 데이터를 서버에 자동 저장

  5. 이는 편집 가능한 셀템플릿의 끝에 표시되는 각 편집 가능한 셀템플릿을 ng-blur로 변경하는 것을 의미합니다.

  6. (최소한 Chrome에서는) 필드를 벗어나면 2개의 흐림 현상이 발생하므로 타이머를 사용하여 1개만 처리됩니다.못생겼지만, 효과가 있어요.

또, 이 코드의 상세한 것에 대해 설명하는 블로그 투고도 작성했습니다.http://technpol.wordpress.com/2013/12/06/editable-nggrid-with-both-dropdowns-and-selects/

UI Grid 3.0을 사용하는 경우 해당 이벤트는 다음과 같습니다.uiGridEventEndCellEdit

$scope.$on('uiGridEventEndCellEdit', function (data) {
    console.log(data.targetScope.row.entity);
}

이는 몇 가지 결함이 있는 답변에 대한 개선 사항입니다. - 답변의 코멘트 중 하나에 표시된 바와 같이 JS 예외를 트리거합니다. 셀의 데이터 입력은 그리드에 유지되지 않습니다. updateEntity 메서드는 입력 데이터를 저장하는 방법을 설명하지 않습니다.

예외를 삭제하려면 스코프 속성을 생성하여 cellEditable에 추가합니다.템플릿:

$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() ...
};

이제 화면에서 변경 사항을 볼 수 있을 뿐만 아니라 셀 기반 백엔드 업데이트를 트리거할 수 있습니다.

코멘트 중 하나에서 언급한 바와 같이 ui-grid에는 편집이 완료되면 행 전체를 저장할 수 있도록 설계된rowEdit 기능이 있습니다.http://ui-grid.info/docs/ #/syslogs/syslogs_row_syslogs 를 참조하십시오.

언급URL : https://stackoverflow.com/questions/15647981/angularjs-and-ng-grid-auto-save-data-to-the-server-after-a-cell-was-changed

반응형