Handlerbars.js and Working with Complex Objects in MVC

In a previous post I used an EditorFor template to display child objects correctly on a view. Now we are going to use some simple JavaScript templating to add child objects. We have a page display book details and want to add and save additional authors.

Demo app

The demo app is a simple bookshelf application. It has a view that uses EditorFor templates to display a book which we want to save. The book can have multiple authors. It is a complex object.

The book is rendered onto the Book.cshtml view and the user sees a book then can be edited and saved as required.

authors-correct-display

The authors are rendered in this format

When this form is posted back, the default model binder in MVC uses the name attribute to correctly bind the authors as a child object of the book object. So we get a correctly populated book object passed through to the controller action.

The book parameter is populated will the correct authors. Nice. In general, to work with child objects the correct format for the name attribute in the HTML form element is ..

We’ll need to bear that in mind when we are creating a control to add new authors.

The Problem

The authors display correctly and work well but what if we want to add additional authors to the book before saving? Perhaps the book is missing authors. Perhaps I’m a rampant egotist and want to add myself as an author to every book in my virtual bookshelf. Let’s use Handlerbars.js and some JQuery goodness to do this.

The Solution

Handlebars.js

Handlebars.js is one of many JavaScript templating engines that bind fragments of HTML and produce data driven templates. Handlebars takes a template such as

And binds it against some JSON

To produce HTML

That’s going to be good for us. We’ve got some pretty chunky fragments of HTML and we want to work with it in the cleanest way we can.

Integrating Handlerbars.js into MVC

Install the package using nuget

In it goes to the application. Now create a script bundle in BundleConfig.cs

and reference that bundle in the view

Creating the HandleBar template

Let’s dive straight in and create the template. We want a HTML fragment that will generate us a new author. HandlerBar templates need to be in script tags with the type

our full template is

This gives us a hidden field for the AuthorID and a text field for the author name. The curly brackets tell us where the holes in the template are so

Are the two pieces of data that the template needs. Handlebars will replace these with the data we supply it.

Constructing the Author add control

Now we need a HTML control to add the author. We want something like this

authors-with-add-button

So a textbox and a button with a squirt of CSS

Let’s assume that JQuery is already reference and available. Next job is to wire up the click event to the button

Which is standard stuff.

Obtaining the data for the template

Next we need to construct the JSON data that Handlebars will use to generate the HTML. We need two pieces of information

  1. The authors name as inputted by the user
  2. The next index of the author elements

Grabbing the author name is straightforward

However to get the next index we need find the current highest index. First we need to navigate the DOM to find the last author. The authors are all wrapped in the ‘shelf-authors’ class to facilitate this

then we want the name attribute

Then we want the last index. If there are 3 authors then lastAuthorFormName will contain

So some regex the current index i.e. the number in square brackets

The entire regex matches “[2]” and the first and only group (\d*) matches the digit itself. The output for this is an array. The first element of the array is the full match. All subsequent elements are the matches for the containing groups (defined in regex by parenthesis). So

would equal “[2]” and

would equal “2”.  So to get the next index we need

Now we have all the information we need to construct the data for the handlebar template

Gluing the template together

Gluing the data into the template is pretty much boilerplate code

Grab the template with a CSS selector then compile and combine. The HTML is now correct and can be inserted into the DOM

The Complete Solution

So combining all the steps together we get

The HTML element is now correct and when this is posted back the new author will be present in the action method i.e.

The book parameter will have a fourth author which will be saved.

author-successfully-added

So I can now add myself as an author to every book in my library which goes some way into feeding my monstrous and uncontrolled ego – which is what it’s all about really.

Useful Links

Project page for handlebars
http://handlebarsjs.com/

Nuget page for handlebars
https://www.nuget.org/packages/Handlebars.js/

Demo application source
https://github.com/timbrownls20/BookShelf/

 

Leave a Reply

Your email address will not be published. Required fields are marked *