Although a little different than I had initially anticipated, I have found/created a solution to my two problems.
Conditionals
I have opted to move non-required input to the sidebar, using the InspectorControls
-element. Reason for this is that I realised that it would be impossible to hide a field (in the editor-part of the screen) that was left blank (required to show an accurate front-end representation), while still being able to edit that field.
For example, this is the definition of a textfield in the sidebar.
el(TextControl, {
type: 'text',
value: attr.location,
label: __('Location', 'peerlings-blocks'),
onChange: function (newLocation) {
props.setAttributes({location: newLocation})
}
}),
This is (in the edit
– and save
-parts) the code used for displaying it, if the field has been used
attr.location && el('span', {className: 'location'}, attr.location),
The reason why I originally didn’t want to move these details to the sidebar was that I thought they then wouldn’t show in the editor-preview, but using the code above, that was possible to achieve. Problem solved.
Separators and wrappers
This took some more fiddling to get to work, for which I had a few revelations:
- The
selector
(defined as part of anyattribute
) looks at the HTML extracted frompost_content
to find the value of a particular attribute. If this selection finds other HTML than expected, the block validation fails. - The
edit
-part is used to display the block-‘preview’ in the WordPress Dashboard. Also, it reads the HTML frompost_content
, when a block is edited again. On the other hand, thesave
-part transforms the attribute values to a HTML that is sent to (and saved in)post_content
. Essentially,save
encodes the block to HTML,edit
decodes the HTML to attributes (found in the selectors discussed previously). This explains why minor differences between the two (in the parts found by the selectors) immediately invalidate the block.
Given the above, I placed the separators and wrappers outside of the elements that are selected to retrieve the attributes. That resulted in some extra wrapper elements, but does the trick. To illustrate, the shortcode had the following HTML output:
<span class="cv-item-details">08/2013 - current | 6 hours per week</span>
Now, that line looks like this:
<span class="resume-item-details">
<span class="duration">
08/2013 – current
</span>
|
<span class="hours">
<span class="data">
6
</span>
hours per week
</span>
</span>
The problems I had originally envisioned (separators in between block-level input fields) were essentially solved by moving a number of input fields to the sidebar (as outlined above). Separators between input fields that do remain are only included in the save
-part, and that works as intended – as shown in the code below.
edit
-part:
el('span', {className: 'resume-item-title'},
el(RichText, {
key: 'editable',
tagName: 'strong',
className: 'name',
placeholder: __('Name', 'peerlings-blocks'),
keepPlaceholderOnFocus: true,
value: attr.name,
onChange: function (newName) {
props.setAttributes({name: newName})
}
}),
el(RichText, {
key: 'editable',
className: 'organisation',
placeholder: __('Organisation', 'peerlings-blocks'),
keepPlaceholderOnFocus: true,
value: attr.organisation,
onChange: function (newOrganisation) {
props.setAttributes({organisation: newOrganisation.replace('<br>', '')})
}
})
),
save
-part (note the comma between the two RichText
-parts, conditional on attr.organisation
not being empty):
el('span',
{className: 'resume-item-title'},
el(RichText.Content, {
tagName: 'strong',
className: 'name',
value: attr.name
}),
attr.organisation && ', ',
el(RichText.Content, {
tagName: 'span',
className: 'organisation',
value: attr.organisation
})
),
You can find the full JS-file of the block (at least, the current version) here.