Meteor entering route on method call

Can someone explain to me why, when I have the collection code inside the router, that route is called when the method is called?

Consider the following code :

home.html

<template name="home">
    {{ duplicate }}
    <form>
        <input type="text" name="test" value="somevalue">
        <input type="submit" value="Submit">
    </form>
</template>

      

script.js

Template.home.events({
    'submit form': function (e) {
        e.preventDefault();
        console.log('Enter Meteor call');
        Meteor.call('createDoc', { 'test': e.target.test.value });
    }
});

      

route.js

Router.onBeforeAction(function () {
    console.log('Enter onBeforeAction');
    $('#loading').show();
    this.next();
});

Router.route('/', function () {
    console.log('Enter action');
    var foo = collection.findOne({ test: 'somevalue' }) ? 'true' : 'false';
    this.render('home', {
        data: {
            'duplicate' : foo
        }
    });

    Template.home.rendered = function () {
        console.log('Enter rendered');
        $('#loading').hide();
    };
});

      

methods.js

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

Meteor.methods({
    createDoc: function (data) {
        console.log('Enter createDoc');
        collection.insert(data);
    }
});

      

The problem is that if I hit the submit button on the form, then after the method is called, the router gets activated even if it e.preventDefault()

submits. The console log shows this behavior:

"Enter Meteor call" script.js:4:3
"Enter createDoc" methods.js:5:3
"Enter onBeforeAction" routes.js:2:2
"Enter action" routes.js:8:2
"Enter onBeforeAction" routes.js:2:2
"Enter action" routes.js:8:2

      

Also, you can see that the router gets called twice and it never logs in Template.home.rendered

. This causes the loading div to appear and never leaves. I can confirm that the data entered is correct.

If I remove collection.findOne()

in routes.js this behavior disappears and everything works as expected.

Questions

  • Why is the route only called when I have it collection.findOne()

    inside the route?

  • Why collection.findOne({ test: 'somevalue' })

    doesn't it ever return anything inside the route? (I know how to get around this using variables and session helpers in script.js, but I want to know exactly why)

This is causing a lot of unexpected behavior in my application. Thank you so much in advance.

+3


source to share


2 answers


As others have said, the problem you are experiencing is that Meteor will react to rerunning code that is running in a reactive context if and only if that code makes a call to a reactive data source.

In your case, the call findOne

is a call to a reactive data source, and the context in Router.route('/', function () { // context });

is a reactive context.

There are two important tools that allow you to control this behavior: one is good design. Be aware of reactivity and try to code around it. Another checks Tracker.active and uses Tracker.nonreactive to avoid reactivity in the context of reactive data.



This should answer your first question. Why findOne

does your query never find anything: have you published data from server to client? Check Publish-Subscribe . You basically need:

// on the server
Meteor.publish('myPublication', function(author) {
     return collection.find();
});
// on the client
Meteor.subscribe('myPublication');

      

+2


source


The call to the .findOne () collection inside the route listens for any new changes to the database, every time the text is saved to the database, the query is executed.

Possible solution: Router.js

Router.onBeforeAction(function () {
  console.log('Enter onBeforeAction');
  $('#loading').show();
  this.next();
});



Router.route('/', {
  template: 'home',
  waitOn: function() {
    return Meteor.subscribe('collection');
  },
  data: function() {
    var foo = collection.findOne({ test: 'somevalue' }) ? 'true' : 'false';
    return {
        'duplicate': foo
    };
  },
  action: function() {
    this.render();
  }
});

      



And publish the file to the server /publish.js

Meteor.publish('collection', function () {
  return collection.find();
});

      

I hope this helps you solve your problem. Best.

0


source







All Articles