Note: This release is in preview. Features described here don’t become generally available until the latest general availability date that Salesforce announces for this release. Before then, and where features are noted as beta, pilot, or developer preview, we can’t guarantee general availability within any particular time frame or at all. Make your purchase decisions only on the basis of generally available products and features.

Define a Router

A Backbone router defines navigation paths among views. To learn more about routers, see What is a router?

  1. In the final <script> block, define the application router by extending Backbone.StackRouter.
    1app.Router = Backbone.StackRouter.extend({
    2
    3});

    For the remainder of this procedure, add all code in the extend({}) block.

  2. Because the app supports a search list page and a user page, add a route for each page inside a routes object. Also add a route for the main container page ("").
    1routes: {
    2    "": "list",
    3    "list": "list",
    4    "users/:id": "viewUser"
    5},
  3. Define an initialize() function that creates the search results collection and the search page and user page views.
    1initialize: function() {
    2    Backbone.Router.prototype.initialize.call(this);
    3
    4    // Collection behind search screen
    5    app.searchResults = new app.models.UserCollection();
    6
    7    app.searchPage = new app.views.SearchPage(
    8        {model: app.searchResults});
    9    app.userPage = new app.views.UserPage();
    10},
  4. Define the list() function for handling the only item in this route. Call slidePage() to show the search results page right away—when data arrives, the list redraws itself.
    1list: function() {
    2   app.searchResults.fetch();
    3   this.slidePage(app.searchPage);
    4},
  5. Define a viewUser() function that fetches and displays details for a specific user.
    1viewUser: function(id) {
    2    var that = this;
    3    var user = new app.models.User({Id: id});
    4    user.fetch({
    5        success: function() {
    6            app.userPage.model = user;
    7            that.slidePage(app.userPage);
    8        }
    9    });
    10}
  6. After saving the file, run the cordova prepare command.
  7. Run the application.

Example

You’ve finished! Here’s the entire application:

1<!DOCTYPE html>
2<html>
3<head>
4<title>Users</title>
5<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" />
6<link rel="stylesheet" href="css/styles.css"/>
7<link rel="stylesheet" href="css/ratchet.css"/>
8</head>
9
10<body>
11
12<div id="content"></div>
13<script src="js/jquery.min.js"></script>
14<script src="js/underscore-min.js"></script>
15<script src="js/backbone-min.js"></script>
16
17<!-- Local Testing -/->
18<script src="js/MockCordova.js"></script>
19<script src="js/cordova.force.js"></script>
20<script src="js/MockSmartStore.js"></script>
21<!-- End Local Testing -->
22
23<!-- Container -->
24<script src="cordova.js"></script>
25<!-- End Container -->
26
27<script src="js/force.js"></script>
28<script src="js/force+promise.js"></script>
29<script src="js/mobilesync.js"></script>
30<script src="js/fastclick.js"></script>
31<script src="js/stackrouter.js"></script>
32<script src="js/auth.js"></script>
33
34
35<!-- ----Search page template ---- -->
36<script id="search-page" type="text/template">
37  <header class="bar-title">
38    <h1 class="title">Users</h1>
39  </header>
40
41  <div class="bar-standard bar-header-secondary">
42    <input type="search" 
43     class="search-key" 
44     placeholder="Search"/>
45  </div>
46
47  <div class="content">
48    <ul class="list"></ul>
49  </div>
50</script>
51
52<!-- ---- User list item template ---- -->
53<script id="user-list-item" type="text/template">
54
55  <a href="#users/<%= Id %>" class="pad-right">
56    <img src="<%= SmallPhotoUrl %>" class="small-img" />
57    <div class="details-short">
58      <b><%= FirstName %> <%= LastName %></b><br/>
59      Title<%= Title %>
60    </div>
61  </a>
62</script>
63
64<!-- ---- User page template ---- -->
65<script id="user-page" type="text/template">
66  <header class="bar-title">
67    <a href="#" class="button-prev">Back</a>
68    <h1 class="title">User</h1>
69  </header>
70
71  <footer class="bar-footer">
72    <span id="offlineStatus"></span>
73  </footer>
74
75  <div class="content">
76    <div class="content-padded">
77      <img id="employeePic" 
78         src="<%= SmallPhotoUrl %>" class="large-img" />
79      <div class="details">
80        <b><%= FirstName %> <%= LastName %></b><br/>
81        <%= Id %><br/>
82        <% if (Title) { %><%= Title %><br/><% } %>
83        <% if (City) { %><%= City %><br/><% } %>
84        <% if (MobilePhone) { %> 
85           <a href="tel:<%= MobilePhone %>">
86           <%= MobilePhone %></a><br/><% } %>
87        <% if (Email) { %>
88           <a href="mailto:<%= Email %>">
89           <%= Email %></a><% } %>
90      </div>
91    </div>
92  </div>
93</script>
94
95<script>
96// ---- The Models ---- //
97// The User Model
98app.models.User = Force.SObject.extend({
99    sobjectType: "User",
100    fieldlist: ["Id", "FirstName", "LastName", "SmallPhotoUrl", 
101       "Title", "Email", "MobilePhone","City"]
102});
103
104// The UserCollection Model
105app.models.UserCollection = Force.SObjectCollection.extend({
106    model: app.models.User,
107    fieldlist: ["Id", "FirstName", "LastName", "SmallPhotoUrl", 
108        "Title"],
109
110    getCriteria: function() {
111        return this.key;
112    },
113
114    setCriteria: function(key) {
115        this.key = key;
116        this.config = {type:"soql", 
117                       query:"SELECT " 
118                        + this.fieldlist.join(",")  
119                        + " FROM User"
120                        + " WHERE Name like '" + key + "%'"
121                        + " ORDER BY Name "
122                        + " LIMIT 25 "
123                      };
124    }
125});
126
127
128// -------------------------------------------------- The Views ---------------------------------------------------- //
129
130app.views.SearchPage = Backbone.View.extend({
131
132    template: _.template($("#search-page").html()),
133
134    events: {
135        "keyup .search-key": "search"
136    },
137
138    initialize: function() {
139        this.listView = 
140            new app.views.UserListView(
141                {model: this.model});
142    },
143
144    render: function(eventName) {
145        $(this.el).html(this.template());
146        $(".search-key", this.el).val(this.model.getCriteria());
147        this.listView.setElement($("ul", this.el)).render();
148        return this;
149    },
150
151    search: function(event) {
152        this.model.setCriteria($(".search-key", this.el).val());
153        this.model.fetch();
154    }
155});
156
157app.views.UserListView = Backbone.View.extend({
158
159    listItemViews: [],
160
161    initialize: function() {
162        this.model.bind("reset", this.render, this);
163    },
164
165    render: function(eventName) {
166        _.each(this.listItemViews, 
167            function(itemView) {itemView.close(); });
168        this.listItemViews = 
169            _.map(this.model.models, function(model) {
170                 return new app.views.UserListItemView(
171                     {model: model}); });
172        $(this.el).append(_.map(this.listItemViews, 
173            function(itemView) {
174                return itemView.render().el;} ));
175        return this;
176    }
177});
178
179app.views.UserListItemView = Backbone.View.extend({
180
181    tagName: "li",
182    template: _.template($("#user-list-item").html()),
183
184    render: function(eventName) {
185        $(this.el).html(this.template(this.model.toJSON()));
186        return this;
187    },
188
189    close: function() {
190        this.remove();
191        this.off();
192    }
193});
194
195app.views.UserPage = Backbone.View.extend({
196
197    template: _.template($("#user-page").html()),
198
199    render: function(eventName) {
200        $(this.el).html(this.template(this.model.toJSON()));
201        return this;
202    }
203
204});
205
206
207// ----------------------------------------------- The Application Router ------------------------------------------ //
208
209app.Router = Backbone.StackRouter.extend({
210
211    routes: {
212        "": "list",
213        "list": "list",
214        "users/:id": "viewUser"
215    },
216
217    initialize: function() {
218        Backbone.Router.prototype.initialize.call(this);
219
220        // Collection behind search screen
221        app.searchResults = new app.models.UserCollection();
222
223        // We keep a single instance of SearchPage and UserPage
224        app.searchPage = new app.views.SearchPage(
225            {model: app.searchResults});
226        app.userPage = new app.views.UserPage();
227    },
228
229    list: function() {
230        app.searchResults.fetch();
231        // Show page right away
232        // List will redraw when data comes in
233        this.slidePage(app.searchPage);
234    },
235
236    viewUser: function(id) {
237        var that = this;
238        var user = new app.models.User({Id: id});
239        user.fetch({
240            success: function() {
241                app.userPage.model = user;
242                that.slidePage(app.userPage);
243            }
244        });
245    }
246});
247</script>
248</body>
249</html>