Model-View-Controller in jQuery

Overview

If you haven’t read it already, be sure to check out this post where I talk more about the motivation for this tutorial.

This MVC setup is perfect if you want to build an application like Jotlet.net, 280Slides.com, or even Gmail. If you’re aiming to build a more traditional web app like BaseCamp, Flickr, or Digg, then this still might be a good resource. A good rule of thumb: If you web application has 1 page load, then this is a great setup! If your app has more than 1 page load, read on anyways and you still might be able to apply some of these principles.

The approach I outline below – as with all my tutorials – is server agnostic. I’ll be using PHP to power the demos, but you can easily use Ruby, Java, or even Lisp! :)

Goals

  1. Clean simple code
  2. Separate the logic of the view and the model
  3. Cache data on the client side – minimize AJAX calls
  4. Provide clean interface to data so disparate view objects can work together on same data model
  5. Maximize both model and view code reuse

The Tutorial

I’ve split this tutorial into multiple Phases. Each phase builds upon the previous, and each has its own demo and sample code that it walks through (and download!). So be sure to check them all out!

The first Phase sets up the foundation on which all the other’s will rely – so it’s a great place to start. Each next phase will add a bit of functionality onto the code from the previous phase.

  1. Phase 1: Loading data from the server
  2. Phase 2: Saving data to the server
  3. Phase 3: Managing Multiple and Relational Data Types (coming soon)
  4. Phase 4: Initializing the model with data (coming soon)
  5. Phase 5: Offline mode (coming soon)

47 responses to “Model-View-Controller in jQuery”

  1. Curtis

    Wow, this is really good stuff already. Already learned quite a bit, can’t wait for the rest.

  2. Happy Tarot » Code » Model-View-Controller in JQuery

    [...] Model-View-Controller in JQuery [...]

  3. Joel Gascoigne

    I really like the idea of this concept, I will be keeping an eye on this for your later parts. May I suggest looking at the PHP function json_encode(), though ;)

  4. links for 2008-08-08 [delicious.com] « Talkabout

    [...] Model-View-Controller in JQuery "Goals [...]

  5. links for 2008-08-09 [delicious.com] « Talkabout

    [...] Model-View-Controller in JQuery "Goals [...]

  6. jQuery : the Official JavaScript Library of Listotron | Listotron Blog

    [...] can check out his extensive front-end Model-View-Controller JavaScript development pattern here. We will be applying this methodology to Listotron, so expect more specific examples and tutorials [...]

  7. Joel Gascoigne

    Hi Adam,

    I’ve actually been putting a heavily modified version of the model-view-controller pattern you describe above into practice in one of my current projects, as it is a rather large project and there is heavy use of AJAX throughout.

    I have actually gone for having a model, view and controller object extended from jquery, smiliarly to you have it but I then have requirement for separate pages and therefore separate models, views and controllers. For example, I have a page named “create”, so I have a createModel, a createView and a createController which are extensions of model, view, controller.

    Having been working with the pattern extensively for a couple of days, it seems to make the code very maintainable and clean, but I have come across one problem:

    Have you thought about how to handle sending parameters when requesting items? Some items require different values sent back depending on one or more parameters sent to them.

    I therefore modified the model to optionally accept parameters and go for POST rather than GET if indeed parameters are required. Seems fairly straightforward, right? Then there’s the problem of caching the same named item but for different combinations of parameters, and this is where I’ve come a little stuck. Caching seems a little redundant once you realise that if parameters are being sent then the response will be different a lot of the time.

    I think this idea needs to be extended a little. There needs to be some way of storing items along with the set of parameters which was sent with the request for the item, very crudely put would be something like cache[item][parameters] – but parameters can be any number of parameters and possibly arrays to send too, so this quickly falls over.

    This is rather long now! What are your thoughts on the matter?

    Joel

  8. Joel Gascoigne

    I’m talking about caching data within the model, in order to avoid multiple AJAX requests for the same item. But the problem arises when you’re requesting items where you’re sending parameters.

    For example, in most moderately sized web applications, you’re going to need more than just GET without any query string or POST parameters. This cropped up for me when using AJAX to retrieve a URL friendly title for a page, the “item” name may be “url_name”, but the value of the item will differ depending on the “full name” of the page for which that short URL is generated. So in this case you would request the “url_name” with a parameter “full_name”. So then retrieving “url_name” in the future returns the cached “url_name” which would not be the desired result, since the “full_name” may have changed.

    I hope you understand the problem I’m describing now.

  9. Joel Gascoigne

    Yep I think you’re with me now – and I had thought about a hashtable approach, I think that’s the only real solution to the problem. Whatever the solution, it needs to be as abstracted as possible, and there may be good reason for certain items to never be cached.

    I’ll be keeping tuned for the later phases, thanks again for opening my eyes to using the much used model-view-controller pattern client-side!

    I expect I will be developing my own version of this, so I will let you know if I come up with some method for caching items with additional data – I certainly think it is something which is necessary in order to make this truly usable.

  10. Peter C

    Hi Adam and Joel,
    Just googled onto this Ajax’ed MVC model. I’ve been looking at JavascriptMVC.com.
    ° I like your model involving Cache-V-C on the browser and MVC on the server. Would like to add that in some complex situations, you may need to synchronize data back to the server.
    ° I’m looking forward to implement this model and to put more intelligence on the browser to offload the server. There would be lots of security concerns (e.g. session info).

  11. mohangk.org/blog » links for 2008-09-03

    [...] Model-View-Controller in jQuery | Wulf An interesting ongoing tutorial on implementing the MVS stack within the browser (A-la JavascriptMVC.com). Looks intriguing and possiby a solution to the mess large javascript applications tend to be. However, the jury is still out (IMHO) as to the whether a MVC framework within the browser is really the best solution for this (tags: jQuery mvc framework AJAX tutorial) [...]

  12. Bob

    Your demo seems to be failing 100% of the time, not 10%. :-)

    INteresting stuff though

  13. lambert

    when’s part 3 coming out? =)

  14. noor

    good evening,
    my name is noor, i would like to inform that i have a project related to MVC and i need a help. so, can you help me in answering these two questions:
    1- Examples of MVC?
    2- What is a pattern within the context of software development?
    thank you alot and best regards,
    noor:)

  15. ajlozier

    joel, i would love to see some code samples of how you extended the base model view and controller classes into more specific instances. thanks!

  16. 50+ jQuery Tutorials und mehr für Einsteiger und Fortgeschrittene

    [...] Model-View-Controller in jQuery Umsetzung des MVC-Konzepts in jQuery. [...]

  17. george

    hi there,

    I’m eager to read the phase3 and other upcoming sections…will they be posted soon?

    currently I’m working on a project using asp.net mvc with nHibernate spring and jQuery

    thx a lot

  18. Guilherme

    This is great stuff! I feel the same need as you, I’m currently developping a new web 2.0 application and wanted to do things in the right away this time, to avoid the javascript messy management.

    You mentioned that the code is most suitable for those applications with only one page load, and I believe you’re saying that because of the client-side cache, right? (reloading would loose the cache and defeats the purpose). Have you ever considered to have an invisible frame (height=0) from where AJAX calls would be made and where the cache would be kept?

    This way your main screen could be reloaded and cache would be preserved. I have this arcthitecture implemented here where I work at, but we are still in the rock age (that is, not using jquery :-) .

    For my personal project I’ll see if I can mix the two things: client-side jquery/json mvc and invisible frame caching.

    Good work!

  19. Steven Black

    This has been inspiring, Adam.

    After playing and building upon this for a few days, I’ve taken this in an interesting direction.

    Are you aware that there’s nothing in these articles, and nothing I’ve built-upon the articles, that is inherently jQuery’ish at core?

    In other words, the jQuery.extend({}} method for creating Models, Views, and Controllers, isn’t required.

    I’ve now mapped the basic ideas onto an alternative base, described by our good friend here: http://is.gd/mED0

    This removes the tricky inheritance difficulties (and failings) inherent in jQuery.extend({}} and, as a result, I have Models, Views, and Controllers as subtypes of an MVCBase class and nicely partitioned lower subtypes for different types of Controllers and Views reflecting the different types interaction panes in this application.

    jQuery is still used throughout, and the MVC elements themselves use jQuery functionality extensively, just that they aren’t themselves jQuery objects.

    Stepping outside the jQuery paradigm for the MVC pieces is a nice breakthrough. Nothing is lost, and the ability to properly classify subtypes is much easier and more straightforward.

    A cool variant I’ve implemented is, using jQuery, a Controller can manage many Views, as you might see in a tabbed interface where each tab is driven by a separate business object but centrally managed by a Controller in a generic way.

    Another View, a basic one, serves to enable and disable tabs as a particular page goes in and out of edit mode. Similarly another simple View serves as an interface to enable and disable other navigation menus as the page goes into edit mode.

    Thanks for the inspiration. Those listeners are killer!

    **–** Steve

  20. Chris

    I’m actualy quite interested in how Steven implemented this, and your take on handling multiple views. For example. If you had a wizard that required multiple “screens” of collecting data, and then on the last screen the data was sent to the server, where would the data object before it’s sent off? In the Controller? or in the Model? My first guess would be the object hosting the data being collected would be stored in the model and updated throughout the screen transitions, but I have a feeling it’s not so simple.

  21. Steven Black

    (Email notifications of comments is great!)

    @Chris, I think the key abstraction bridging views and data is the form elements themselves.

    Using jQuery this is easy.

    For example, when creating the view you can pass-in any container selector and, in the view::init(), snurf-out all the forms therein.

    Remember it’s the forms that contain the fields (both visible and hidden), and the very handy jQuery Deserialize plugin (http://www.reach1to1.com/sandbox/jquery/testform.html) works on a form-basis.

    So creating a view is a matter of passing-in a comma-delimited list of form selectors, or comma-delimeted list of containers that may (or may not) contain the forms. Even pass-in the body selector if you want to snag all the forms. It just works.

    So the forms are a natural basis for transient data storage prior to submitting.

    Implementation details can vary but, in Adam’s model, the submit action triggers a notification to listeners and, at that point, a specialized listener can iterate through one or more views managed by the controller and, within each view, iterate the forms and marshall the data from each one prior to an ::ajaxSubmit()

    Note too that you could hook-in the most excellent Form Validation plugin and trigger the marshalling after successful client-side validation, which is a bonus.

    I’m at that stage now, and running into the usual Javascript problems of properly referencing objects called from delegated functions called from other delegated functions without resorting to global-scope, or equivalent-to-global-scope kluges.

    At the moment my design has a variable addressed as $.MVC where, regardless of the depth of delegation, I can always find the (so far singleton) controller and its (so far singleton) model.

    I’m not comfy with the notion of the model object as a singleton. What I have now works but I can foresee the day when this simplification will be onerous. The underlying question to resolve is, assuming no spaghetti, which model is immutably tied to which view?

    That’s not a trivial problem, and I sense that I’m one use-case away from having to address it. I might resort to a collection of model-view pairs maintained by the (so far singleton) controller where the views remain a wrapper for one or more forms. That part is working great.

    All that said, I’m pretty happy with subtyping models and controllers so far.

  22. Chris

    @Stephen

    Thanks for your insight. I can see how forms are good for holding data prior to transmission, but I think my particular case may need a different architecture.

    I’m contemplating rewriting an old order entry system for a local bakery. Previously I wrote it in ASP.NET and it had multiple pages, with no AJAX. There are at least 15 different screens/subscreens allowing for customizing of hundreds of goods, and throughout each page, I accumulated all of the data in a session object (which I regret, b/c session is a pain), and that session object would transcend from page to page. I’d like to rewrite it to use the single-page MVC model. But the catch is, after each item was selected/modified, the total price in the top right would have to update, meaning the order would have to be processed on each user action. To have to comb through the DOM, retrieve each item’s price on every user action seems like too much

    That being said, my first thought would to be make a js object that keeps a running tally of what was selected/modified throughout the order process, much like a bar tab. Every time the user clicks something, the listeners would alert the controller, and the controller would update the variable with the changes. After a few screens the order would look something like this:

    var order = {
    name: ‘Joe Smith’,
    location: ‘Southwest’,
    orderdate: ’07/17/2009′,
    delivery: ‘pickup’,
    payment: {
    type: Visa,
    card: 5555555555555555,
    expMonth: 9,
    expYear: 8
    },
    items: {
    desserts: [
    { name: 'Chocolate Cake', quantity: 1, price: 9.99, message: 'Happy Birthday Jim!!!' },
    { name: 'Pudding Cake', quantity: 2, price: 13.99, message: 'Another message' },
    { name: 'Carrot Cake', quantity: 4, price: 8.99, message: 'None' },
    ],
    drinks: [
    { name: 'Sweet Tea', quantity: 1, size: '128oz', price: 2.99 },
    { name: 'Orange Soda', quantity: 2, size: '128oz', price: 1.99 },
    { name: 'Fruit Punch', quantity: 4, size: '128oz', price: 2.99 },
    ]
    }
    };

    When the user submits the order, then the controller would instruct the model to pass the order as json to the server and the server would then save it.

    Loading an existing order would work in the reverse fashion. A controller would take the existing order, loop through each type of item, pass each portion of the order to the appropriate view, and each view would update its DOM elements accordingly.

    Another option would be to send an AJAX call to the server, and the server temporarily store it either in a session object or a temp db table, and return the updated price, but this would require an AJAX call every time the user clicks an element, which isn’t very practical.

    Anyway, please let me know if I’m on the right track here. Thanks again.

  23. Steven Black

    A couple of ideas, bearing in mind that I’m looking at a vast simplification of your structures.

    1) No need to repeatedly comb through the DOM. You could, for example, assign a common class to all the “total” fields on the various pages, cache them as a single jQuery object and, at event junctures, spin through them summing the values then displaying the sum.

    Even if the number of these ‘total’ fields is dynamic, you can always get to them pretty efficiently by addressing their parent containers, which greatly cuts down on the DOM iteration costs.

    So once you’ve combed the DOM once, you cache the references (or parent container references) for quick and speedy subsequent access to particular values.

    2) You may have an opportunity to normaliza and flatten your json structire. Rather than

    items{deserts: [], drinks: []…}

    You could make ‘deserts’ and ‘drinks’ an attribute of each item. This looks doable because, regardless of the structure of item, “quantity” and “price” look consistent and, by my eye, that’s all you need for the dynamic total calculations.

    Point being: if you can normalize the item structure then that makes dynamic access more straightforward, especially if the semantic differences between item types aren’t really relevant to the display dynamics.

  24. Chris

    I know you’ve been busy, but any luck on a part 3 for this tutorial?

    Thanks

  25. greg

    hey, i think the jquery mvc idea is great. i wonder y the tutorial has seized?

    jquery is now at 1.4.2… any of you guys know a good jquery mvc tutorial?

    thanks

  26. Weise

    Hi there , very interested to know if you will be completing this excellent tutorial?… Best Regards

    weise

  27. storm

    Like anything else in development, you’ll have to decide if the trade-off of this kind of separation is worth it. For small applications where you only have a few functions, this type of separation is surely overkill. The larger your application gets, though, the more it benefits from the separating code into Model, View, and Controller.
    JavaScriptMVC
    JavaScript MVC conception

  28. Chris

    For any type of javascript work that’s bigger than an example or a function or two, I’ve used this setup. It’s served me well over the past year or so. The only thing I’m curious about is how to get inheritance to work with this model. I know I can use .extend, but that doesn’t allow overriding methods.

  29. Model-View-Controller in jQuery | Wulf « random misspellings

    [...] Model-View-Controller in jQuery | Wulf. [...]

  30. John

    Nice, clean approach, simple.

  31. madhuka

    grate one!!

  32. Piyush

    Hi there , very interested to know if you will be completing this excellent tutorial?… Best Regards

  33. MVC in jquery, Multiple data requests from model but single callback needed | Easy jQuery | Free Popular Tips Tricks Plugins API Javascript and Themes

    [...] am trying to go after something like this. [...]

  34. Greg

    did Adam die or did this get dropped after part 2?

  35. Modular Jquery SPA (MVC)

    [...] Adam Wulf tutorial (3-4 years ago) [...]

  36. Xavi

    That’ll be great Adam! This tutorial is very promissing

  37. vatsal

    Thanks a lot Adam … It’s very well explained …exactly what I was looking for…. :D

  38. rahul

    it’s amazing tutorial

    thanks

  39. SAM BI

    thank you for the tutorial!

Leave a Reply

Google Author link