Nested List Components
Sitevision 6.1 introduces the ability to pass options to a component on render. This improvement simplifies creation of nested List Components. This is a quick tutorial on how to get started.
Mission
This example will demonstrate how to render a nested List Component, in the form of a timeline of entries, where each entry can hold an array of comments.
The data structure
The initial state of the app looks like this. This is the state that will be populated in the WebApp's store.
const entries = [
{
id: 'b712',
author: 'John',
message: 'Hello mates!',
comments: [
{
id: '4b15',
author: 'Jane Tigerblood',
message: 'WINNING!'
},
{
id: '4c43',
author: 'Joe',
message: 'Second is first loser'
}
]
},
{
id: '43eb',
author: 'Jane',
message: 'Howdy partner!',
comments: [
{
id: 'b16a',
author: 'John',
message: 'What are you driving today?'
},
{
id: '40e8',
author: 'Joe',
message: 'Audi, partner!'
}
]
}
];
Component setup
- Entries.js (List Component)
- Entry.js (Component)
- Comments.js (List Component)
- Comment.js (Component)
Entries.js
define(require => {
'use strict';
const ListComponent = require('ListComponent');
return ListComponent.extend({
tagName: 'ul',
childProperty: 'entries',
childComponentPath: 'Entry',
// The component retrieves what it needs from the store state
filterState: state => {
return Object.assign({}, {
entries: state.entries
});
}
});
});
Entry.js
State for a child component should be retrieved from the store state using id from the new options
argument.
define(require => {
'use strict';
const
Component = require('Component'),
template = require('/template/entry');
return Component.extend({
template: template,
// NEWS!
// filterState now receives a second parameter (options) that contains the id
// of the specific item it renders. The id should be used to retrieve data from the store state.
// Given that, make sure your children (entries in this example) have an id attribute.
filterState: (state, options) => {
const entry = state.entries.find(entry => entry.id === options.id);
return Object.assign({}, entry);
}
});
});
entry.html
When rendering the Comments component, we pass an option to help identify correct data in the filterState
method.
<h4><%- author %></h4>
<p><%- message %></p>
<!-- NEWS! Passing options to a component -->
<!-- We pass down the id of the entry to the Comments component -->
<!-- entryId will be available as options and in the filterState method -->
<%= renderer.renderComponent('Comments', {entryId: id}) %>
Comments.js
The entryId
passed on render will be available on this.options
as well as on the options
argument in filterState.
define(require => {
'use strict';
const ListComponent = require('ListComponent');
return ListComponent.extend({
tagName: 'ul',
childProperty: 'comments',
childComponentPath: 'Comment',
// Pass down the entryId to the children (Comment)
// Will be used to retrieve data from the store state
childOptions: function() {
return {
entryId: this.options.entryId
};
},
// The options argument contains the entryId which we passed on render
// Here it is used to retrieve data from the store state
filterState: (state, options) => {
const entry = state.entries.find(entry => entry.id === options.entryId);
return Object.assign({}, {
comments: entry.comments
});
}
});
});
Comment.js
To retrieve data for a specific comment we use entryId
and id
that are available on the options
argument. The entryId
is passed from childOptions
of the Comments component and the id
refers to the child item that is being rendered.
define(require => {
'use strict';
const
Component = require('Component'),
template = require('/template/comment');
return Component.extend({
template: template,
// options is populated with entryId (from parent component)
// and id (from the item being rendered)
filterState: (state, options) => {
const entry = state.entries.find(entry => entry.id === options.entryId);
const comment = entry.comments.find(comment => comment.id === options.id);
return Object.assign({}, comment);
}
});
});
Summary
Passing options on render will ease the creation of nested List Components as it will be easier to locate which data a child component should retrieve from the store.
Component reusability between WebApps will also be simplified since general components can be built utilizing passed options instead of relying on state coming from the store.
Do you want to subscribe to News from Sitevision Developer team? Subscribe here!