How to access a pre-rendered Mongo field value in Meteor using JavaScript

Greetings to all! Thank you for your assistance. The question has been revised based on the feedback received.

I'm a newbie when it comes to Mongo and Meteor.

In my "posts" collection, there is a field called "slug".

The "post" template is correctly populating with values of each post. The slug value always follows a format like "my-great-post".

My task is to retrieve the text value for the _id's slug, which will vary each time the template is accessed. I need to encode it, generate a string, and then display the string in the template.

Attempts Made:

  • Failed to return a value for "this.slug" or "this.data.slug" in either template helpers or onRendered, despite having the collection defined and accurately populating spacebars values in the template

  • When using "this", it outputs "[object Object]" to the console.log

  • The app crashes when trying to encode and deliver a string from the helper function. Perhaps, I do not fully grasp the syntax for helpers as per the documentation

(Per advice in the comments, I refrained from attempting to create scripts in the template HTML. Here is additional information requested by those providing assistance)

- Template HTML -

{{#with post}}

<div class="blog-article">
  <div class="blog-header">
    <div class="left">

      <!-- title -->
      <h1 class="post-title">{{title}}</h1>

      <div class="holder">
        <div class="post-tags">
          <!-- tags -->
           {{#each tags}}
              <span>{{this}}</span>
           {{/each}}
        </div>
      </div>

    </div>

  </div> 

  <div class="blog-post">
    <div class="blog-copy">

      <!-- date -->
      <div class="post-date">{{post_date}}</div>

      <!-- social -->  
      <div class="blog-social">
         <!-- 
               <a class="so-facebook" target="_blank" href="need to encode slug here"></a>
         -->       
       </div>

       <!-- ============== post ============== -->

       {{{content}}}

       <!-- ============ end post ============ -->

     </div>
  </div>
</div>

{{/with}}

- Template JS -

Template.post.onCreated(function() {
  var self = this;
  self.autorun(function() {
    var postSlug = FlowRouter.getParam('postSlug');
    self.subscribe('singlePost', postSlug);  
  });
});

Template.post.helpers({

  post: function() {
    var postSlug = FlowRouter.getParam('postSlug');
    var post = Posts.findOne({slug: postSlug}) || {};
    return post;
  } 

   // Unable to make these work within a helper function; they crash the app outside the helper
   // console.log(this.slug);   
   // console.log(this.data.slug);

});

Template.post.onRendered( function () {

   // These are ineffective 
   // console.log(this.slug);   
   // console.log(this.data.slug);

}); 

db.posts.findOne();

{
  "_id" : ObjectId("576c95708056bea3bc25a91f"),
  "title" : "How Meteor Raised the Bar For New Rapid-Development Technologies",
  "post_date" : "May 28, 2016",
  "image" : "meteor-raised-the-bar.png",
  "slug" : "how-meteor-raised-the-bar",
  "bitlink" : "ufw-29Z9h7s",
  "tags" : [
    "Tools",
    "Technologies"
           ],
  "excerpt" : "sizzling excerpt",
  "content" : "bunch of post content html"
}

If someone can resolve this using any method, I would be overjoyed and immensely grateful for the solution.

Answer №1

It seems like the issue lies within the parent template, rather than this specific one. In Meteor, JavaScript files are separated from HTML files, so avoid including a <script> tag in your HTML.

The first step is to load all your documents into the client. Once you have that down, then you can focus on loading only the necessary documents.

To achieve this, you'll need a collection and a publication. By default, collections are fully published automatically, unless you've disabled the autopublish feature.

Let's begin with the parent template. Here, I'll iterate through all posts in the collection and display them using the innerTemplate.

<template name=parent>
  <ul>
  {{#each post}}
    {{> innerTemplate}}
  {{/each}}
  </ul>
</template>

Next, let's take a look at how the inner template could be structured:

<template name=innerTemplate>
  <li>{{slug}}</li>
</template>

As a result, you'll have a simple list displaying each slug.

To connect everything together, create a JS file that: 1. Defines the collection on both the client and server 2. Passes the collection to the parent template

This JS file should be accessible by both the client and server.

posts = new Mongo.Collection('posts');

if(Meteor.isClient) {
  Template.parent.helpers({
    posts() {
      return Posts.find();
    }
  });
}

If you want to manipulate 'slug' in the JS file, you can do something like this:

if(Meteor.isClient) {
  Template.innerTemplate.helpers({
    upperCaseSlug() {
      return this.slug.toUpperCase();
    }
  });
}

Then, reference upperCaseSlug in your template, like so:

<template name=innerTemplate>
  <li>{{upperCaseSlug}}</li>
</template>

Answer №2

Let's delve into the world of Meteor:

Avoid encountering this kind of pattern at all costs:

<script type="text/javascript>
...some code
</script>

Meteor consolidates all your JavaScript files into one large file and automatically includes it in your application. There should be no need for you to manually declare scripts as shown above.

Furthermore, there is no necessity to retrieve the value of a data object by inspecting the DOM. The data context within each template provides your data accessible through the variable this.

Whether in a helper function or within a template event, referencing this guarantees that you are accessing the precise data being presented within that template instance.

Upon reviewing your template code, it becomes evident that your template lacks a data context - although you establish the data context within your {{#with post}} and its corresponding helper, it does not result in the creation of the required this one level below.

Hence, @Nathan's guidance was accurate, with the exception that he assumed iteration over a cursor rather than examining a single post.

Extract all HTML content enclosed by your {{#with post}} and {{/with}} tags and transfer it to a fresh template named postDetail. Subsequently, revise your outer template as follows:

<template name="post">
{{#with post}}
  {{> postDetail}}
{{/with}}
</template>

The postDetail template will now automatically inherit a data context equivalent to the post object, enabling your helpers to safely reference this.

Template.postDetail.helper({
  slugURI{
    return "/"+encodeURI(this.slug);
  }
});

Thereafter, within your postDetail template, you can access the encoded slug using:

<a class="so-facebook" target="_blank" href={{slugURI}}>

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

Tips for sending additional parameters to an MVC controller without including them in the URL when using the JavaScript window.open method

<a href="#" onclick="openAnchor('<%# DataBinder.Eval(Container.DataItem,"Url") %>', '<%# DataBinder.Eval(Container.DataItem,"infoToSend") %>')"> </a> openAnchor= function (Url, infoToSend) { window.open(Url, ...

Using JavaScript in Internet Explorer 11, you can open multiple tabs without the UrlReferrer being null

I have tried numerous solutions to open multiple tabs in IE 11, but none of them seem to work for me. In Chrome, everything works smoothly with a simple window.open(url) command. When I try to open tabs using an iterative JavaScript code snippet, only one ...

Having trouble installing Angular 4 with npm?

After installing Angular, I encountered an error when trying to use the command line "ng -v". Please refer to the attached jpeg file. My node version is 6.10.3. Does anyone have a solution? https://i.sstatic.net/ZQ69k.png ...

Using React Router to send selected component to parent element

The content of App.js includes the following; render() { return ( <div className="App"> <Navbar /> </div> ) } Meanwhile, in Navbar.js class Navbar extends React.Component { render() { ret ...

Tips for maintaining the state of my jQuery accordion menu on my website even after refreshing the page

I came across a nested JQuery accordion code that works perfectly, but there's a major issue. When I click on a menu or submenu in my sidebar (a link that redirects to a different URL), the site fails to remember which menu or submenu should be shown ...

Creating a bump chart using structured data: A step-by-step guide

The bump chart example provided by ECharts includes sections with randomly generated data, which can be confusing for those unfamiliar with JavaScript or TypeScript. What would the code appear like if it didn't rely on data generation? ...

simultaneous fading in and out transitions for two distinct elements

I'm a newcomer to Vue.js and the world of transitions. Currently, I'm working on designing a Vue component that will handle lazy loading data from a server. My goal is to display a loading gif when data is not yet available. Everything seems to ...

Adjust the margin-top of the navigation bar with animation upon clicking the button

I have implemented a Cookie bar that is fixed at the top of my website. When the Close icon is clicked, the bar fades away. Due to the positioning of the div, I am also pushing down my .nav element by 64px. Inquiry: Is it feasible for the margin-top on ...

Grunt is throwing an error message of "Cannot GET/", and unfortunately ModRewrite is not functioning properly

I've recently started using Grunt (just began last Friday). Whenever I run Grunt Serve, it displays a page with the message "cannot GET/" on it. I tried implementing the ModRewrite fix but the error persists. Any assistance would be highly appreciat ...

Using a loop variable within a callback function in JavaScript/TypeScript: Tips and tricks

I have a method in my TypeScript file that looks like this: getInitialBatches() { var i = 0; for (var dto of this.transferDTO.stockMovesDTOs) { i++; this.queryResourceService .getBatchIdUsingGET(this.batchParams) ...

Determine if an object is already present in a JSON array by comparing their respective IDs

I have a shopping cart stored in JSON format. [{"tuote":{"id":"2","name":"Rengas 2","count":16,"price":"120.00"}},{"tuote":{"id":"1","name":"Rengas 6","count":"4","price":"25.00"}},{"tuote":{"id":"4","name":"Rengas 4","count":"4","price":"85.00"}}] Form ...

Utilize PHP to process and incorporate webhook information

Looking for assistance with PHP to receive webhook data and execute php code. While my php script is functioning correctly, it seems that I am not capturing the webhook data properly. I have attempted to retrieve the [loc] data using various methods such a ...

Struggling to display the default value on a <select> element using the defaultValue prop in React

My objective is to create a dropdown menu that lists all the US state names. If there is a stateName in this.props (obtained from the redux store with values like NY, KY, or an empty string), I want the dropdown to display it by default. Otherwise, I want ...

Guide to leveraging clsx within nested components in React

I am currently using clsx within a React application and encountering an issue with how to utilize it when dealing with mappings and nested components. For instance: return ( <div> <button onClick={doSomething}>{isOpened ? <Component ...

Enhance your MongoDB document by concatenating another string to a string field using Spring Data

Is there a way to update a string field in a MongoDB document by concatenating another string value using Java and Spring Data MongoDB? For example: { “languages”: “python,java,c” } If we want to add "kotlin" to the existing values: { ...

Unable to append item to array in MongoDB collection document

Currently in the process of developing an API for my chat platform, I have created an endpoint specifically to store new messages in MongoDB. Each message is stored as an array within the database. Testing the functionality of this endpoint using Postman ...

Having difficulty generating a footer for a page that includes a Material-UI Drawer component

Looking to create a standard full-width footer at the bottom of my page, I need help with the implementation. Utilizing the "Permanent drawer" from Material-UI Drawer for reference here. If you're interested in experimenting with it, CodeSandbox link ...

Is it possible to create a Nuxt.js static website that incorporates a dynamic single-page application built with Vue.js

Currently researching Static Site Generators for a client project, I discovered Vue.js and Nuxt.js, which appear promising. Given the choice between Vue.js and React, I lean towards Vue at the moment. The client's website consists of 120 pages with s ...

Django's post-login redirect is stuck in a continuous loop

I am facing an issue with my Django 1.9 and MongoDB setup. I have a custom user model and a webpage for uploading files. The upload functionality is working fine, but now I need to make that page login protected. When I try to access https://localhost/upl ...

The website is up and running smoothly, except for encountering an XMLHttpRequest() error when trying to

I have developed a new website My website functions smoothly on most browsers and iPhone simulators, but encounters issues when accessed from a real iPhone. I have traced the problem to XMLHttpRequest(). The XML data retrieval seems to be causing trouble, ...