How to use Helpers within script tag, (and load dynamically data from Collection)

Hello,

I’m struggling to do something that should be simple.
My setup is meteor 1.6 and Blaze.

I have a script tag in my template, and need to load data from a helper (that get some data from a Mongo Collection). The script will then manipulate the data and write the result in a div in the template.

Here a simplified version that just print out data.

<template name="abc">

<div></div>

<script>
       console.log(({{dataFromTheHelper}}));
</script>

</template>

This triggers an error

Uncaught SyntaxError: Unexpected token )

Because it seems that the data is not loaded. Here the result from the JS debugger.

console.log(());

The data are correctly loaded when used within the template, but not in the script tag.
I read many articles mentioning that Meteor does not handle this scenario properly, but I dont see how I could work around this.
My data are in the collection, I have to load them dynamically in a script in a template.

The scenario is similar to this “unresolved” post.

Am I the only one in the Meteor community who tries to do something like this? :smiley:

Thanks to let me know what is the “trick” to do this.
Or If I have to review the way I approach my issue.

Waiting for your feedback.
Cheers
Sam

If it was react, we have react helmet.

Yeah you should definitely rethink your approach.

Any logic for a template should be handled in the onCreated and onRendered methods of the template definition:

Template.abc.onCreated(function () { ... });
Template.abc.onRendered(function () { ... });
2 Likes

Thanks coagmano.
I should have read carefully this link :wink:

I put my logic in the onRendered, and it works well.

One more thing, I needed to get data from a Collection in the onRendered, and because it is not reactive by default. It does not work.

So, I did the following

Template.abc.onRendered(function () {

  Meteor.subscribe('mydata', () => {
    // Wait for the data to load using the callback
    Tracker.afterFlush(() => {
      var oneElement =  MyCollection.findOne(new Meteor.Collection.ObjectID("cf3e54dc7f4fe1c2252d48ea"));
      this.$('div').doSomething(oneElement);
    });
  });

});

This code work. I just wanted to be sure that it is the best way.
Do you confirm ?

And last thing.
I found a “dirty” hack that let me work with the script tag in my template.

If I wrap the script with a IF, then I get the data from the helper…

<template name="abc">

<div></div>
{{#if dataFromTheHelper}} <!-- fucking hack -->
<script>
       console.log(({{dataFromTheHelper}}));
</script>
{{/if}}

</template>

It is really dirty… but it solved my issue…
Anyway, now I will use the onRendered function from the template.
(I know how it works now :wink:)

It depends on your usecase - in the situation where you may already have the data, and don’t want to wait for the roundtrip on a subscription, this wont work well - similarly, in the case where you subscribe elsewhere (e.g., in flowrouter) this wouldn’t work.

I would typically just use an autorun block within the onRendered method:

Template.abc.onRendered(function () {
  //subscribe if necessary
  this.autorun(() => {
    var oneElement =  MyCollection.findOne(new Meteor.Collection.ObjectID("cf3e54dc7f4fe1c2252d48ea"));
    this.$('div').doSomething(oneElement);
  });
});

I changed Tracker.afterFlush by this.autorun, and it works fine.
(And I kept the subscription.)

Thanks a lot.