occasl
occasl

Reputation: 5454

Using Meteor to run queries and set checkbox field defaults

I have a few "user settings" that I want to be based on a query I do on start-up. For instance, all my setting fields are checkbox inputs and I'll set them to yes or no based on the preference they chose previously that we have stored in the database.

My query from the client looks as follows:

   Meteor.call('getNotificationPreferences', function(err, result) {
        console.log(result);
        Session.set('aNotificationPreference', result.a);
        Session.set('bNotificationPreference', result.b);
        Session.set('cNotificationPreference', result.c);
        Session.set('dNotificationPreference', result.d);
    });

This call simply pulls that information from MongoDB and sets the session variable correctly, but then I want to use that session variable to set the checkbox field "checked" attribute. I've tried to set this directly with jQuery and also reactively with Meteor. Sometimes this works and sometimes it doesn't.

The HTML looks something like this (using jquery mobile):

<template name="preferences">
    <div data-role="collapsible" data-collapsed="false" data-collapsed-icon="mail" data-expanded-icon="edit">
        <h2>Notifications</h2>
            <div class="ui-field-contain">
                <label for="aNotificationSwitch">A</label>
                <input type="checkbox" data-role="flipswitch" data-theme="b" name="aNotificationSwitch" id="aNotificationSwitch" data-mini="true" checked={{aNotification}}>
            </div>
            <div class="ui-field-contain">
                <label for="bNotificationSwitch">B</label>
                <input type="checkbox" data-role="flipswitch" data-theme="b" name="bNotificationSwitch" id="bNotificationSwitch" data-mini="true" checked="{{bNotification}}">
            </div>
            <div class="ui-field-contain">
                <label for="cNotificationSwitch">C</label>
                <input type="checkbox" data-role="flipswitch" data-theme="b" name="cNotificationSwitch" id="cNotificationSwitch" data-mini="true" checked="{{cNotification}}">
            </div>
            <div class="ui-field-contain">
                <label for="dNotificationSwitch">D</label>
                <input type="checkbox" data-role="flipswitch" data-theme="b" name="dNotificationSwitch" id="dNotificationSwitch" data-mini="true" checked="{{dNotification}}">
            </div>
    </div>
</template>

Then in my JavaScript, I have the following:

Template.preferences.aNotification = function() {
    // Setting directly doesn't work either
    //$('#aNotificationSwitch').prop('checked', Session.get("aNotificationPreference"));
    return Session.get("aNotificationPreference");
};

Can anyone explain why this wouldn't work consistently?

I've also tried doing this the Meteor way, by publishing the preferences as follows:

   Meteor.publish("user-preferences", function () {
    return Meteor.users.find({_id: this.userId},
        {fields: {'notification': 1}});
});

Upvotes: 1

Views: 353

Answers (1)

saimeunt
saimeunt

Reputation: 22696

The checked property of an HTML checkbox should not be set to either "true" or "false" as you're trying to do in your code, but respectively to "checked" and nothing.

<input type="checkbox" checked>

is the same as

<input type="checkbox" checked="checked">

These two examples will set the checkbox in the active (checked) state, although the first example is preferable because it's more concise.

An unchecked checkbox is achieved by not specifying the attribute at all :

<input type="checkbox">

So as far as Meteor is concerned, change your helper to :

Template.preferences.aNotification = function() {
    return Session.get("aNotificationPreference")?"checked":"";
};

And in the HTML, just do :

<input type="checkbox" {{aNotification}}>

From a design perspective, I wouldn't store the user settings in Session variables fetched from the server via a method call, it doesn't sound very meteorish.

Have you considered storing these settings as properties in the Meteor.user() object ? This would involve setting these properties via a method call, and then publishing the properties explicitly to the client.

Server publication :

Meteor.publish("userSettings",function(){
  if(!this.userId){
    this.ready();
    return;
  }
  return Meteor.users.find(this.userId,{
    fields:{
      "profile.settings":1
    }
  });
});

Client :

// this should be put in a iron:router RouteController waitOn !
Meteor.subscribe("userSettings");

Template.preferences.helpers({
  aNotification:function(){
    if(!Meteor.userId()){
      return "";
    }
    // this will fail if the publication is not yet ready
    // either guard accessing sub properties (this is bad)
    // or use iron:router to wait on the subscription (this is good)
    return Meteor.user().profile.settings.a?"checked":"";
  }
});

Upvotes: 2

Related Questions