jonnyrichards
jonnyrichards

Reputation: 185

Is there something strange about the way Meteor loads jQuery?

I'm having some difficulties with standard jQuery functionality when I use Meteor. My main 'client/server' JS file looks like this:

if (Meteor.is_client) {
$(document).ready(function(){
$('#myDiv').append("foo");
console.log('bar');
});
}

When I load the app, 'bar' logs fine, but .append doesn't work. If I call the same .append in the console after page load, it works fine. (Similarly if I run the same code in a non-Meteor setting, it also works fine.)

The code I actually want to run looks like this:

$(document).ready(function(){
var myModel = new MyModel({"name": "foo"});
var myModelView = new MyModelView({model: myModel});
});
var MyModel = Backbone.Model.extend({
initialize: function() {  
}
});
var MyModelView = Backbone.View.extend({
el: $('#myEl'),
initialize: function(){
_.bindAll(this, 'render');
this.render();
},
render: function(){
$(this.el).append(this.model.get('name'));
console.log(this.model.get('name'))
}
});

The method that isn't working here is render, in the View. The console.log bit of the render method is fine, but the jQuery append doesn't work. Initially I wondered whether it was something about the way I was using Backbone that was the problem, but now I'm wondering if it's a Meteor/jQuery issue instead?

Upvotes: 5

Views: 5298

Answers (5)

COREST
COREST

Reputation: 1

Meteor Helper

Template.templateName.helpers({
    runJQueryPlugin: function() {
        $('#itemId').dropdown();
    }
}

Blaze

<template name="templateName">
    {{#if currentUser}}
        <div id="itemId">JQuery Dropdown Menu</div>
        {{runJqueryPlugin}}
    {{else}}
        <div>Login Button</div>
    {{/if}}
</template>

This works for me.

Upvotes: 0

oskare
oskare

Reputation: 1061

Both the:

$(document).ready

and the:

Template.templateName.rendered = function(){

solutions are depending on the templates being shown on startup and/or all their content is populated. If you for example use a

{{#if show}} 

for the actual content within a template, jQuery might not always bind. I ended up adding a

{{bindEvents}}

at the end of my template and then:

Template.templateName.bindEvents = function(){
$( "#accordion" ).accordion();
}

Feels hackish but this way my jQuery works properly no matter how the actual content is loaded in relation to the template or document themselves.

Upvotes: 0

AnalogDiode
AnalogDiode

Reputation: 101

The following worked for me:

if (Meteor.is_client) {
    Template.templateNameThatContainsMyDiv.rendered = function(){
        $('#myDiv').append("foo");
        console.log('bar');
    };
}

Upvotes: 10

matb33
matb33

Reputation: 2820

Perhaps try using Meteor.startup on the client-side:

if (Meteor.is_client) {
    Meteor.startup(function () {
        $(document).ready(function (){
            $('#myDiv').append("foo");
            console.log('bar');
        });
    });
}

From what I gather in the Meteor docs, the $(document).ready() call may even be superfluous when using Meteor.startup

Upvotes: 13

Tamara Wijsman
Tamara Wijsman

Reputation: 12348

$(document).ready kicks of when the initial static DOM has finished loading, if you are using any JS templating libraries then the initial static DOM is most likely empty at the time when $(document).ready is ran. So, you will have to subscribe with a callback to kick off your code when the template has done rendering. If that's not possible you'll have to use .on or .bind and listen for the insertion of the DOM node you are looking for...

Upvotes: 5

Related Questions