docs/modules/DataSources.md
DataSources are a powerful feature in GrapesJS that allow you to manage and inject data into your components, styles, and traits programmatically. They help you bind dynamic data to your design elements and keep your user interface synchronized with underlying data models.
To start using DataSources, you need to create them and add them to GrapesJS.
Example: Creating and Adding a DataSource
const editor = grapesjs.init({
container: '#gjs',
});
const datasource = {
id: 'my-datasource',
records: [
{ id: 'id1', content: 'Hello World' },
{ id: 'id2', color: 'red' },
],
};
editor.DataSources.add(datasource);
You can reference DataSources within your components to dynamically inject data.
Example: Using DataSources with Components
editor.addComponents([
{
tagName: 'h1',
type: 'text',
components: [
{
type: 'data-variable',
defaultValue: 'default',
path: 'my-datasource.id1.content',
},
],
},
]);
In this example, the h1 component will display "Hello World" by fetching the content from the DataSource with the path my-datasource.id1.content.
DataSources can also be used to bind data to CSS properties.
Example: Using DataSources with Styles
editor.addComponents([
{
tagName: 'h1',
type: 'text',
components: [
{
type: 'data-variable',
defaultValue: 'default',
path: 'my-datasource.id1.content',
},
],
style: {
color: {
type: 'data-variable',
defaultValue: 'red',
path: 'my-datasource.id2.color',
},
},
},
]);
Here, the h1 component's color will be set to red, as specified in the DataSource at my-datasource.id2.color.
Traits are used to bind DataSource values to component properties, such as input fields.
Example: Using DataSources with Traits
const datasource = {
id: 'my-datasource',
records: [{ id: 'id1', value: 'I Love Grapes' }],
};
editor.DataSources.add(datasource);
editor.addComponents([
{
tagName: 'input',
traits: [
'name',
'type',
{
type: 'text',
label: 'Value',
name: 'value',
value: {
type: 'data-variable',
defaultValue: 'default',
path: 'my-datasource.id1.value',
},
},
],
},
]);
In this case, the value of the input field is bound to the DataSource value at my-datasource.id1.value.
Transformers in DataSources allow you to customize how data is processed during various stages of interaction with the data. The primary transformer functions include:
onRecordSetValueThis transformer is invoked when a record's property is added or updated. It provides an opportunity to validate or transform the new value.
const testDataSource = {
id: 'test-data-source',
records: [],
transformers: {
onRecordSetValue: ({ id, key, value }) => {
if (key !== 'content') {
return value;
}
if (typeof value !== 'string') {
throw new Error('Value must be a string');
}
return value.toUpperCase();
},
},
};
In this example, the onRecordSetValue transformer ensures that the content property is always an uppercase string.
GrapesJS allows you to control whether a DataSource should be stored statically in the project JSON. This is useful for managing persistent data across project saves and loads.
skipFromStorage KeyWhen creating a DataSource, you can use the skipFromStorage key to specify whether it should be included in the project JSON.
Example: Creating a DataSource with skipFromStorage
const persistentDataSource = {
id: 'persistent-datasource',
records: [
{ id: 'id1', content: 'This data will be saved' },
{ id: 'id2', color: 'blue' },
],
};
editor.DataSources.add(persistentDataSource);
const temporaryDataSource = {
id: 'temporary-datasource',
records: [
{ id: 'id1', content: 'This data will not be saved' },
],
skipFromStorage: true,
};
editor.DataSources.add(temporaryDataSource);
In this example, persistentDataSource will be included in the project JSON when the project is saved, while temporaryDataSource will not.
skipFromStorageWhen a project is loaded, GrapesJS will automatically restore the DataSources that were saved. You can then access and use these DataSources as usual.
// After loading a project
const loadedDataSource = editor.DataSources.get('persistent-datasource');
console.log(loadedDataSource.getRecord('id1').get('content')); // Outputs: "This data will be saved"
Remember that DataSources with skipFromStorage: true will not be available after a project is loaded unless you add them programmatically.
DataSource records are mutable by default, but can be set as immutable to prevent modifications. Use the mutable flag when creating records to control this behavior.
const dataSource = {
id: 'my-datasource',
records: [
{ id: 'id1', content: 'Mutable content' },
{ id: 'id2', content: 'Immutable content', mutable: false },
],
};
editor.DataSources.add(dataSource);
const ds = editor.DataSources.get('my-datasource');
ds.getRecord('id1').set('content', 'Updated content'); // Succeeds
ds.getRecord('id2').set('content', 'New content'); // Throws error
Immutable records cannot be modified or removed, ensuring data integrity for critical information.
DataSources are integrated with GrapesJS's runtime and BackboneJS models, enabling dynamic updates and synchronization between your data and UI components. This allows you to:
Example: Using DataSources to Manage a Counter
const datasource = {
id: 'my-datasource',
records: [{ id: 'id1', counter: 0 }],
};
editor.DataSources.add(datasource);
editor.addComponents([
{
tagName: 'span',
type: 'text',
components: [
{
type: 'data-variable',
defaultValue: 'default',
path: 'my-datasource.id1.counter',
},
],
},
]);
const ds = editor.DataSources.get('my-datasource');
setInterval(() => {
console.log('Incrementing counter');
const counterRecord = ds.getRecord('id1');
counterRecord.set({ counter: counterRecord.get('counter') + 1 });
}, 1000);
In this example, a counter is dynamically updated and displayed in the UI, demonstrating the real-time synchronization capabilities of DataSources.
Examples of How DataSources Could Be Used: