»
S
I
D
E
B
A
R
«
Model-View-Controller (MVC) with JavaScript
Jan 20th, 2010 by franciov

In developing Javascript Applications, the best thing you can do is rely on a framework such as SproutCore (that has recently reached version 1.0) or JavascriptMVC. However in some cases the Dojo toolkit or the jQuery library can satify most of your needs, expecially when you are relatively new to Javascript or just want to avoid the initial learning time associated to the use of a framework. But, as often happens in these situations, the lack of a framework, or at least of standardized and shared solutions, causes problems with maintainability, extensibility and complexity.  This is particularly true for Mobile Widgets, which are relatively simple Javascript Applications which don’t need, at least in my experience, a framework on which rely on, but need to implement architectural patterns and design patterns.

My goal for this article is to show how to create the main structure of a MVC-based Javascript Application using pure Javascript in defining classes, and the jQuery library to access and manipulate the DOM.

Model
Let’s start with the implementation of a Model object. ListModel is a very simple class that implements a list of items, in which items can be added and deleted.

function ListModel() {
        this._items = null;
}
ListModel.prototype = {
        init : function (items) {
                this._items = items;
        },

        getItems : function () {
                return this._items;
        },

        addItem : function (item) {
                this._items.push(item);
        },

        removeItemAt : function (index) {
                this._items.splice(index, 1);
        }
});

View
The View implements an action form which is included inside the finditems HTML div, consisting of an input text field and a button to apply the form. The init method bind the apply button to the method findItemsController’s apply method, for the click event. The show method cleans the screen and makes the view visible, the hide method makes the view not visible, and the getInputValue method returns the value that has been inserted in the input text field.

function FindItemsView(){
        this.view = "#finditems_div";
        this.inputTextfield = "#finditems_input";
        this.applyButton = "#finditems_apply";
}
FindItemsView.prototype = {
        init : function () {
                $(this.applyButton).click(findItemsController.apply);
        },

        show : function () {
                $(this.view).show();
        },

        hide : function () {
                $(this.view).hide();
        },

        getInputValue : function () {
                return $(this.input).val();
        }
};

Controller
The FindItemsView class is tightly bound with the FindItemsControllerclass, which handles the input event from the user interface via direct calls, registered handlers or callbacks. In our example FindItemsController’s apply method is called when the apply button is pressed (this event has been register in the init method of the FindItemsView class), gets the value of the input field from the View, then performs an asyncronous call to a service: the response handler is FindItemsController itself, and three callback methods (success, error and timeout) are passed. If nothing goes wrong, the success callback is called and a new ListModel object is created and initialized with retrieved items. At this point the control is given to the ListItemsController, that has the responsibility to display the ListModel on a different View.

function FindItemsController(){
}
FindItemsController.prototype = {
        init : function () {
        },

        apply : function () {
                var input = findItemsView.getInput();
                service.findItem(input, findItemsController, success, error, timeout);
               
        },

        success : function ( items ) {
                listModel = new ListModel();
                listModel.init(items);
                listItemsController.display(listModel); /* give the control to ‘listItemsView’ */
        },

        error : function () {
                alert("Error");
        },

        timeout : function () {
                alert("Timeout");
        }
};

Alright! This is the starting point to write a MVC-based Javascript Application using pure Javascript and jQuery library. Alex Netkachov in this article shows how to write a simple MVC-based JavaScript component with the support of the Dojo language utilities. Also want to point out this interesting video about JavascriptMVC: using a framework or a toolkit is rarely a bad idea.

Well, since in this period I am extensively developing Mobile Widgets (i.e. Javascript Application), I’m going to come back on the subject soon, showing how to implement widely used design patterns, such as Observer, Facade, Singleton and Factory.

Stay tuned !

How to skip a step in a Spring AbstractWizardFormController
Jul 22nd, 2009 by franciov

spring-framework-2.5

Here we are again dealing with the Abstract Wizard Form Controller, a form controller for typical wizard-style workflows, provided by Spring, a Java Web Application Framework. This time we discuss a more frequent problem: skipping steps.

For istance, let’s consider the situation in which you are at page n of your wizard and submitting a form for target n+1. What if, for some reason, you need to skip the step n+1 and go forward one step?

The first attempt to face this problem might consists in conditionally changing the target value inside the form included in the jsp page corresponding to the view for page n. For example we might switch between passing the request parameter _target3 or _target4 by using the JSTL Core TagLib. This works, but we are putting a conditional control inside a View, that is a very bad practice in a MVC-based framework like Spring.

Let’s move the conditional control into our wizard controller, and to be more precise into the getTargetPage method:

protected int getTargetPage(HttpServletRequest request, Object command, Errors errors, int currentPage) {

        if (currentPage == 2 /* n */) {
                if (/* insert your condition here*/) {
                        return 3; /* n+1 */
                }
        }

        return super.getTargetPage(request, command, errors, currentPage);
    }

This solution is clean and makes your application more readable, your code more reusable and so on…

But what if the step we want to jump to is the final step? We cannot reach it by using the getTargetPage method because the final step has no page number assigned: the finish action is triggered by the request parameter _finish and the view name is retrieved by the ModelAndView object that the processFinish method returns.

To solve this problem we can modify the view name for target n+1 at runtime by overriding the getViewName method as following:

protected String getViewName(HttpServletRequest request, Object command, int page) {

        if (page == 3 /* n+1 */) {
                retun "redirect:myWizard.html?_finish=";  // go to final step
        }

        return super.getViewName(request, command, page);
    }

In this way we simply redirect the flow to the final step. Obviously, at finish all pages get validated to guarantee a consistent state, so you cannot skip a step whose page needs validation.

Spring AbstractWizardFormController, how to manipulate pages at runtime
Jul 19th, 2009 by franciov

spring-framework-2.5
The Abstract Wizard Form Controller is a form controller for typical wizard-style workflows, provided by Spring, a Java Web Application Framework.

In contrast to classic forms, wizards have more than one form view page. Therefore, there are various actions instead of one single submit action:

  • finish: trying to leave the wizard successfully, i.e. performing its final action, and thus needing a valid state;
  • cancel: leaving the wizard without performing its final action, and thus without regard to the validity of its current state;
  • page change: showing another wizard page, e.g. the next or previous one, with regard to “dirty back” and “dirty forward”.

In this article I want to focus on pages, how to set them up, expecially in the uncommon situation in which you don’t know exactly the number of pages you want to put in your wizard before running the application.

Every Spring manual would suggest you to put WizardFormController’s pages in the Spring XML configuration file, and actually this is the best way to set up your pages. Let’s consider the following configuration:

<bean name="myWizardForm"
          class="forms.MyWizardForm">

    </bean>

    <bean name="/myWizard.html"
          class="control.MyWizardFormController"
          p:sessionForm="true"
          p:commandClass="forms.MyWizardForm"
          p:commandName="myWizardForm">

        <property name="pages">
            <list>
                <value>page0</value>
                <value>page1</value>
                <value>page2</value>
            </list>
        </property>
    </bean>

We have put a property named pages inside myWizard.html bean, in which we listed the page values. Each value is used as the name of the view inside your jsp folder.

And now the wizard form, you can set it up for your needs.

public class MyWizardForm {

    // put your fields here

    public MyWizardForm() {
        // initialization
    }

    // put your setters and getters here
}

Finally the wizard controller.

public class MyWizardFormController extends AbstractWizardFormController {

    public MyWizardFormController() {
    }

    protected Map referenceData(HttpServletRequest request, Object command, Errors errors, int page) throws Exception {

        Map map = new HashMap();
        // put information you need into the map

        return map;
    }

    protected ModelAndView processFinish(HttpServletRequest request, HttpServletResponse response, Object object, BindException exception) throws Exception {
        return new ModelAndView("finish");
    }

What if, for some reasons, you need to create or edit your wizard page list at runtime? Let’s face the problem.

First of all, you can override the XML configuration through the setPages method. The following example replaces the page list specified in the XML file with an identical one but that has been built at run-time in MyWizardFormController constructor.

public MyWizardFormController() {
        String pages[] = new String[3];
        pages[0] = "page0";
        pages[1] = "page1";
        pages[2] = "page2";
        this.setPages(pages);
    }
}

This doesn’t help much: we moved the configuration outside XML (that’s a bad thing) but we still have a fixed number of pages with fixed values.

Let’s consider an application in which the page values are the request parameter keys for the first step (i.e. _target0). We might call setPages inside an overridden method used before the wizard controller accesses to page list, such as the getInitialPage method.

public class MyWizardFormController extends AbstractWizardFormController {

    public MyWizardFormController() {
    }

    protected int getInitialPage(HttpServletRequest request, Object command) {

        // override pages only when the target page is 0
        if (this.getTargetPage(request, 0) == 0) {

            // retrieve keys from request parameters
            Set parameters = new HashSet(request.getParameterMap().keySet());
            Iterator parametersIterator = parameters.iterator();
            String pages[] = new String[parameters.size()1];
            int i = 0;

            // fill wizard pages
            while (parametersIterator.hasNext()) {
                String page = (String) parametersIterator.next();
                // let’s ignore the ‘_target0′ parameter key
                if (page.startsWith("_") == false){
                    pages[i] = page;
                    i++;
                }
            }

            this.setPages(pages);  
        }

        return super.getInitialPage(request, command);
    }

In this way, as soon as myWizard.html bean is invoked by clicking on a link (i.e. GET http request) or submitting a form (i.e. POST http request), the page list is dinamically built starting from request parameter keys. This would be more useful if you decide to use request parameters values, or attributes.

For my purposes I used request parameter keys retrieved from a form submission in order to run an unordered set of pages and reporting each result (i.e. validation) in the final step.

»  Substance: WordPress   »  Style: Ahren Ahimsa
© www.francesco.iovine.name