Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Isomorphic Apps with Meteor: Working With the Session Object

DZone's Guide to

Isomorphic Apps with Meteor: Working With the Session Object

· Java Zone
Free Resource

The single app analytics solutions to take your web and mobile apps to the next level.  Try today!  Brought to you in partnership with CA Technologies

This article, excerpted from Meteor in Action gives you a simple example on how to use Meteor's reactivity with the Session object and a dropdown list.

Traditionally accessing a web site via HTTP is stateless. A user requests one document after another. Because there is often the need to maintain a certain state between requests, for example keep a user logged in, the most essential way to store volatile data in a web application is the session. Meteor’s concept of a session is different from languages such as PHP, where a dedicated session object exists on the server or in a cookie. Meteor does not use HTTP cookies but the browser’s localStorage instead, for example for storing session tokens to keep a user logged in.

A dedicated Session object that is only available on the client and lives in memory only is useful for keeping track of current user contexts and actions.

The Session object

The Session object holds key-value pairs, which can only be used on the client. Technically, it is a reactive dictionary that provides a get() and a set() method. Until a Session key is associated via set() it remains undefined. This can be avoided by setting a default value using setDefault() which works exactly as set(), but only if the value is currently undefined. As a frequent operation is to check for a session value, the Session object provides an equals() function. It is not necessary to declare a new Session variable using the var syntax, it becomes available as soon as a set() or setDefault() command is used.

This is the required syntax:

Session.setDefault("key", "default value");  // #1
Session.get("key");                          // #2
Session.set("key","new value");              // #3 
Session.equals("key","expression");          // #4
  1. setDefault() only sets a value for key if the key is undefined
  2. returns current value (in this case the default value)
  3. assigns a new value to key
  4. translates to Session.get("key") === " expression" but is more efficient as it does not need to iterate through all keys within Session

Good to know Although a Session variable is typically used with strings, it can also hold arrays or objects.

Let’s see how we can apply the Session object to an application. In the corresponding book chapter we are building a housesitting app so we take that as an example. Consider Session to be the app’s short-term memory for keeping track of a currently selected house.

Using Session to store selected dropdown values

For the selectHouse template all we need to select a house from the database is a dropdown list. The idea is to retrieve all documents from the database and show all available names. Once a name is selected, it is going to define the data context for all other templates and a single house is displayed. We will be using the code shown below.

<template name="selectHouse">
    <select id="selectHouse">
        <option value="" {{isSelected}}></option>
        {{#each housesNameId}}
            <option value="{{_id}}" {{isSelected}}>{{name}}</option>
        {{/each}}
    </select>
</template>

We will now use a Session variable called selectedHouse to store the dropdown selection. Since the select box should reflect the actual selection, it needs to add a selected attribute to the currently selected option. In order to do so, we define a second helper named isSelected that returns either an empty string or selected, if the value of _id equals that of our Session variable.

As the last step we need to set the value for the Session variable based on the user’s selection. Because it involves an action coming from the user this requires an event map.

Whenever the value for the DOM element with the ID selectHouse changes, the event handler will set the selectedHouse variable to the value from the selected option element. Note that we need to pass the event as an argument to the JavaScript function that sets the Session value in order to access its value:

Template.selectHouse.helpers({
    housesNameId: function () {             // #1
        return HousesCollection.find({}, {});
    },
    isSelected: function () {               // #2
        return Session.equals('selectedHouse', this._id) ? 'selected' : '';
    }
});
Template.selectHouse.events = {
    'change #selectHouse': function (evt) { // #3
        Session.set("selectedHouse", evt.currentTarget.value);
    }
};
  1. returns all documents from the collection
  2. returns selected if the _id for the currently processed house equals that stored inside the Session variable
  3. remember to pass the event as an argument so the function can assign the selection value to the Session variable

You can test that everything works correctly by opening the JavaScript console inside a browser and selecting a value from the dropdown list. You can get and set values for the variable directly inside your console as well. If you change the value to a valid _id you can see that the dropdown list instantly updates itself due to the isSelected helper as you can see in the figure.

Creating a reactive context using Tracker.autorun

When working with JavaScript code you will often need to check for the value of a variable to better understand why an application behaves the way it does. Using console.log() to keep track of variable contents is one of the most important tools for debugging. Since we are dealing with reactive data sources we can also take advantage of computations to monitor the actual values of those sources. Simply put, we are going to print the contents of the reactive Session variable anytime it changes. In order to do so we will create a reactive context for the execution of console.log().

Besides Templates and Blaze there is a third way to establish a context that enables reactive computations: Tracker.autorun(). Any function running inside such a block is automatically rerun whenever its dependencies (i.e., the reactive data sources used within it) change. Meteor automatically detects which data sources are used and sets up the necessary dependencies.

We can keep track of the value for Session.get("selectedHouse") by putting it inside an autorun. We place this code at the very beginning of the client.js file, outside of any Template blocks. Whenever we use the drop down list to select another value, the console immediately prints the currently selected ID. If no house is selected it will print undefined.

Use Tracker.autorun to print a Session variable to the console like this:

Tracker.autorun(function() {
    console.log("The selectedHouse ID is: " + 
                 Session.get("selectedHouse"));
});

As you can see, the Session object is very simple to work with and can be extremely useful. It can be accessed from any part of the application and maintains its values even if you change source files, and Meteor reloads your application (hot code pushes). If a user initiates a page refresh all data is lost though.

Keep in mind, though, that the contents of a Session object never leave the browser, so other clients or even the server may never access its contents. 

CA App Experience Analytics, a whole new level of visibility. Learn more. Brought to you in partnership with CA Technologies.

Topics:

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}