slickgridangular-slickgrid

Angular slickgrid dynamic editor collection by every row data


This is my slickgrid dataset

[{title : 'foo', prerequisites : true}, {title : 'bar', prerequisites : false}]

These are my column definitions:

[
     {
        id: "title",
        name: "Title", 
        field: "title"
     },  
     {
        id: 'prerequisites', name: 'Prerequisites', field: 'prerequisites',
        type: FieldType.string,
        editor: {
          model: Editors.multipleSelect,
          collection: [{ value: '', label: '' }, { value: true, label: 'true' }, { value: false, label: 'false' }]
        }
      }]

This creates a static editor dropdown for every row in the prerequisites column.

But what I want is to have, that the dropdown doesn't have the true option in the row where the title is foo

In other words, I want to hide some options in case of some selected rows, based on another column's value in the corresponding row.


Solution

  • EDIT

    With the latest version 2.25.0 of Angular-Slickgrid (see here), we now have an option to override the collection right from the column definitions as asked in the original question. There's also a new Wiki - Collection Override

    For example you can now do this

    this.columnDefinitions = [
      {
        id: 'prerequisites', name: 'Prerequisites', field: 'prerequisites',
        type: FieldType.string,
        editor: {
          model: Editors.multipleSelect,
          collection: [{ value: '', label: '' }, { value: true, label: 'true' }, { value: false, label: 'false' }]
            },
          collectionOverride: (finalCollection, args) => {
            console.log(args); 
            if (args.dataContext.title === 'foo') {
              return finalCollection.filter((col) => col.value !== true);
            }
            return finalCollection;
          },
        }
      }
    ];
    

    Also note that all the Editors, Filters and Formatters are now Public so that it's easier to extend from, e.g. export class CustomSelectEditor extends SelectEditor


    Original Answer Select Editor/Filter was never built with dynamic collection and access to the item dataContext in mind but similar to the other SO Answer I gave to your other SO Question, you can again extend the Select Editor and override the filterCollection() function, which is called just before renderDomElement() and that is the best place to override the output collection before it is passed to the renderDomElement(inputCollection) function

    Note that I did not test the code below but I expect the concept to 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(protected args: EditorArguments, protected isMultipleSelect) {
        super(args, true);
      }
    
      protected filterCollection(): any[] {
        const activeCell: { row: number; cell: number; } = this.grid.getActiveCell();
        const dataContext = this.grid.getDataItem(activeCell.row);
        // your custom logic
        // const customCollection = ...
        return customCollection;
      }
    }
    

    or Editors.singleSelect if SelectEditor is not publicly available and if that is the way to go, then you'll also have to extend Editors.multipleSelect OR create 1 Custom Editor and pass true for multiple or false for single in the super(args, true) call

    import { Editors } from 'angular-slickgrid';
    
    export class CustomSelectEditor extends Editors.inputText {
      constructor(protected args: EditorArguments, protected isMultipleSelect) {
        super(args, true);
      }
    
      protected filterCollection(): any[] {
        const activeCell: { row: number; cell: number; } = this.grid.getActiveCell();
        const dataContext = this.grid.getDataItem(activeCell.row);
        // your custom logic
        // const customCollection = ...
        return customCollection;
      }
    }