Applying editors to Grid cells
The Grid widget provides a predefined number of inline editors that can be applied to a column cell: text, combo, richselect, datepicker. Moreover, you can apply custom editors to column cells.
Applying in-built inline editors
To apply the inline editor to column cells, set the editor parameter of the columns property to the required value: "text" | "combo" | "datepicker" | "richselect". In this case all cells within a column will have the same editor type.
Example:
<script>
import { Grid } from "@svar-ui/svelte-grid";
import { getData } from "./common/data";
const { data, countries, users } = getData();
const columns = [
{ id: "id", width: 50 },
{
id: "firstName",
header: 'Name - "text"',
editor: "text",
width: 180,
},
{
id: "country",
header: 'Country - "combo"',
editor: {
type: "combo",
config: { template: (option) => `${option.id}. ${option.name}` },
},
options: countries,
width: 180,
},
{
id: "date",
header: 'Date - "datepicker"',
width: 180,
editor: "datepicker",
template: (v) => (v ? v.toLocaleDateString() : ""),
},
{
id: "assigned",
header: 'Users - "richselect"',
width: 180,
editor: "richselect",
options: users,
},
];
</script>
<Grid {data} {columns} />
Related samples:
Disabling editors
There are two common ways to disable the editor for specific cells:
Option 1. You can intercept the editor opening event and return false to prevent the editor from opening under certain conditions. For example, to disable editing of the "date" column for the row with id 1:
<script>
import { Grid } from "@svar-ui/svelte-grid";
import { getData } from "../data";
const { data } = getData();
let api = $state();
if (api) {
api.intercept("open-editor", (ev) => {
if (ev.column === "date" && ev.id === 1) {
return false; // block the editor
}
});
}
const columns = [
{ id: "id", header: "ID", width: 60 },
{ id: "firstName", header: "First Name", editor: "text", width: 180 },
{
id: "date",
header: "Date",
editor: "datepicker",
width: 200,
},
];
</script>
<Grid {data} {columns} bind:this={api} />
Option 2. Alternatively, you can configure the editor property on a column as a function that receives the row and column info and returns the editor type or undefined/null to disable editing for that cell:
<script>
import { Grid } from "@svar-ui/svelte-grid";
import { getData } from "../data";
const { data } = getData();
const columns = [
{ id: "id", header: "ID", width: 60 },
{ id: "firstName", header: "First Name", editor: "text", width: 180 },
{
id: "date",
header: "Date",
width: 200,
editor: (row, column) => {
// only enable editor for rows other than id === 1
if (row.id !== 1) {
return "datepicker";
}
// returning nothing disables editing for this cell
}
},
];
</script>
<div style="padding: 20px;">
<h4>The "Date" column is not editable in row with ID 1</h4>
<Grid {data} {columns} />
</div>
Related samples: Disabled cell inline editors
Applying dynamic editors
If your data is heterogeneous and you want to assign different editors to cells within the same column based on the row data, you can specify the editor property as a function in the column configuration. This function returns the desired editor type or editor configuration depending on the row.
Example:
// mapping of column ids to their editors or editor configs
const editors = {
firstName: "text",
date: "datepicker",
country: {
type: "combo",
config: {
template: option => option.label,
options: countries,
},
},
};
const columns = [
{
id: "value",
editor: row => editors[row.id], // dynamically choose editor by row.id
template: (value, row) => {
if (row.id === "country") {
return countries.find(c => c.id === value)?.label || value;
}
return value instanceof Date ? value.toLocaleDateString() : value;
},
}
];
<Grid {data} {columns} />
Make sure to pass the proper options to combo or richselect editors via their config. Define the template for the column to correctly display different data types depending on the editor used.
Customizing in-built editors
The Grid API allows applying a template and custom Svelte component to the cell editor (except the "text" type editor) via the config object of the editor parameter in the columns property.
Applying a template
You can customize how dropdown options or input fields are displayed by providing a template function inside the editor.config object. The function receives a single option and should return a string (template?:(obj) => string).
The example below shows how to apply a template to the "combo" editor in the Country column. Each option in the example will be displayed in the format id.label (e.g., 1.USA).
<script>
import { Grid } from "@svar-ui/svelte-grid";
import { getData } from "../data";
const { data, countries } = getData();
const columns = [
{ id: "id", width: 50 },
{
id: "country",
header: 'Country - "combo"',
editor: {
type: "combo",
config: {
template: option => `${option.id}. ${option.label}`,
},
},
options: countries,
width: 180,
},
];
</script>
<Grid {data} {columns} />
Please note: for the combo editor, a template function is applied to the dropdown options, while for datepicker, it will be applied to the input field.
Applying a custom component
You can apply your custom Svelte component to the editor cell by specifying it in editor.config.cell.
In the example below the StatusStub component is applied to the richselect editor. The cell property in the config object takes the custom component name (StatusStub) that should be applied to the editor.
<script>
import { Grid } from "@svar-ui/svelte-grid";
import { getData } from "../data";
import StatusStub from "../custom/StatusStub.svelte";
const { data, users } = getData();
const statuses = [
{ id: 1, label: "In progress", type: "primary" },
{ id: 2, label: "Done", type: "success" },
{ id: 3, label: "Not started", type: "disabled" },
];
const columns = [
{ id: "id", width: 50 },
{
id: "status",
header: 'Status - "richselect"',
editor: {
type: "richselect",
config: { cell: StatusStub },
},
options: statuses,
width: 180,
},
];
</script>
<Grid {data} {columns} />
StatusStub.svelte:
<script>
let { data } = $props();
</script>
<div class="status {data.type}">
<div class="status-wrapper">
<div class="dot"></div>
<span class="name">{data.label}</span>
</div>
</div>
<style>
.status {
height: 100%;
width: 100%;
display: flex;
align-items: center;
}
.status .status-wrapper {
border-radius: 18px;
padding: 2px 8px;
display: flex;
gap: 4px;
align-items: center;
justify-content: center;
position: relative;
}
.status .status-wrapper::before {
position: absolute;
height: 100%;
width: 100%;
content: "";
border-radius: 18px;
opacity: 0.15;
}
.status .dot {
height: 6px;
width: 6px;
border-radius: 50%;
}
</style>
When customizing the multiselect editor, please note that its editor.config.cell component is used both as a dropdown list option and editor display cell, so you should check which data comes as a prop.
- In the dropdown list — data is a single option object
- In the opened editor cell — data is an array of the currently selected option objects
Component example:
<script>
let { data } = $props();
</script>
{#if Array.isArray(data)}
<!-- grid cell: data is an array of selected items -->
<span>{data.map(item => item.label).join(", ")}</span>
{:else}
<!-- suggest list item: data is a single option -->
<span>{data.label}</span>
{/if}
Apply the component to the column:
<script>
import { Grid } from "@svar-ui/svelte-grid";
import { getData } from "./common/data";
import MultiSelectCell from "./custom/MultiSelectCell.svelte";
const { data, countries } = getData();
const columns = [
{ id: "id", width: 50 },
{
id: "destinations",
header: "Destinations",
editor: {
type: "multiselect",
config: { cell: MultiSelectCell },
},
options: countries,
width: 250,
},
];
</script>
<Grid {data} {columns} />
Related sample: Custom cell editors
Applying custom editors
Grid allows adding custom components to column cells. The rules of embedding custom components are described here: Adding custom content to cells
The example below shows how to customize the Checkbox component and call the update-cell action via the api.exec() method so that the cell is updated directly in Grid.
<script>
import { Checkbox } from "@svar-ui/svelte-core";// import the Checkbox component
let { row, column, api } = $props();// get access to Grid api via `$props`
function onChange(ev) {
const { value } = ev;
api.exec("update-cell", { //call the action
id: row.id,
column:column.id,
value
});
}
</script>
<Checkbox value={row[col.id]} onchange={onChange} />
In the next example we import the component and apply it to the Grid cell:
<script>
import CheckboxCell from "../custom/CheckboxCell.svelte";
import { Grid } from "@svar-ui/svelte-grid";
import { getData } from "./common/data";
const { data } = getData();
let cell;
const columns = [
{ id: "id", width: 50 },
{ id: "checked", cell: CheckboxCell, width: 36 },
];
</script>
<Grid {data} {columns} />
Adding a custom editor type
You can also register your own Svelte component as an inline editor using the registerInlineEditor helper.
Step 1. Create your custom editor component
A custom editor is a regular Svelte component and receives context props from Grid. Use $props to access the cell context and the editor callbacks:
<script>
import { onMount } from "svelte";
import { ColorBoard, Dropdown } from "@svar-ui/svelte-core";
import { clickOutside } from "@svar-ui/lib-dom";
let { editor, onsave, onapply, oncancel } = $props();
let value = $state(editor.value);
function updateValue({ value, input }) {
if (input) onapply(value);
else onsave();
}
let node;
onMount(() => {
node.focus();
if (window.getSelection) {
window.getSelection().removeAllRanges();
}
});
</script>
<div class="value" bind:this={node} tabindex="0" onclick={oncancel}>
{value}
</div>
<Dropdown width={"auto"}>
<div use:clickOutside={() => onsave(true)}>
<ColorBoard {value} onchange={updateValue} button={true} />
</div>
</Dropdown>
The component receives the following props from Grid:
editor.value— the current cell valueonsave()— confirms and closes the editoronapply(value)— updates the cell value without closing the editoroncancel()— discards changes and closes the editor
Grid does not automatically close dropdowns. If your custom editor uses a Dropdown, you need to handle its closing logic yourself. In the example above, the clickOutside is used to call onsave() when the user clicks outside.
Step 2. Register the custom component
Once the component is created, register it using registerInlineEditor before the Grid is initialized. The first argument is the type name that you should then also specify in column definitions, and the second is the component itself:
import { Grid, registerInlineEditor } from "@svar-ui/svelte-grid";
import ColorEditor from "../custom/ColorEditor.svelte";
registerInlineEditor("color", ColorEditor);
registerInlineEditor follows the same pattern used by other SVAR component registries (Menu, Toolbar, Editor), so the registered editor becomes available globally across all Grid instances in your application.
Step 3. Apply the custom editor to a column
After registration, to apply the component, add the custom editor's type name to the editor property of the relevant column. You can also pair it with a custom cell:
<script>
import { Grid, registerInlineEditor } from "@svar-ui/svelte-grid";
import { getData } from "../data";
import ColorEditor from "../custom/ColorEditor.svelte";
import ColorCell from "../custom/ColorCell.svelte";
registerInlineEditor("color", ColorEditor);
const { data } = getData();
const columns = [
{ id: "id", width: 50 },
{ id: "name", header: "Name", editor: "text", width: 160 },
{
id: "color",
header: "Color",
editor: "color", // reference the registered editor by type name
cell: ColorCell, // optional: custom component for rendering the column value
width: 120,
},
];
</script>
<Grid {data} {columns} />
Related samples
Related articles: