Handlebars does not support loading data into variables using Express

My NodeJS/Express application utilizes Handlebars for templates, and everything works smoothly except when attempting to display data retrieved from an Express API.

The data is successfully fetched and can be viewed in the Chrome debugger.

In the problematic template, I am constructing the HTML within a script tag and then compiling it using JS.

Below is the sample template HTML code:

<script id="search-result-template" type="text/x-handlebars">
  <div>String</div>
  {{#each patient}}
    <div>
    {{cp_first_name}}
    </div>
    {{!-- {{> searchresultpartial}} --}}
  {{/each}}
</script>

The overall page structure is more complex, but I've presented this simplified version for debugging purposes.

The following code fragment compiles the template:

let patientSearchButton = document.getElementById('patient-search-execute');
patientSearchButton.addEventListener("click", async function (e) {
    e.preventDefault();
    let patientSearchFirstname = document.getElementById('patient-search-firstname')
    let cp_first_name = patientSearchFirstname.value;
    let url = baseURL + 'patientsearchquery/' + cp_first_name;
    const response = await fetch(url, {
        method: 'get',
        headers: {
            'Accept': 'application/json, text/plain, */*',
            'Content-Type': 'application/json'
        }
    });
    var data = response.json();
    let patientList = await data;
    patient = patientList;

    if (response.status === 200) {
         let patientSearchResultTemplate = document.querySelector("#search-result-template").innerHTML;
        let patientSearchResultTemplateFunction = Handlebars.compile(patientSearchResultTemplate);
        let patientSearchResultTemplateObject = patientSearchResultTemplateFunction(patient);
        let contentPartial = document.getElementById('patient-search-table');
        contentPartial.innerHTML = patientSearchResultTemplateObject;

        if (Handlebars.Utils.isArray(patient)) {
            console.log("Array");
        } else {
            console.log("Not");
        }
        console.log(patient);
    } else {
        alert("HTTP-Error: " + response.status);
    }
});

I'm able to view the API data and confirm that Handlebars recognizes it as an Array.

However, the issue arises when iterating through the #each helper in the template.

I've attempted various approaches like using ../ to adjust the context and trying different methods to pass the data into the template.

Initially, I thought the "this" context might have been disrupted due to being within an event handler tied to a button click. I tested moving the code outside the event handler, and despite the correct display of "this" context in Chrome, the behavior remained unchanged.

When inspected in Chrome, the array data looks like this: https://i.stack.imgur.com/SFzi8.png

Upon pausing on a breakpoint in Chrome, I observed that the patient data is present when passed to the template.

I understand there's likely a simple solution, but after exhausting my options, I find myself at a loss.

This issue has occurred with two distinct templates, albeit similar. Despite experimenting with multiple variations, the problem persists.

Any insights or suggestions would be greatly appreciated.

Additionally, I revised the code to pass the property explicitly, as seen in Chrome here: https://i.stack.imgur.com/k3gBX.png

Despite successfully displaying the property in Chrome, Handlebars still does not render it properly.

While this.patients showcases the data in the console, the variable fails to render in Handlebars. What could be preventing its rendering?

Answer №1

The {{#each visitor}} in your document expects the data passed to have a property called visitor, which should be iterable like an Array.

However, it seems that you are directly passing an Array to the template function without the visitor property, causing the #each loop to not run.

To fix this issue, consider passing an Object to the template function and assigning an object key, visitor, with the value being your Array of visitors.

You can do this by changing:

let guestSearchResultTemplateObject = guestSearchResultTemplateFunction(visitor);

to:

let guestSearchResultTemplateObject = guestSearchResultTemplateFunction({ visitor: visitor });

Alternatively, you can use the shorthand method:

let guestSearchResultTemplateObject = guestSearchResultTemplateFunction({ visitor });

Keep in mind: Since visitor is an Array of Visitor Objects, consider renaming it to be plural for clarity if working in a team setting.

Answer №2

The main issue stemmed from the data being recognized as a Handlebars Sequelizer Object, preventing access to the prototype following a security update in Handlebars 4.6.0.

Instead of resorting to the commonly recommended solution of "allowInsecurePrototypeAccess," which appeared questionable to me, I opted to create a duplicate of the data using JSON.stringify() and JSON.parse(). This allowed Handlebars to successfully retrieve and utilize the information.

In the end, it turned out to be a contextual error, albeit not the one I initially anticipated.

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

Is it possible for a MySQL loop to only delete the first entry?

My MySQL looping is not working properly when I click the second button to get their id and continue with the rest of the process. Why is this happening? $(document).ready(function() { $("#deleteSchedule").click(function (e) { e.preventDefault(); ...

Node.js front end test automation system with advanced capabilities

Presently, I am actively engaged in developing a node.js + express application. My main goal is to establish a robust testing framework for this project. Recently, I stumbled upon an enlightening article that outlines how to create a basic application us ...

Ways to link my frontend to a NodeJS backend that is publicly deployed rather than on localhost

When my NodeJS server is running on localhost PORT, I can successfully connect them both by using the following code: const PORT = 9000; const app = express() app.listen(PORT, () => console.log(`Server is up and running on PORT ${PORT}`)) app.use(bodyPa ...

Error: Module 'node-rdkafka' not found

After successfully installing node-rdkafka on my MacBook Pro using the "npm install node-rdkafka" command, I encountered an issue while attempting to build the following node.js code in Eclipse. Within my Eclipse Node.JS application, var Kafka = require( ...

Using a forward slash in the path for the href attribute in a CSS link within an ejs file

Image 1: Configuring express.static for the public folder Image 2: Adding href="/app.css" in post.ejs file Image 3: Final result While experimenting with using /app.css and app.css in the post.ejs file, I noticed that the outcome was consistent with th ...

The second parameter of the Ajax request is not defined

Having an issue with my Ajax request in Vue.js where the second parameter is logging as undefined in the console. I've been trying to fix this problem but haven't found a solution yet. This is the code snippet for $.ajax(): //$.ajax() to add ag ...

The issue of execution order in JavaScript Recursion with promises

In the process of developing a method for creating markup to be used in a web app's off-canvas navigation. One of the challenges I am facing is making an asynchronous callback to another service that provides children nodes for the parent menu node (r ...

Implement session functionality in express following its initialization

As I delve into learning nodejs, I made a mistake by forgetting to include the flag for session support. $ express -s somefolder I am now wondering if I can execute the above command without erasing any of the existing additions or changes, or is there a ...

Increasing Nested Values in MongoDB Using NodeJS

Looking at this JSON structure: JSON = { "change_number": "CRQ91320s23", "change_description": "Nexusg work", "date": "2/10/2020", "changeowner" : "Jeff ...

Using TypeScript to define callback functions within the Cordova.exec method

I'm encountering an issue with the TypeScript definition for Cordova. The codrova.d.ts file doesn't allow for any function arguments in the success-callback and error-callback. To better illustrate my problem, here's a small example: Here ...

What is the reason behind allowing JavaScript to perform mathematical operations with a string type number?

let firstNum = 10; let secondNum = "10"; console.log(firstNum * secondNum); // Result: 100 console.log(secondNum * secondNum); // Result: 100 ...

The EJS templating system

I am currently working on a node.js project and I have an ejs template file that utilizes templates for the header and footer. The structure of template.ejs is as follows: <%- include(header) %> main content <%- include(footer) %> <script ...

Transform the React.js class poll component into a React Hooks poll component

I have created a React component "class" based poll, but I am looking to convert it into a React hook form. Can someone please help me with this? I'm having trouble understanding how to achieve this. import React, { Component } from "react"; ...

Strategies for safeguarding data in Node.js in the event of a crash

In my express app, users have the ability to create subdomains which act as proxies for sites dynamically. The challenge lies in potentially losing data if the app encounters errors, crashes, or restarts. This would result in all the unique proxies create ...

tips for generating a random number for direct display

Can anyone help me figure out how to automatically display the total of numbers from this script on my blog post without having to click anything? Additionally, I need it to update if the browser is refreshed. ` http://jsfiddle.net/BenedictLewis/xmPgR/ ...

Guide on incorporating pinching gestures for zooming in and out using JavaScript

I have been working on implementing pinch zoom in and out functionality in JavaScript. I have made progress by figuring out how to detect these gestures using touch events. var dist1=0; function start(ev) { if (ev.targetTouches.length == 2) {//checkin ...

Attempting to transfer a property from one page to another using the Link component in NextJS

Currently, I have a page containing six Link elements that are meant to redirect to the same destination but with different props based on which link is clicked. To pass props, this is how I've implemented it: <Link href={{ pathname: '/pro ...

Issue with setting a cookie on a separate domain using Express and React

My backend is hosted on a server, such as backend.vercel.app, and my frontend is on another server, like frontend.vercel.app. When a user makes a request to the /login route, I set the cookie using the following code: const setCookie = (req, res, token) = ...

Deployment of the API and frontend on separate subdomains and domains respectively within the Google Cloud Platform

My journey began by setting up a Google App Engine where I deployed both the API and the frontend on my custom domain, which I referred to as mysite.ms. The API was written in nodejs with Express, while the frontend was a React application. To achieve this ...

What is the best approach to removing a component by utilizing the children prop in React?

I am currently working on a specific scenario: In my project, I have a component called Foo with a property named bar If the bar property is set to true, then I need to display the Bar component that is nested inside the Foo component If the bar prop ...