slickgridangular-slickgrid

Angular slickgrid edit handler does not trigger on selecting same value from dropdown


I have a requirement in angular slickgrid where I want to edit the row with the same option which in result will update the date on which the update was made.

What I actually do is call an API on edit command handler when any changes are made in the table, but when I click on the same option from dropdown, the handler is not triggered(which is valid as there was no change made, but for my purpose I need that to be triggered)

So my code looks something like this:

These are my grid options

{
            enableAutoResize: true,
            enableSorting: true,
            editable: true,
            autoEdit: true,
            autoCommitEdit: true,
            editCommandHandler : (item, column, editCommand) => EditHandler(item, column, editCommand)//This is my EditHandler method which gets triggered and calls an API in backend
}

This is my column definition

{
    id: 'status', name: 'Status', field: 'status', 
    filterable: true,
    editor: {
      collection: [{ value: 'progress', label: 'Progress' }, { value: 'new', label: 'New' }, { value: 'done', label: 'Done' }],
      model: Editors.singleSelect
    }
  }

Now suppose If a row contains Progress in the status column and when I change that to New from dropdown my EditHandler method triggers and I proceed with my changes.

But what I want is to click on Progress again and want to trigger the EditHandler method and call the API which updates the date with the same status


Solution

  • EDIT

    The following works and I tested it. I also added code to keep the last event name triggered (onClose/onOpen) so that you won't trigger the editCommandHandler when opening the select dropdown. You should also use the latest version of Angular-Slickgrid version 2.25.0, all the Editors/Filters are now Public so it's easier to extend them (see latest Release Note).

    export class CustomSelectEditor extends SingleSelectEditor {
      private lastEventName = '';
    
      constructor(args) {
        super(args);
    
        // retrieve the options that were provided to multipleSelect.JS
        // we will override the onClose/onOpen to get last event name triggered
        // Note: make sure that the onClose is still calling the this.save() else nothing will work
        const libOptions = this.editorDomElement.multipleSelect('getOptions');
        libOptions.onClose = () => {
          this.lastEventName = 'onClose';
          this.save();
        };
        libOptions.onOpen = () => {
          this.lastEventName = 'onOpen';
        }
        this.editorDomElement.multipleSelect('refreshOptions', libOptions);
      }
    
      isValueChanged(): boolean {
        // return true only when it's the onClose event to fire the editCommandHandler
        if (this.lastEventName === 'onClose') {
          return true;
        }
    
        // but keep previous logic when it's not the onClose event
        if (this.isMultipleSelect) {
          return !charArraysEqual(this.$editorElm.val(), this.originalValue);
        }
        return this.$editorElm.val() !== this.originalValue;
      }
    }
    

    All Editors were written in a way to avoid triggering events when nothing changed, if you really wish to change that behavior then you could extend the SelectEditor and override the isValueChanged() function.

    Note that I did not test the code below but it should work, I'm not sure if SelectEditor is actually public, if it's not then try to extend Editors.singleSelect and Editors.multipleSelect

    Try first to extend SelectEditor directly (I think they are not currently public and that won't work, but I'll probably change that in future version)

    import { SelectEditor } from 'angular-slickgrid';
    
    export class CustomSelectEditor extends SelectEditor {
      constructor() {
        super();
      }
    
      isValueChanged(): boolean {
        // your custom logic
      }
    }
    

    or Editors.singleSelect if SelectEditor is not publicly available

    import { Editors } from 'angular-slickgrid';
    
    export class CustomSelectEditor extends Editors.inputText {
      constructor() {
        super();
      }
    
      isValueChanged(): boolean {
        // your custom logic
      }
    }
    

    then use it in your custom editor in your column definitions

    {
        id: 'status', name: 'Status', field: 'status', 
        filterable: true,
        editor: {
          collection: [{ value: 'progress', label: 'Progress' }, { value: 'new', label: 'New' }, { value: 'done', label: 'Done' }],
          model: CustomSelectEditor 
        }
    }