I am trying to extend the render of the htmlSerializer
so I can add additional dynamic params/props to the rendered HTML.
I am using Nuxt/Vue.
Can you help?
I am trying to extend the render of the htmlSerializer
so I can add additional dynamic params/props to the rendered HTML.
I am using Nuxt/Vue.
Can you help?
What additional info would you like? Please could you give us some examples?
I am using the <prismic-rich-text />
Vue component to render Ordered Lists (via Vue.js).\
$prismic.asText()
because I want the content writers to have control of text hightlighting, e.g. ‘bold,’ text labels, etc…PrismicRichText
component.ol
element, I am finding workarounds.import { RichText } from 'prismic-dom'
export default {
name: 'PrismicRichText',
functional: true,
props: {
field: {
type: Array,
required: true,
},
htmlSerializer: {
type: Function,
required: false,
},
wrapper: {
type: String,
required: false,
default: 'div',
}
},
render(h, {
props, data, children, parent
}) {
const { field, htmlSerializer, wrapper } = props
const innerHTML = RichText.asHtml(
field,
parent.$prismic.linkResolver,
htmlSerializer || parent.$prismic.htmlSerializer
)
return h(
wrapper,
{
...data,
domProps: {
innerHTML
},
},
)
}
}
Does that make sense?
There are some workarounds, but I’d prefer to be able to extend Prismic here so that I can add additional props. I think that would be cleaner and more maintainable. I also I can imagine later we’d need to add some additional props.
If I understand correctly, you’ll want to add a html serialiser function. You’re currently defaulting to the prismic one, which is what generates the HTML.
You can see more info in the docs here (I’ve just linked the JS version - the logic is the same).
So you could have something like this:
function htmlSerialiser (type, element, content, children) {
const serialiser = {
'group-o-list-item': `<ol>${children.join('')}</ol>`,
'o-list-item': `<li>${children.join('')}</li>`,
}
return serialiser[type] || null
}
Now you can add attributes to the <ol>
and <li>
elements as necessary.
I create this as a method, and use this.htmlSerialiser
, but yours is a functional component so it might not work that way and you’d have to pass it in as a prop.
Thank you for the response.
I was able to create another htmlSerializer, following your above pattern and the one outlined here: https://prismic.io/docs/vuejs/beyond-the-api/html-serializer
Unfortunately, because the htmlSerializer, and how it is used, is defined in the node module, as I copy and pasted above, I don’t have access to this function to add additional params, props, etc… Meaning, all I can deal with are the (type, element, content, children)
params. I would like to add another, dynamic one. Thus, the need to be able to extend this component.
Another way of saying this:
I would like to define this htmlSerializer
in one of two ways:
anotherHtmlSerializer(
type,
element,
content,
children,
additionalParams,
) {
if (type === Elements.list) {
return `<ul>${children.join('')}</ul>`;
}
if (type === Elements.oList) {
const startNum = params.startNum;
const olEl = `<ol start=${startNum}>${children.join('')}</ol>`;
return olEl;
}
// Return null to stick with the default behavior for everything else
return null;
},
And I would call it like so:
<prismic-rich-text
:field="list.list"
:htmlSerializer="
anotherHtmlSerializer((params = { startNum: list.start_number }))
"
/>
<prismic-rich-text
:field="list.list"
:startNumber="list.start_number"
/>
Unfortunately, the props are defined on the htmlSerializer and I would need to extend it somehow.
In both cases I am unable to add any additional, dynamic params.
I’d work like this. Create this file here in your components, and import this instead of using the default <prismic-rich-text />
element.
I’ve added in an additional params
prop, and created a small html serialiser from your <ol>
specification.
Note that you don’t have to use the Elements.oList, there’s nothing special about it - it just returns the string group-o-list-item
.
It is a bit spaghettified at the moment, you might get on better removing the functional
directive and rendering template tags.
import { RichText } from 'prismic-dom'
export default {
name: 'ExtendedRichText',
functional: true,
props: {
field: {
type: Array,
required: true,
},
htmlSerializer: {
type: Function,
required: false,
},
wrapper: {
type: String,
required: false,
default: 'div',
},
params: {
type: Object,
required: false,
default () {
return {}
},
},
},
render(h, {
props, data, children, parent
}) {
const { field, htmlSerializer, wrapper, params } = props
function defaultSerializer (type, element, content, children) {
if (type === 'group-o-list-item') {
const startNum = params.startNum
return `<ol start=${startNum}>${children.join('')}</ol>`
} else {
return null
}
}
const innerHTML = RichText.asHtml(
field,
parent.$prismic.linkResolver,
htmlSerializer || defaultSerializer
)
return h(
wrapper,
{
...data,
domProps: {
innerHTML
},
},
)
}
}
@tgalpin, you can extend the functionality of the HTML Serializer by making your HTML Serializer a closure. That is, make it a function that returns an HTML Serializer function. This will allow you to pass whatever you need to your HTML Serializer. In this case you can pass your starting number.
Then you could do something like this:
const anotherHtmlSerializer = (startingNumber) => {
return function(type, element, content, children) {
if (type === Elements.oList) {
return `<ol start=${startingNumber}>${children.join('')}</ol>`;
}
return null;
}
}
Does this make sense? Give this a try and let me know if you manage to get it working!
That was it!
Thank you Levi. I don’t know why I didn’t think of it.