Single Page Apps – Writing a LoDash/Underscore Plugin for SammyJS

Sammy.jsAlthough SammyJS is a router that provides you with file loading of data and templates. You load templates and data using Sammy’s plugins.

In this tutorial, you will learn how you can use sammy.load to load JSON data, and then use LoDash (or Underscore) to _.find() to retrieve the item based on the value provided in the sammy route. And you will combine the template and data using a custom Sammy plugin.

Why LoDash?

LoDash or Underscore provide great methods for working with collections and arrays. There are subtle differences in these two libraries. But for this tutorial, they provide the same functionality.

Use these libraries to “slice and dice” your data. In the case of this tutorial, you will use _.find(). In your real life applications, there will be more complex ways of manipulating your data, that LoDash can provide.

LoDash includes _.template(). The template method compiles a set of HTML code and turns it into JavaScript. The templates can include _ and complex JavaScript functions.

For a tutorial on how to build LoDash templates, see HTML Templates With Logic Using Underscore, LoDash.

Getting Started

You should already know how to build LoDash templates and how load templates and data into Sammy.

For this tutorial, you will need:

Place the libraries in a folder named Scripts

And you will need starter code that includes data and templates and a starter page for your HTML.

Data/products.txt

Templates/product.html

Templates/products.html

The starter HTML

The code loads the Sammy plugin that you will write, adds the plugin so Sammy can use it, and then runs the routes.

The code in yellow, loads the Scripts/sammy.lodash.js file that you will write, and uses the sammy.use method to make it available inside Sammy. The Sammy.use() use takes the plugin function you defined and evaluates it within the context of the current application.

<!DOCTYPE html>
<html>
<head>
  <title>Products Using Custom LoDash Plug-in for Sammy</title>
</head>
<body>
  <nav>
    <ul>
      <li><a href="#/">Home</a></li>
      <li><a href="#/products">Products</a></li>
      <li><a href="#/products/1">Product 1</a></li>
    </ul>
  </nav>

  <div id='content'></div>

  <script src="Scripts/jquery-1.9.1.js"></script>
  <script src="Scripts/lodash.js"></script>
  <script src="Scripts/sammy-0.7.4.js"></script>
  <script src="Scripts/sammy.lodash.js"></script>
  <script>
    (function () {
      "use strict";
      console.log("initializing sammy");

      var app = $.sammy('#content', function () {

         this.use('LoDash','html);

        // the callback is the entire route wrapped in a closure
        this.around(function (callback) {
          var context = this;
          this.load('data/products.txt', { json: true })
        .then(function (items) {
          context.items = items;
        })
          .then(callback);
        });


        this.get('#/', function (context) {
          context.log('Yo yo yo');
          context.app.swap(''); // clear the content area before loading the partials
          context.$element().append('<h1>Main page</h1>');
        });

        this.get('#/data', function (context) {
          context.app.swap(''); // clear the content area before loading the partials
          context.$element().append(JSON.stringify(context.items));
        });

        this.get('#/products/:id', function (context) {
          // Insert your code here
        });

        this.get('#/products', function (context) {
          // Transform the data using a LoDash template
        });
      });

      $(function () {
        app.run('#/');
      });

    })();
  </script>
</body>
</html>

Add the Products Route Code

The implementation of the routes this.get(‘#/products‘, is actually the same code that you used in the previous post, SPA 5–Deep Dive into Loading Templates Using Sammy, Mustache, RequireJS.

 

The difference is that because Sammy’s render method will the Sammy.LoDash method in our new sammy.lodash.js plugin because we specified that using the sammy.use() where you pass in the function name(Sammy.LoDash) and the extension type (html).

Add the Product Route Code Using LoDash/Underscore Find

Use LoDash (or Underscore) to find the right product based on the route. _.find uses a function to determine which of the product matches the id in the route.

this.get('#/products/:id', function (context) {

  var param = context.params['id'];
  var products = context.items.products

  // find the product based on the value of :id
  var productData = _.find(products, function (product) {
    return product.id.toString() === param;
  });

  if (!productData) {
    return context.notFound();
  }

  // partial() internally calls render and swap 
  // creates the html and puts it into $element
  context.partial('Templates/4-product.html', { product: productData });
});

Build the LoDash Plugin

A Sammy plugin is really just a Sammy app definition that isn’t evaluated until needed. You can use Sammy plugins for code that you can reuse across applications. Sammy users have provided several plugins. You can find them at Sammy Plugins. And you can model your plugin from that.

Sammy uses plugins to automatically transform the data using templates.

The code uses a factory pattern to create the plugin using define method when the module is used for AMD, or uses window global values.

The object exposes the Sammy.LoDash function that uses the _.template method.

Sammy loads the template from the file and passes it into Sammy.LoDash, which then calls _.template().

You can use the plugin as a helper function too. The code sets up the plugin so you can use it as a help function too.

Scripts/sammy.lodash.js

(Note that in the define method, by convention I am using underscore as the name of the require.js module.)

Currently the tests for all plugins are contained in the single file test_sammy_plugins.js

Sample Code

This sample code is available on the DevDay repository on GitHub:  https://github.com/devdays/single-page-app/tree/master/Sammy

See 7-LodashEngine.html

References

Sammy Plugin reference

Sammy Plugins source code

SammyJS loading json from http

Advertisements