In Slick Grid inline edit I can't able to get the entire object

Viewed 378

I am using angular slickgrid for showing my data. When I am trying to edit the slick grid record, I will get the changed fields only I need the entire object. I have given the sample data.

Columndefinition :

this.columnDefinitions = [
      {
        id: 'title', name: 'Title', field: 'title', width: 220, cssClass: 'cell-title',
        filterable: true, sortable: true,
        queryFieldSorter: 'id', type: FieldType.string,
        formatter: Formatters.tree,
        editor: {
          model: Editors.longText,
          required: true,
        },
      },
      { id: 'duration', name: 'Duration', field: 'duration', minWidth: 90, filterable: true },
      {
        id: 'child.0.percentComplete', name: '% Complete', field: 'child.0.percentComplete', minWidth: 120, maxWidth: 200,
        sortable: true, filterable: true, filter: { model: Filters.slider, operator: '>=' },
        formatter: Formatters.percentCompleteBar, type: FieldType.number,
        editor: {
          model: Editors.slider,
          minValue: 0,
          maxValue: 100,
          params: { hideSliderNumber: false },
        },
      },

    ];

SlickGrid input data set structure:

const data = [
      {
        'id': 0,
        'indent': 0,
        'parentId': null,
        'title': 'Task 0',
        'duration': '5 days',
        'percentComplete': 73,
        'start': '2003-03-21T18:30:00.000Z',
        'finish': '2003-04-21T18:30:00.000Z',
        'effortDriven': true,
        'child' : [{
            'id': 2,
            'indent': 0,
            'parentId': 1,
            'title': 'Task 0',
            'duration': '5 days',
            'percentComplete': 73,
            'start': '2003-03-21T18:30:00.000Z',
            'finish': '2003-04-21T18:30:00.000Z',
            'effortDriven': true
        }]
      },
      {
        'id': 1,
        'indent': 0,
        'parentId': null,
        'title': 'Task 1',
        'duration': '5 days',
        'percentComplete': 4,
        'start': '2004-04-24T18:30:00.000Z',
        'finish': '2004-05-24T18:30:00.000Z',
        'effortDriven': false
      }
    ];

When I start to change the employee field oncellchanged called and I got arg.Item

Current behaviour

onCellChanged(e, args) {
    this.angularGrid.gridService.updateItemById(args.item['id'], args.item);
    console.log(args.item);
}

Log

{
  "id": 0,
  "indent": 0,
  "parentId": null,
  "title": "Task 0",
  "duration": "5 days",
  "percentComplete": 73,
  "start": "2003-03-21T18:30:00.000Z",
  "finish": "2003-04-21T18:30:00.000Z",
  "effortDriven": true,
  "child": {
    "0": {
      "percentComplete": 25
    }
  }
}

Expected output:

{
  "id": 0,
  "indent": 0,
  "parentId": null,
  "title": "Task 0",
  "duration": "5 days",
  "percentComplete": 73,
  "start": "2003-03-21T18:30:00.000Z",
  "finish": "2003-04-21T18:30:00.000Z",
  "effortDriven": true,
  "child": [
    {
      "id": 2,
      "indent": 0,
      "parentId": 1,
      "title": "Task 0",
      "duration": "5 days",
      "percentComplete": 25,
      "start": "2003-03-21T18:30:00.000Z",
      "finish": "2003-04-21T18:30:00.000Z",
      "effortDriven": true
    }
  ]
}

Software versions

  • Angular : 7.3.5

  • Angular-Slickgrid : 2.17.10

  • TypeScript : 3.1.6

  • Node : 10.16.3

1 Answers

The issue due to the utils files used in angular slickgrid library. If you want to fix this issue, have two solutions.

  1. The library itself handle the function logic.
  2. Need to implement custom editor based on your requirement.

Issue area

In each editor, applyValue method sets the object value to respective path. In the method, the array value not parsed properly. You can extend the editor class and override the applyValue method. Here I shared the sample code for your reference. Especially, go through the setDeepValue method which I have mentioned below.

import { EditorArguments, InputEditor } from 'angular-slickgrid';

export class CustomInputEditor extends InputEditor {
  constructor(protected readonly args: EditorArguments, inputType: string) {
    super(args, inputType);
  }
  applyValue(item: any, state: any) {
    const fieldName = this.columnDef && this.columnDef.field;
    if (fieldName !== undefined) {
      const isComplexObject = fieldName?.indexOf('.') > 0; // is the field a complex object, "address.streetNumber"
    // is the field a complex object having array value you need to specify the index position in path (Here I used 0th index), "address.0.streetNumber"

      // validate the value before applying it (if not valid we'll set an empty string)
      const validation = this.validate(state);
      const newValue = validation?.valid ? state : '';

      // set the new value to the item datacontext
      if (isComplexObject) {
        // when it's a complex object, user could override the object path (where the editable object is located)
        // else we use the path provided in the Field Column Definition
        const objectPath =
          this.columnEditor?.complexObjectPath ?? fieldName ?? '';
        this.setDeepValue(item, objectPath, newValue);
      } else if (fieldName) {
        item[fieldName] = newValue;
      }
    }
  }

  setDeepValue<T = any>(obj: T, path: string | string[], value: any) { // Customized the set value method to handle the array data
    if (typeof path === 'string') {
      path = path.split('.');
    }

    if (path.length > 1) {
      const e = path.shift();
      if (obj && e !== undefined) {
        let innerObject;
        if (!Array.isArray(obj[e]) && typeof obj[e] != 'object') {
          obj[e] = {};
        }
        this.setDeepValue(obj[e], path, value);
      }
    } else if (obj && path[0]) {
      (obj as any)[(path as any)[0]] = value;
    }
  }
}

I hope this may helpful for you.

Kind information to the library author, If possible update the setDeepValue method in latest release.

Related