Issue with onRendered()

Hello @ll,

I have the following simple html code:

<head>
  <title>Mein Test</title>
</head>
<body>
<div class="container">
        <div class="row">
            <div class="col-lg-4 col-lg-offset-4">
                {{>dropdown}}
            </div>
        </div>
    </div>
</body>

<template name="dropdown">
    <select class="form-control drop">
        {{#each item}}
            <option>{{name}}</option>
        {{/each}}
    </select>
    <br>
    <h3>{{price}}</h3>
</template>

and the following Javascript code:

Item = new Mongo.Collection('item');

if (Meteor.isServer) {
    if (Item.find().count() === 0) {
        Item.insert({
            name: "first item",
            price: 10.40
        });

        Item.insert({
            name: "second item",
            price: 30.20
        });
    }
}

if (Meteor.isClient) {
    Template.dropdown.onRendered(function() {
        console.log(this.$(".drop").val());
    });
    Template.dropdown.helpers({
        'item': function() {
            return Item.find();
        }
    });
}

The console.log() inside the onRendered() returns only null value. But if I paste the console.log() in the Meteor.setTimeout() function it work well. How can I solve this issue the Meteor like way.

PS: Sorry for my bad english.

What value you expect to be returned?
When onRendered is fired, there are no <option> s in that select yet.
Or I would not expect them to be inserted there yet.

If the render of the page is finished, than there is the “first value” selected in the dropdown menü. With the console.log() I want to print out the value, which is selected in the dropdown menü after loading the page.

I dont know why would somebody want to do that, when can simply use JS in template to get inital value from collection.

But with my limited knowledge, if I really had to code it from html, I would use _uihook on that select element and define insertElement function which would fire that console.log when executed first time.

The only thing I had to do, is to read the selected value from the dropdown menu on reload of the page and print it out in the browser console. It is only a test.

The reason you see “null” might be that you don’t wait for the data to be published from the server before displaying your list. So the list is initially empty.
To check that, put a console.log in your item helper to see what it returns.

But till now I thought the template is only rendered if all data is inserted into the template.

Here is what happens:

  1. Your local database is empty
  2. The “dropdown” template is rendered, but the list is empty because of point 1
  3. The onRendered callback fires. In there, .val() returns null because the list is empty.
  4. Data arrives from the server
  5. Your template is locally updated to show the new data (no re-render)

Ok thank you and how can I solve this problem?

You could use iron router and wait for the data to be ready. You will have to remove autopublish package.

Or in the onRendered() create a autorun instead:

Template.dropdown.onRendered(function() {
  this.autorun(function () {
    var count = Item.find().count();
    if (count > 0) {
       console.log($(".drop").val());
    }
  });
});

Ok super. That’s is. I will use the autorun function. Thank you very much.

If you are starting with Meteor, don’t use Iron Router, it is quite a complex package.

The count() trick will solve your immediate problem, indeed. But the complete Meteor way is:

  • remove the autopublish package
  • create a publish function to publish your data
  • use the subscribe function to load your data

You will end up with the following code:

Template.dropdown.onRendered(function() {
  var self = this;
  self.subscribe('myData');
  self.autorun(function () {
    if (self.subscriptionsReady()) {
       console.log(self.$(".drop").val());
    }
  });
});
3 Likes

Thank you Steve for the explanation.

No need for autoruns here. .subscribe has an onReady callback, which is where you should put your console.log

Hallo avalanche1,

can you make an example?

coffee

Template.name.onCreated
  this.subscribe('myData', -> console.log $(".drop").val())