[SOLVED] Template helper - get Mongo field value already dynamically loaded on the current page

I’m new to Meteor and Mongo and having trouble creating a javascript that can access a specific field in a collection for the _id that is already loaded on a page.

I’ve searched Mongo docs, Meteor docs and tutorials and StackOverflow and while some things seem hopeful they usually refer to getting the field of a known _id, where as in this case the _id is dynamically added to the page via a subscription. So I want something like “this.description” where “description” is the desired field to capture.

Page is already loaded and successfully collecting Mongo field information using Spacebars. So for example, for database “products”,

{{description}} 

is showing as

I'm an excellent product!

for the unique product and description on the page.

Now in the page helper, how can I do the equivalent of

var thisDescription = {{description}};
console.log(thisDescription);

where it is going to return the exact same field value to console.log?

Once I can correctly get the value I can make a real script, but for now I’ll jump for joy if I can just get console.log to print the correct value every time the template is accessed.

At first it seemed like this should work…

var getField =  Products.findOne({});
console.log(getField.description);

but it only got the description one time. When the template was accessed for a different product, the description from the original template render persisted.

Depending on how your products subscription is setup, Products.findOne({}); could always return the same Product. If the subscription isn’t limited to return the exact Product you’re expecting, the findOne call will just grab and return the first Product it finds. This could be the first Product inserted into Mongo for example, instead of the Product you want to work with.

If you’re able to share more of your template and helper code showing how you have things setup, we can help get this sorted out.

Also, how to you publish and subscribe to your collection products? Or are you still using the autopublish module?

Hugh has helped before. I love Hugh. Jan, app’s publish and subscribe is according to the Meteor tutorial and guide (autopublish is removed). Publish and Subscribe are correctly populating the template.

Here’s what’s in my “product” template’s js…

// client/templates/product.js 

Template.product.onCreated(function() {
  var self = this;
  self.autorun(function() {
    var productSlug = FlowRouter.getParam('productSlug');
    self.subscribe('singleProduct', productSlug);  

    // try to get something to pass to script
    FlowRouter.watchPathChange();
    var context = FlowRouter.current();
    var thisDescription = context.description;

    // this works
    console.log('onCreated' + thisDescription);
    return thisDescription;

   });

});

Template.product.helpers({

  product: function() {
    var productSlug = FlowRouter.getParam('productSlug');
    var product = Products.findOne({slug: productSlug}) || {};
    return product;
  },
});

So, the var thisPath works in console.log in the onCreated script. Now I want to pass back to the product.html template like so…

{{#with product}}

    ...bunch of html and spacebars including {{description}}, then... 
    {{#if Template.subscriptionsReady}}

    <script>
           how do I get the thisDescription var in here?
            It has to be in the script. Can't use "{{description}}". 
    </script>

    {{/if}}
{{/with}}

? Soooo close and still tinkering… I thought it would be easy but I stayed up all night.

So thisDescription is from FlowRouter?

    var context = FlowRouter.current();
    var thisDescription = context.description;

if you want that value in the template, I guess you need to helper for that

Template.product.helpers({

  product: function() {
    var productSlug = FlowRouter.getParam('productSlug');
    var product = Products.findOne({slug: productSlug}) || {};
    return product;
  },
  thisDescription: function() {
    var context = FlowRouter.current();
    return context.description;
  }
});

1 Like

So when I added “thisDescription” function, I was still unable to access a value for thisDescription from an onRendered script or javascript, it only gave me a spacebars helper {{thisDescription}}.

I also tried in the template’s html,

<script type="text/javascript">
   console.log(thisDescription);
   console.log(this.description);
</script>

…both return undefined.

I need a way to get the value in a script, so I can encode the value.

Can’t you encode the value in a helper? Or write a helper that encodes whatever input you give it and return the result?

It doesn’t feel natural to insert a script tag in your template.

Like this:

Template.product.helpers({
encodeString: function(string) {
const encodedString = whateveryouwanttodowith(string);
return encodedString;
}
});

And in your template:

{{ encodeString product.description }}

1 Like

Another solution would be to use dburles:collection-helpers and add a helper to the products collection that returns an encoded version of the description. Then you could:

{{ product.encodedDescription }}

Oh my gosh - that’s IT! That’s perfect. Thank you!!! :relaxed:

I’d like to learn more about syntax for creating more robust helpers. Typically when I tried to add helpers before, app crashed though the script would work if re-worked in a script tag in template html (terrible practice). Do you have any good references for learning more about helpers? If so I will check them out.

I tried to heart your reply about 100 times and ran into Meteor’s action limit. Hope it didn’t notify you to death!

You’re welcome Deborah.

Perhaps this article from The Meteor Chef could help you:
https://themeteorchef.com/snippets/using-global-template-helpers

There’s a lot of good stuff over there.

1 Like

Another resource would be Discover Meteor
https://www.discovermeteor.com/blog/a-guide-to-meteor-templates-data-contexts
https://www.discovermeteor.com/blog/spacebars-secrets-exploring-meteor-new-templating-engine

The Guide is great as well, but there’s not that much to read about basic helpers in it.

1 Like

Those will help a lot!! I just learned a data context reference adjustment solved a similar problem - so that will be excellent reading!