wf-html
Intro
In a XalokNext project, the App/Bundle/CmsBundle/Resources/views/Template
directory holds the templates that are being used to build blocks of content that are editable through the UI. One or more article templates can be defined, their respective wf-html should be placed in the App/Bundle/CmsBundle/Resources/views/Template/Article
directory.
Besides being able to edit article contents, XalokNext allows defining editable blocks of contents called boards - their wf-html should be placed in the App/Bundle/CmsBundle/Resources/views/Template/Board
directory.
Twig is being used for wf-html to leverage the twig templating language capabilities:
- extend other templates: e.g. the
Article/default-amp.html.twig
extendsArticle/default.html.twig
, as it's almost identical to it, overwriting only the parts that are different) - translate strings:
0
) - include other twig files - the most notable example being including twigs from
App/Bundle/CmsBundle/Resources/views/TemplateModules
.
It's important to know that the twig files themselves are not being used at runtime (when rendering an article/board), rather, they are being downloaded by either make wf_assets
(in the CI environment) or by the wf-assets-watch
gulp task that is included as part of make dev
. Either of these tasks download the files as static html (in web/bundles/wfcmsbaseadmin/javascripts/html_template
directory), from here they are picked up by webpack that bundles them together with the rest of the JS code, where they're being used.
Text modules
In a wf-html
you can include whatever HTML structure that the frontend design requires. When editing an article/board, this HTML is shown to the user in a WYSIWG editor.
To make some parts editable as text, one has to annotate the HTML element with the wf-role
attribute:
<article>
<div class="title">
<h1 wf-role="title"></h1>
</div>
</article>
The value of the wf-role
attribute is a string of your own choice (all projects have used by convention alphanumeric strings with _
as separator, e.g.: wf-role="main_image"
). You can read some details on this on the Modules page.
wf-new
All the wf-role
elements are removed from the HTML at the compilation step. Where modules are defined, the editor is shown a button to add a module of that type. But some modules are known at developing time to be required - e.g.: a title module inside an article, or a board that allows embedding 3 articles, could start with 3 empty modules to avoid the extra clicks needed to add the modules. For this you can use wf-new
attribute:
<h1 wf-role="title"
wf-new
></h1>
If more instances of the same module are needed, you can also specify a number:
<div wf-role="article"
wf-new="3"
></div>
wf-allow
Using wf-allow
, one can specify whether there can be multiple instances of the same module or not.
<h1 wf-role="title"
wf-new
wf-allow="" <!-- don't allow neither adding, nor deleting the `title` module, there should be one and just one `title` -->
></h1>
<div wf-role="main_image"
wf-new
wf-allow="-" <!-- allow deleting the `main_image` module, it can be added back, but don't allow adding more than one `main_image`. -->
></div>
<p wf-role="paragraph"
wf-allow="+-" <!-- allow zero or more paragraphs -->
></p>
Composite modules
Intro
Besides being able to edit text modules, XalokNext allows to embed content models - entities external to the current content, like images, videos, files (attachments), polls, etc. This is done through the use of composite modules. These modules also allow grouping one or more submodules.
Content models
In a browser open __PUBLIC_URL__/developer
- there is a section Content types that lists the available content types that you can embed inside a composite.
Example: Dump all the contents of the content model:
<div wf-role="image">
[[ image ]]
</div>
Given the above code, XalokNext automatically detects the use of the image
content type and adds an edit button to the toolbar of the module. Clicking this button allows the editor to choose an image.
The same happens for the other content models that are registered in the project. Note that by default, XalokNext register content models with the following types: image
, video
, audio
, page
, poll
, file
, listing
, tag
, category
.
After choosing an image, click the debug button on the module's toolbar and check the DevTools console. It will log an object with all the variables that can be used inside this module. Use it to inspect properties of the image
model that you've chosen.
Augmenting content models
All the content models that are selected in an editor go through an augmenting process - some code that adds properties to the details that the server sends. For example, image
content models get a src
property that is a value computed like:
// Example code that already exists in
// vendor/wfcms/standard/Wf/Bundle/CmsEditorBundle/Resources/public/javascripts/wfvue/content_models/augment_content_models.js
// This is contrived for brevity
image.src = computed(() => {
return `uploads/${image.uploadPrefix}/${image.imageName}`;
})
The same applies for video
, file
and audio
contentModels.
Another example for using this that already exists in XalokNext base is for article (page
content model) authors, it adds a page.signature
property (if it's not already sent by the server) that is obtained by concatenating the first and last names.
If one needs to work with images that are custom for a project (e.g.: a logo
image assigned to a category), that image must go through a similar process in order to make it usable by wf-filter. To do so:
// in config.js
Object.assign(adminConfig.webpack.resolve.alias, {
"wfed/wfvue/content_models/augment_content_models":
"admin/wfvue/content_models/augment_content_models",
});
Example: Allow using page.category?.logo
as an image inside a composite module:
// in src/App/Bundle/CmsAdminBundle/Resources/public/javascripts/wfvue/content_models/augment_content_models.js
define([
"wfvue",
"_wfed/wfvue/content_models/augment_content_models",
], function (wfvue) {
const baseAugmentContentModel = wfvue.bridgeCommon.augmentContentModel;
const contentModelFromServer = wfvue.contentModelFromServer;
wfvue.bridgeCommon.augmentContentModel = (contentModel) => {
contentModel = baseAugmentContentModel(contentModel);
switch (contentModel.contentType) {
case "page":
if (contentModel.category?.logo) {
baseAugmentContentModel(
contentModelFromServer(contentModel.category.logo)
);
}
break;
}
return contentModel;
};
});
Then, the wf-html can use that image:
<div wf-role="article">
<img wf-filter:name_of_the_imagine_filter="page.category?.logo" />
</div>
Grouping modules
Inside a composite module one can nest text submodules or other composite modules.
Example: Nesting submodules
<div wf-role="image">
<span wf-role="description"
wf-cm-text="image.description"
></span>
<span wf-role="caption"
wf-cm-text="image.caption"
></span>
</div>
Read the documentation of the wf-directives for a list of builtin wf-directives.