Retrieve a Vue Component by utilizing a personalized rendering method for a Contentful embedded entry

Currently experimenting with Contentful, encountering some issues with the Rich text content field.

To customize the rendering of this block and incorporate assets and linked references in Rich text content, I am utilizing the modules '@contentful/rich-text-types' and @contentful/rich-text-html-renderer.

Upon calling getEntries in the nuxt asyncData function, the description data becomes accessible in my page component. I am using the documentToHtmlString function along with certain options.

Everything is functioning as expected, but I intend to employ a pre-existing component (Post.vue) instead of returning the template in ES6 Template Strings.

Although aware that this is achievable, navigating the JS world is still relatively new to me.

I attempted to require components/post/Post.vue, but figuring out the implementation remains challenging.

import { BLOCKS } from '@contentful/rich-text-types';
import { documentToHtmlString } from "@contentful/rich-text-html-renderer"

The Vue component template where the rich text field is displayed

<section class="container">
  <div class="columns">
    <div class="column">
     <div v-html="formatContent(description)" /> 
    </div>
  </div>
</section>

The formatContent method is invoked to make use of documentToHtmlString as shown below (it functions properly):

methods: {
  formatContent(content) {
    return documentToHtmlString(content, options)
  }
}

Adapting documentToHtmlString with options as outlined in the documentation:

const embeddedEntryRender = (node) => {
  const { data: { target: entry} } = node

  const fields = entry.fields
  const sys = entry.sys
  // At this point
  // const postComponent = require('~/components/post/Post')

  return `
    <div class="column is-4">
      <div class="card">

        <div class="card-content">
          <div class="media">
            <div class="media-content">
              <h3 class="title is-4">${fields.title}</h3>
              <div class="subtitle is-6">${fields.description}</div>
            </div>
          </div>

          <div class="content">
          </div>

        </div>
      </div>
    </div> `
}

const options = {
  renderNode: {
    [BLOCKS.EMBEDDED_ENTRY]: (node) => embeddedEntryRender(node),
    // [BLOCKS.EMBEDDED_ASSET]: (node) => `<custom-component>${customComponentRenderer(node)}</custom-component>`
  }
}

No errors have been identified

--

Many thanks

Answer №1

Yes, it is possible to incorporate a custom Vue component using a different npm library to solve this issue.

npm install contentful-rich-text-vue-renderer

In your template:

<rich-text-renderer :document="document" :nodeRenderers="renderNode" />

The 'document' variable contains data from Contentful, which you refer to as 'description'. The 'renderNode' function is described below.

In your script section:

data () {
      return {
        renderNode: [INLINES.ASSET_HYPERLINK]: (node, key, h) => {
            return h('my-vue-component', { key: hey, props: { myProp: 'blah blah' }},'what I want inside the <my-vue-component> tag'`)
      } 
    }

This process can be confusing initially. Begin by importing the richTextRenderer component from the npm library and ensure it is declared in the components section of your Vue component, or globally.

Then, pass the contentful rich text field into its 'document' prop.

If you require custom rendering, provide a function in the nodeRenders prop (which needs to be declared in the data section).

In the provided example, any asset hyperlink type will be replaced with a component containing the desired content.

I only achieved success when declaring 'my-vue-component' globally in the main.js file.

import MyVueComponent from 'wherever/it/is';
Vue.component('my-vue-component', MyVueComponent);

Further configurations are available, but it's recommended to consult the npm library documentation for guidance. Note that the documentation may not be comprehensive, as I personally had to refer to their GitHub code to understand how to pass props effectively.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Choosing items from a list based on the choices made in another list

How can I make the second select bar dependent on the selection made in the first one? For example, if I select publisher with id=1, then only show templates that have publisher id=1. <v-flex> @can('publish') @if (sizeof($publ ...

When dynamically loaded HTML is involved, Javascript ajax calls often fail to execute properly

Currently, I am in the process of creating a JavaScript script that can facilitate clicking through <a href> links by only replacing the inner HTML instead of reloading the entire page. The interesting thing is, it seems to be functioning properly, e ...

Adjusting the background element of a fullpage.js layout during resizing and customization

Is there a way to make the background image responsive on a fullpage.js page, specifically for mobile and tablet devices? How can I ensure that a specific part of the image stays at the center of the page when resizing? For instance, in the provided imag ...

JavaScript source control tool

Is there a Java-based version of GitHub? I am interested in developing a dynamic application using HTML5 and Javascript, and had the thought of integrating Git to monitor data changes. Therefore, I am curious if there exists a JavaScript adaptation of a G ...

Access denial encountered when attempting to submit upload in IE8 using JavaScript

When running the submit function on IE8, I am receiving an "access is denied" error (it works fine on Chrome and Firefox for IE versions above 8): var iframe = this._createIframe(id); var form = this._createForm(iframe, params); ... ... ...

Prevent floating labels from reverting to their initial position

Issue with Form Labels I am currently in the process of creating a login form that utilizes labels as placeholders. The reason for this choice is because the labels will need to be translated and our JavaScript cannot target the placeholder text or our de ...

Implementing dynamic input elements in React components and managing state changes

I am currently working on a React component that includes simple input fields to track state for an AJAX call. There is also a button that, when clicked, generates a new set of input fields identical to the original ones. As a React novice, I initially at ...

Having trouble launching the freshly developed Angular app

I'm encountering an issue with my newly created app - I can't seem to launch it. Error: The loader “C:/C#/Angular/my-app/src/app/app.component.css” is not providing a string as expected. I've attempted reinstallation of Angular and Nod ...

Changing the class when a checkbox is selected using JQuery

I’m working on a bootstrap switcher and I want to change the panel color from grey to green when the checkbox (switch) is checked. I had it working before, but after updating the switcher, it no longer functions properly. Here is the main code for the s ...

Is it possible to merge upload file and text input code using AJAX?

For my form submissions using jQuery and Ajax, I'm trying to figure out how to send both data and files together. Currently, I have the following code: $("#save-sm").bind("click", function(event) { var url = "sm.input.php"; var v_name_sm = $(&ap ...

ReactJS sidebar navigation functionality

I have a fixed sidebar with icons for navigating to different pages. When an icon is clicked, a secondary menu slides out. However, the issue is that when another icon is selected, the menu slides back in instead of switching or staying out. Additionally, ...

Switch ng-model in Angular to something different

I am looking to transform my own tag into a template <div><input .../><strong>text</strong></div> My goal is to have the same values in both inputs. Check out the plunker here If I change the scope from scope: {value:' ...

What is the best way to incorporate an additional feature into vue.js?

Is it possible to add multiple get posts in Vue.js? I have successfully implemented a single post function, but I'm unsure how to incorporate multiple post functions. Here is my current code snippet: <script> new Vue({ el: '#app' ...

Transform a 3D text rotation JavaScript file into an Angular component tailored TypeScript file

I have a javascript file that rotates text in 3D format, and I need help converting it into an Angular component specific TypeScript file. You can find the codepen for the original JavaScript code here. Below are my Angular files: index.html <!doctyp ...

What could be causing my v-data-table to not populate with vuex data?

I am facing an issue with a component that contains a Vuetify datatable. The datatable is connected to my Vuex store, and when the component loads, it should populate the table with data. Although I can see the data being fetched and stored correctly, the ...

Utilizing the Mouse Hover feature to target various <div id> elements within a single Vue.js function

I have created two div IDs in an HTML file where I have specified the mouseover property. <div id="app"> <img class="img-responsive img-full" v-bind:src="imgData" @mouseover="imgData = imgData_1"> </div> <div id="app1"> <img cl ...

What could be the reason for JavaScript delaying the execution of DOM statements until a variable is true?

Today I've been tackling numerous bugs, but there's one particularly tricky bug that has me stumped. The snippet of code below pertains to a basic logon page. Currently, the only valid username is 'admin' and the corresponding password ...

What is the correct location for the webpack.config.js file within a React project?

I recently inherited a React project that I need to continue working on, but I have never used React before. I've been advised to use a web worker in the project and have found a tool that seems suitable for my needs: Worker Loader The suggested meth ...

Combining Two DIVS Side by Side

Hey there, I am working on a timeline using two divs within a table cell. My goal is to have these divs overlap instead of appearing one below the other. The position attribute for all the DIVs inside the cell must remain unchanged due to the drag/drop fu ...

The Arrival of Link: A Countdown Timer

I'm attempting to create a countdown timer that reveals a link after 20 minutes. Currently, this is my progress... <script type="text/javascript"> window.onload = function() { countDown('my_div1', '<a href="cdtl.html" ...