Feature section
Adding the content type definition
Basically, here is an overview:
The mapping from the definition to the visual elements is similar to what we have seen in the hero section, except that we now have one element that contains multiple sub-elements.
This is done using the following line:
+ * (solidTemplate:feature)
This is a child node definition that is restricted to a single content node type solidTemplate:feature
.
The type definition is just below in the above illustration and is rather straightforward.
For the icon, we use a reference to an image that may be uploaded by content editors.
First we must add the definitions for both components in our definitions.cnd
file:
[solidTemplate:featureSection] > jnt:content, solidTemplatemix:solidTemplateComponents
+ * (solidTemplate:feature)
Then for the feature
[solidTemplate:feature]
- title (string) = 'Be Productive' i18n
- icon (weakreference, picker[type='image'])
- text (string) = 'Fermentum posuere urna nec tincidunt praesent semper feugiat nibh. A arcu cursus vitae congue mauris. Nam at lectus urna duis convallis. Mauris rhoncus aenean vel elit scelerisque mauris.' i18n
Creating a feature view
The view for the solidTemplate:feature
is created in the $NPM_TEMPLATE/src/server/views/feature/FeatureDefault.jsx
file with the following content:
import React from 'react';
import {useServerContext, getNodeProps, buildUrl, defineJahiaComponent} from '@jahia/js-server-core';
export const FeatureDefault = () => {
const {currentNode, renderContext, currentResource} = useServerContext();
const props = getNodeProps(currentNode, ['icon', 'title', 'text']);
return (
<div className="feature text-center is-revealing">
<div className="feature-inner">
<div className="feature-icon">
{props.icon &&
<img srcSet={buildUrl({path:props.icon.getPath()}, renderContext, currentResource)} alt="Feature"/>
}
</div>
<h4 className="feature-title mt-24">{props.title}</h4>
<p className="text-sm mb-0">{props.text}</p>
</div>
</div>
)
}
FeatureDefault.jahiaComponent = defineJahiaComponent({
nodeType: 'solidTemplate:feature',
displayName: 'Feature',
componentType: 'view'
})
Again the HTML was copied from the static HTML template and modified to insert the content node properties.
Creating a feature section view
The parent feature section view is created in $NPM_TEMPLATE/src/server/views/featureSection/FeatureSectionDefault.jsx
with the following content:
import React from 'react';
import {Render, AddContentButtons, useServerContext, getChildNodes, defineJahiaComponent} from '@jahia/js-server-core';
export const FeatureSectionDefault = () => {
const {currentNode} = useServerContext();
const allChildren = getChildNodes(currentNode, -1);
return (
<section className="features section">
<div className="container">
<div className="features-inner section-inner has-bottom-divider">
<div className="features-wrap">
{allChildren && allChildren.map(child =>
<Render path={child.getPath()} key={child.getIdentifier()} />
)}
</div>
<AddContentButtons />
</div>
</div>
</section>
)
}
FeatureSectionDefault.jahiaComponent = defineJahiaComponent({
nodeType: 'solidTemplate:featureSection',
displayName: 'Feature section',
componentType: 'view'
})
You can see here that we are using getChildNodes
helper function to easily retrieve all the child nodes of the current node (The -1 count indicates we force the retrieval of all the nodes, which is something that should never be done in production views to avoid potential performance issues). To render them, we first check that we do have child nodes and then iterate over them using a map function and a Render
component, which will then call the FeatureDefault.jsx
view to render the child node. The <AddContentButtons
/>
is used to position the button to add new content entries.
Exporting the views
Then we need to export our two views, we first need to create a src/server/views/feature/index.js
file with the following content:
export * from './FeatureDefault';
And then create a src/server/views/featureSection/index.js
file with the following content:
export * from './FeatureSectionDefault';
And finally we must add the new types to the main src/server/views/index.js
file with the following content:
export * from './featureSection';
export * from './feature';
We can now get rid of the whole section from the $NPM_TEMPLATE/src/server/templates/page/PageHome.jsx
template, so simply remove:
<section className="features section">
... content removed for brievety...
</section>
Creating the content
Let’s add the feature section content now. Make sure you refresh your browser first and that everything is working. Click the New content
button again to open up the content type selection dialog:
Select the featureSection
and click CREATE
If you remember from the definition, the feature section has no self-defined properties, so we can simply click SAVE
to create it and click the back arrow to come back to the Page Builder. We now see a feature
button that appears in the new feature section.
Clicking the New feature
button will directly open the content editing window, bypassing the content type selection since we already know which type we want to edit:
The feature content object is already filled out with the default values so we can simply leave them as they are. Let’s then click on Select an image
for the icon:
We basically get an empty image selection screen, as our project never had any images added to it. Let’s quickly upload some images by clicking on the Upload file
button. It is possible to upload more than one file at the same time, so here we navigate to the $HTML_TEMPLATE/dist/images
directory and select all the feature-icon*.svg
files:
Simply click Open
once they are selected, this will trigger the upload process and the image selection screen will refresh to display the newly uploaded images. We can then select the feature-icon-01.svg
as illustrated in this screenshot:
Finally click the SELECT
button to return to the content editing screen:
Click the SAVE
button.
You should now see your feature displayed. works normally.
You can then repeat this process to create as many features as you’d like.
Next step
Continue to finishing up your integration