TIL Thursday: Add Modals to your Forms

TIL Thursday is a series of articles that illustrates an area of functionality or part of SuiteCommerce Advanced that you may not know about. By the end of it, you should be able to say "Today I learned..."

In the third part of the tutorial, we did some coding which dealt with updating a record. On the list page, we created a link that sends the user to a separate page to edit or add a record, and submitting the form sent them back to the list page. But did you know that we recommend all add and edit functions are performed in a modal dialog?

This article will take you through the simple steps of implementing modals on a list page, including the template changes to launch the modals and the code change required to 'refresh' the list when a record is added or changed.

Modify the Template

The first step is the easiest. As part of the SuiteCommerce Advanced bundle, we have included a version of Bootstrap that builds in support for modal dialogs. Thus, any page that you want to open in a modal requires a small change to templates.

Building on the work we did for the Artist module, open artist_details.tpl. Add the following code as an attribute to the "Edit" button:

data-toggle="show-in-modal"

Note that we don't need to do this for the delete button as we're already using a confirmation dialog for this. However, you'll also need to update the "New Artist" button in artist_list.tpl with the same code. After you've saved your changes, run gulp local and visit your local site. Now if you click on "New Artist" or "Edit" you'll see your forms open in modals. In fact, if you enter or update data, it'll submit and send to the server like normal.

But, you'll also notice that when you update or add a record, the list does not automatically update with the latest information (but it will if you refresh the page). This behaviour is sub-optimal and inconsistent with other actions on the site, namely the delete operation which does update the list automatically. The next step will be adding in some code to trigger a refresh.

Reload the List

Remember, it is the router that decides what happens when a particular URL is requested; it is here where we have artistDetails function that determines what is shown when a user requests to create a new artist or update the details of an artist. We need to edit the part of the deferred object (or 'promise') that runs when the promise is resolved. In Artist.Router.js replace your promise.done function with the following:

promise.done(function () {
    var view = new EditView({model: model, application: self.application});

    model.off(null, null, self);
    model.on('reset destroy change add sync', function () {
      var currentView = self.application.getLayout().currentView;
      if (currentView instanceof ListView) {
        self.artistList();
      } else {
        Backbone.history.navigate('artists', {trigger: true});
      }
    }, self);

    view.showContent();
});

The first line is standard, it's just building the view. It is the next parts that are specific to the modal dialogs:

  1. Kill all previously-bound callbacks to the model (using model.off), this is basically just a bit of tidying up.
  2. Set up a function for the callbacks that we want.
  3. Within that function, check for the view the user is currently looking at.
  4. Using that, find out if it's the list view page. If it is, tell it to run the artistList function, which generates the list of artists. This is kind of like saying "hey, act like they've just visited the page in their browser" but without refreshing the whole page.
  5. If they're not viewing the list page, because, for example, they went directly to the details page in their browser, then navigate them to the list page (like they clicked a link to go there).
  6. Finally, show the content of the view.

That's really it. If you save the file and reload your local site again, you'll see that your new artists (or changes to existing artists) are immediately reflected in the list page.

Considerations for Use

The method outlined above contains some characteristics specific to the Artist module itself. When does this yourself for your own pages, there are some things you should keep in mind.

  1. Not all modules contain deferred objects. Nonetheless, this code still works with some modifications. For example, changing self for this.
  2. The use of model.off and model.on is specific to this module as the view we're using doesn't include child views. If, for example, your module uses a collection, then you might need to change model for collection.
  3. If you get stuck, compare your router to the router of a reference module that is similar in function to yours. It will give you an idea of how it should look. For example, Address.Router.js does similar things to our Artist module.

Summary and Extensions

So this was just a short tutorial on getting modals to work. The first part involves a small template change to add parameters to the links that we want to launch modals using in-built Bootstrap functionality. The second part involves a change to the router function that handles the details view.

To take it further, you could modify the templates to include, for example, a "Cancel" button &em; while there is a "X" in the top right of the modals, you may wish to make quitting the modal more prominent. Just make sure you update your view to contain events that listen for this button, and then closes the modal. Refer to other modules for an idea on how to do this.

Further Reading