Vue Data Grid

Edit Components

vue logo

A Cell Editor Component is the UI that appears, normally inside the Cell, that takes care of the Edit operation. You can select from the Provided Cell Editors or create your own Custom Cell Editor Components.

The example below shows some Provided Editor Components and some Custom Editor Components.

Custom Components

When a Vue component is instantiated the grid will make the grid APIs, a number of utility methods as well as the cell and row values available to you via a params object.

With Vue 2 and Vue 3 you can access the params object via this.params in the usual methods (lifecycle hooks, methods etc), and with Vue 3's setup via props.params.

The editor params interface is as follows:

Vue 3 - Class Based Components & Typed Components

If you're using a Class Based Component (i.e. you're using vue-property-decorator/vue-class-component), or if you're using a vanilla Vue 3 component with lang='ts' then you'll need to specify the params object as a prop.

For example:

<script lang="ts">
   import {defineComponent} from "vue";

   export default defineComponent({
       name: "MyComponent",
       props: ['params'],  // required for TypeScript ...
   })
</script>

Selecting Components

Cell Editor Components are configured using the cellEditor property of the Column Definition.

<ag-grid-vue
    :columnDefs="columnDefs"
    /* other grid options ... */>
</ag-grid-vue>

this.columnDefs = [
    { 
        field: 'name', 
        editable: true, 
        // uses a provided editor, referenced by name
        cellEditor: 'agTextCellEditor' 
    },
    { 
        field: 'name', 
        editable: true, 
        // uses a custom editor, referenced directly
        cellEditor: CustomEditorComp
    },
];

See Registering Custom Components to optionally register components and refernce them by name.

Dynamic Selection

The colDef.cellRendererSelector function allows setting different Editor Components for different Rows within a Column.

The params passed to cellEditorSelector are the same as those passed to the Editor Component. Typically the selector will use this to check the row's contents and choose an editor accordingly.

The result is an object with component and params to use instead of cellEditor and cellEditorParams.

This following shows the Selector always returning back the provided Rich Select Editor:

cellEditorSelector: params => {
    return {
        component: 'agRichSelectCellEditor',
        params: { values: ['Male', 'Female'] }
    };
}

However a selector only makes sense when a selection is made. The following demonstrates selecting between Cell Editors:

cellEditorSelector: params => {

  if (params.data.type === 'age') {
    return {
      component: NumericCellEditor,
    }
  }

  if (params.data.type === 'gender') {
    return {
      component: 'agRichSelectCellEditor',
      params: {
        values: ['Male', 'Female']
      }
    }
  }

  if (params.data.type === 'mood') {
    return {
      component: MoodEditor,
      popup: true,
      popupPosition: 'under'
    }
  }

  return undefined
}

Here is a full example:

  • The column 'Value' holds data of different types as shown in the column 'Type' (numbers/genders/moods).
  • colDef.cellEditorSelector is a function that returns the name of the component to use to edit based on the type of data for that row
  • Edit a cell by double clicking to observe the different editors used.

Dynamic Props

The colDef.cellEditorParams function allows dynamic props independently of the Editor selection. For example you might have a 'City' column that has values based on the 'Country' column.

cellEditorParams: params => {
    const selectedCountry = params.data.country;

    if (selectedCountry === 'Ireland') {
        return {
            values: ['Dublin', 'Cork', 'Galway']
        };
    } else {
        return {
            values: ['New York', 'Los Angeles', 'Chicago', 'Houston']
        };
    }
}

Below shows an example with dynamic props. The following can be noted:

  • Column Gender uses a Cell Component for both the grid and the editor.
  • Column Country allows country selection, with cellHeight being used to make each entry 50px tall. If the currently selected city for the row doesn't match a newly selected country, the city cell is cleared.
  • Column City uses dynamic parameters to display values for the selected country, and uses formatValue to add the selected city's country as a suffix.
  • Column Address uses the large text area editor.

Custom Props

The property colDef.cellEditorParams allows custom props to be passed to editors.

colDef = {
   cellEditor: 'MyCellEditor',    
   cellEditorParams: {
       // make "country" value available to cell editor
       country: 'Ireland'
   },
   // ...other props
}

An editor can be Inline or Popup.

An Inline Editor Component will be placed inside the Grid's Cell, replacing the Cell contents when active.

A Popup Editor Component appears in a popup over the Cell. Popup Editors are not constrained to the Cells dimensions.

Configure that a Custom Cell Editor is in a popup in one of the following ways:

  1. Specify cellEditorPopup=true on the Column Definition.
  2. Implement the isPopup() method on the Custom Cell Editor and return true.
colDefs = [
  {
    cellEditor: MyPopupEditor,
    cellEditorPopup: true
    // ...
  }
]

Popup Editors appear over the editing Cell. Configure the Popup Editor to appear below the Cell in one of the following ways:

  1. Implement the getPopupPosition() method on the Custom Cell Editor and return under.
  2. Specify cellEditorPopupPosition='under' on the Column Definition.
colDef = {
  cellEditorPopup: true,
  cellEditorPopupPosition: 'under',
  // ...other props
}

Keyboard Navigation

In Custom Editors, you may wish to disable some of the Grids keyboard navigation. For example, if you are providing a simple text editor, you may wish the grid to do nothing when you press the right and left arrows (the default is the grid will move to the next / previous cell) as you may want the right and left arrows to move the cursor inside your editor. In other cell editors, you may wish the grid to behave as normal.

Because different cell editors will have different requirements on what the grid does, it is up to the cell editor to decide which event it wants the grid to handle and which it does not.

You have two options to stop the grid from doing it's default action on certain key events:

  1. Stop propagation of the event to the grid in the cell editor.
  2. Tell the grid to do nothing via the colDef.suppressKeyEvent() callback.

Option 1 - Stop Propagation

If you don't want the grid to act on an event, call event.stopPropagation(). The advantage of this method is that your cell editor takes care of everything, this is good for creating reusable cell editors.

The following code snippet is one you could include for a simple text editor, which would stop the grid from doing navigation.

const KEY_LEFT = 'ArrowLeft';
const KEY_UP = 'ArrowUp';
const KEY_RIGHT = 'ArrowRight';
const KEY_DOWN = 'ArrowDown';
const KEY_PAGE_UP = 'PageUp';
const KEY_PAGE_DOWN = 'PageDown';
const KEY_PAGE_HOME = 'Home';
const KEY_PAGE_END = 'End';

const MyCellEditor = {
   template: `<input v-model="value" @keydown="onKeyDown" />`,
   data() {
       return {
           value: null
       };
   },
   methods: {
       /* Component Editor Lifecycle method */
       getValue() {
           return this.value;
       },
       
       onKeyDown(event) {
          const key = event.key;

          const isNavigationKey = key === KEY_LEFT ||
              key === KEY_RIGHT ||
              key === KEY_UP ||
              key === KEY_DOWN ||
              key === KEY_PAGE_DOWN ||
              key === KEY_PAGE_UP ||
              key === KEY_PAGE_HOME ||
              key === KEY_PAGE_END;

              if (isNavigationKey) {
                  // this stops the grid from receiving the event and executing keyboard navigation
                  event.stopPropagation();
              }
       }
   },
   mounted() {
       this.value = this.params.value;
   }
}

Option 2 - Suppress Keyboard Event

If you implement colDef.suppressKeyboardEvent(), you can tell the grid which events you want to process and which not. The advantage of this method of the previous method is it takes the responsibility out of the cell editor and into the column definition. So if you are using a reusable, or third party, cell editor, and the editor doesn't have this logic in it, you can add the logic via configuration.

const KEY_UP = 'ArrowUp';
const KEY_DOWN = 'ArrowDown';

const MyGrid = {
   template: `
      <ag-grid-vue
          class="ag-theme-quartz"
          :columnDefs="columnDefs">
      </ag-grid-vue>
   `,
   components: {
       'ag-grid-vue': AgGridVue
   },
   data: function () {
       return {
           columnDefs: [
              {
                  headerName: "Value Column",
                  field: "value",
                  suppressKeyboardEvent: params => {
                      console.log('cell is editing: ' + params.editing);
                      console.log('keyboard event:', params.event);
               
                      // return true (to suppress) if editing and user hit up/down keys
                      const key = params.event.key;
                      const gridShouldDoNothing = params.editing && (key === KEY_UP || key === KEY_DOWN);
                      return gridShouldDoNothing;
                  }
              }
           ]
       }
   },

   // rest of the component
}

Accessing Instances

After the grid has created an instance of an Editor Component for a Cell it is possible to access that instance. This is useful if you want to call a method that you provide on the Editor that has nothing to do with the operation of the grid. Accessing Editors is done using the grid API getCellEditorInstances(params).

If you are doing normal editing, then only one cell is editable at any given time. For this reason if you call getCellEditorInstances() with no params, it will return back the editing cell's editor if a cell is editing, or an empty list if no cell is editing.

An example of calling getCellEditorInstances() is as follows:

const instances = api.getCellEditorInstances(params);
if (instances.length > 0) {
   const instance = instances[0];
}

The example below shows using getCellEditorInstances. The following can be noted:

  • All cells are editable.
  • First Name and Last Name use the default editor.
  • All other columns use the provided MySimpleCellEditor editor.
  • The example sets an interval to print information from the active cell editor. There are three results: 1) No editing 2) Editing with default cell renderer and 3) editing with the custom cell editor. All results are printed to the developer console.