Database value doesn't update properly / acting weird


#1

Hi everyone,

This post is from StackOverflow, but since the Meteor community doesn’t seem very active there, I repost it here, hoping for answers.

I’ trying to update a value of my user collection, based on the value of a select.
I have no clue what is actually happening.

Here is my relevant code:

// client/settings.html
<template name="settings">
    
    <select id="weightUnit">
        <option value="kg" selected="{{selectedWeightUnit 'kg'}}">Kg</option>
        <option value="lbs" selected="{{selectedWeightUnit 'lbs'}}" >Lbs</option>
    </select>
    
</template>

// client/settings.js
Template.settings.helpers({
    selectedWeightUnit: function(val) {
        var weightUnit = Meteor.user().weightUnit;
        console.log(weightUnit);
        return weightUnit == val;
    }
});

Template.settings.events({
    "change #weightUnit": function(e) {
        e.preventDefault();
        var unit = $("#weightUnit").val();

        console.log("before: ", Meteor.user().weightUnit);
        Meteor.call("updateWeightUnit", unit);
        console.log("after: ", Meteor.user().weightUnit);
    }
});

Template.settings.onRendered(function () {
    $('select').material_select(); // initialize materializecss' select
});

// server/methods.js
Meteor.methods({
    updateWeightUnit: function(unit) {
        if (this.userId) {
            Meteor.users.update( { _id: this.userId }, { $set: { weightUnit: unit }} );
        }
    }
});

What’s weird is what’s logged in the console:
Screen of console
(sorry I can’t post images directly since I’m a new user)

What I can see and understand:

  • At the beginning, weightUnit is undefined. (twice since there is 2 options calling selectedWeightUnit)
  • When I change the value:
    • before I call the update the value is still undefined (that’s ok)
    • after I call the update, the value is lbs (the one I chose)

What I can see and WTF:

  • Why is the page reloading 4 times (8 values, 2 per reload - or whatever it is) ?
  • On the first 2 reloads the values stays lbs (which is ok) but then changes to undefined (???!)

Obviously, if I reload (F5) the page, Meteor.user().weighUnit is undefined


To be honest , this doesn’t make any sense to me.

Could this come from a package I use?

My packages are:

meteor-platform
email
fastclick
meteorhacks:fast-render

iron:router
zimme:active-route

accounts-base
accounts-password
accounts-facebook
accounts-twitter
accounts-google
joshowens:accounts-entry

fourseven:scss
fortawesome:fontawesome
poetic:materialize-scss

aldeed:template-extension
dburles:collection-helpers
meteorhacks:kadira
tap:i18n
u2622:persistent-session

#2

I suggest something like creating non-reactive variables in onRendered and using these to initialize selected initial state.
Current way every time value in database update, these states are recalculated.
So you change it by hand in browser, method is called, database updated, minimongo updated and than template helpers recalculated with new values -> changed DOM.
I would expect.


#3

Ok so here is what’s happening:

  • You are right about the first 2 undefined and the before and after log.
  • the reason that there are 4 values is because the method uses what is called latency compensation.
  • the LC simulates the method on the client which is why it is defined in the first 2 results (for each of the template helpers)
  • then the server performs the method and does the update
  • Once the server finishes the method, the client undoes the simulation and replaces the values with ones from the server
  • However you don’t have a publication for the Meteor.user().weightUnit field
  • So when the template helpers run for a second time they are undefined again.
  • The only fields published with Meteor.user() by default are username, emails, and profile