2

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

  • You should provide more code in your question not just the data but also the grid code. Anyway in your case you probably did not know that you can use the dot separator for complex object and all Filters are supporting it, so you can use `'childs.name'` in your column definition. `this.columnDefinitions = [{ id: 'children', name: 'Children', field: 'childs.name' ... }]` – ghiscoding Jun 17 '20 at 13:41
  • @ghiscoding Here I have modified the Question and Mentioned the column definition. Please ask me if you still having trouble for understanding my question. – Manikandan K Jun 18 '20 at 08:32
  • When I mentioned the dot notation in the `field` property, it's meant to be used for complex object (typically an object not an array), I'm not sure that will work for an array. It's much easier to work with a flat dataset, your data looks like a Tree Data set and if you are using the new Tree Data feature of Angular-Slickgrid then the dataset is still a flat dataset (when using the lib, internally the DataView can only work with the flat dataset, so the lib keeps 2 references, 1 ref for the flat dataset and 1 ref for the Tree Data set). So if it's Tree Data, then it's a simple Filter not dot – ghiscoding Jun 18 '20 at 18:25
  • ... if you refer to the Tree Data example you will see that the Filters are defined as if the dataset is flat. When I say flat it basically (not in a Tree Data structure, but only parent/child references, so if 1 parent has 2 children, it will show 3 rows in the dataset) – ghiscoding Jun 18 '20 at 18:32

1 Answers1

1

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.

Nelson Gnanaraj
  • 176
  • 1
  • 13
  • 1
    pushed a [PR](https://github.com/ghiscoding/slickgrid-universal/pull/728) to fix what you mentioned, since I didn't understand the original question, but you know this is an Open Source project, it would have been nice to get a PR from you instead of seeing this patch which just complicates your code implementation. – ghiscoding Jul 28 '22 at 19:12