Вы находитесь на странице: 1из 16

Build a simple client-side MVC app with RequireJS | @verekia's blog

4/16/2013

@verekia's blog

Productivity

CSS Preprocessors

Responsive Initializr

RequireJS

Less

About me Resume

Posted on November 2, 2011

Previous Next

Build a simple client-side MVC app with RequireJS


Tweet

As a web developer, you certainly often started coding your JavaScript in a single file, and, as the code base gets larger and larger, it became really difficult to maintain. To solve this problem you can split your code in several files, add more script tags and use global variables to reach functions declared in other files. But this pollutes the global namespace and for each file an additional HTTP request consumes bandwidth, which slows down the loading time of the page. If this happened to you, you certainly understand that there is a strong need to organize our front-end code differently, particularly if we have to build large-scale web apps with thousands of lines of JavaScript. We need a new way to organize all this mess to make it easier to maintain. This new technique consists in using script loaders. Plenty of them are available on the web, but well focus on a very good one called RequireJS. In this step by step tutorial you will learn how to build a simple MVC (Model View Controller) app using RequireJS. You dont need any particular previous knowledge of script loading well see the basics together.

Introduction
What is RequireJS and why its awesome
RequireJS is an implementation of AMD (Asynchronous Module Definition), an API for declaring modules and loading them asynchronously on the fly when theyre needed. Its developed by James Burke, and it just reach the symbolic 1.0 version after 2 years of development. RequireJS can help you organize your code with modules and will manage for you the asynchronous and parallel downloads of your files. Since scripts are loaded only when needed and in parallel, it reduces the loading time of your page, which is great!

MVC for front-end?


MVC is a well known design pattern to organize server-side code and make it modular and sustainable. What about using it for front-end? Can we apply this design pattern to JavaScript? If youre just using JavaScript for animating, validating few forms or any simple treatment that doesnt require many lines of code (lets say less than 100 lines), there is no need to structure your files using MVC, and probably no need to use RequireJS either. However if youre building a rich web app with many different views, definitely yes!

http://verekia.com/requirejs/build-simple-client-side-mvc-app-require-js

1 / 16

Build a simple client-side MVC app with RequireJS | @verekia's blog

4/16/2013

The app well create


To illustrate how to organize your MVC code using RequireJS, well create a very simple app with 2 views: The first view will display a list of users (represented by a name attribute), The second view will allow you to add a user. This is how it will look like at the end:

The business logic is obviously super simple so you can focus on understanding whats really important here: structuring your code. And since its that simple, I strongly recommend that you really try to do it in parallel of reading this tutorial. It wont take long, and if you have never done modular programming or used RequireJS before, coding this example will really help you become a better programmer. Seriously, its worth it, you should do it.

HTML and CSS files


Here is the HTML markup well use for this example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <!doctype html> <html> <head> <meta charset="utf-8"> <title>A simple MVC structure</title> <link rel="stylesheet" href="css/style.css"> </head> <body> <div id="container"> <h1>My users</h1> <nav><a href="#list">List</a> - <a href="#add">Add</a></nav> <div id="app"></div> </div> <script data-main="js/main" src="js/require.js"></script> </body> </html>

The navigation in our app will be the links of the nav menu which will remain present on each page of the app, and all the magic of the MVC application will happen in the #app div. We also included RequireJS (which you can grab here) at the bottom of the body, and you can notice a special attribute on the script tag: data-main="js/main". The value passed to this attribute is used by RequireJS as the entry point of the entire application. Lets also add just a little bit of basic styling:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #container{ font-family:Calibri, Helvetica, serif; color:#444; width:200px; margin:100px auto 0; padding:30px; border:1px solid #ddd; background:#f6f6f6; -webkit-border-radius:4px; -moz-border-radius:4px; border-radius:4px; } h1, nav{ text-align:center; margin:0 0 20px; }

http://verekia.com/requirejs/build-simple-client-side-mvc-app-require-js

2 / 16

Build a simple client-side MVC app with RequireJS | @verekia's blog

4/16/2013

OOP reminder: What is a module?


In JavaScript Object-Oriented Programming, there is a very common design pattern called Module Pattern. It is used to encapsulate methods and attributes in objects (which are the modules) to avoid polluting the global namespace. It is also used to kind of simulate classes from other OOP languages like Java or PHP. This is how you would define a simple MyMath module in our main.js file:
1 2 3 4 5 6 7 8 9 10 11 12 var MyMath = (function(){ // Put your private variables and functions here return { // Here are the public methods add:function(a, b){ return a + b; } }; })(); console.log(MyMath.add(1, 2));

Public methods are declared using the object literal notation, which is not very convenient. You can alternatively use the Revealing Module Pattern, which returns private attributes and methods:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 var MyMath = (function(){ // With this pattern you can use the usual function notation: function add(a, b){ return a + b; } return { add:add // But don't forget to declare it in the returned object! }; })(); console.log(MyMath.add(1, 2));

I will be using the Revealing Module Pattern in the rest of this article.

RequireJS
Defining a module with RequireJS
In the last section we declared a module in a variable to call it later. This is just one way to declare modules. Were now going to see a (barely!) different method used by RequireJS. The purpose of RequireJS is to split our JavaScript files for a better maintainability, so lets create a MyMath.js file to define our MyMath module in the same folder as main.js:
1 2 3 4 5 6 7 8 9 10 define(function(){ function add(a, b){ return a + b; } return { add:add }; });

Instead of declaring a variable, we just put the module as a parameter of the define function. This function is provided by RequireJS and will make our module accessible from the outside.

Requiring a module from the main file


Lets go back to our main.js file. RequireJS provides a second function called require that were going to use to call our MyMath module. Here is what our main.js now looks like:
1 2 3 4 5 require(['MyMath'], function(MyMath){ console.log(MyMath.add(1, 2)); });

The call to MyMath is now wrapped in the require function, which takes 2 parameters:
http://verekia.com/requirejs/build-simple-client-side-mvc-app-require-js 3 / 16

Build a simple client-side MVC app with RequireJS | @verekia's blog

4/16/2013

An array of modules we want to load, declared with their path relative to the entry point (remember the data-main attribute in the HTML) and without the .js extension, A function to call once these dependencies are loaded. The modules will be passed as parameters of this function so you can simply name those parameters with the same modules names. You can now reload the page and congratulations! You just called a method from an other file! Yes, that was super easy and youre now ready for the big scary MVC architecture (which works exactly like the module definition you just did, so be sure youll be doing great!).

The MVC structure


Important note: In this tutorial, well mimic the server-side MVC in which 1 controller = 1 view. In front-end development, it is very common to have multiple views per controller. In this case views become visual components like buttons or fields. MVC JavaScript frameworks like Backbone use this different approach which is not the purpose of this article. My goal here is not to create a real life entire MVC framework, but simply illustrate how RequireJS works through a structure that many of you already know well.

Lets start with the part Im sure you love: creating all the folders and files of our project. We want to use Models to represent data, the business logic will be handled by Controllers, and those controllers will call specific Views to render pages. So guess what? We need 3 folders: Models, Controllers and Views. Considering our simple app case, well have 2 controllers, 2 views and 1 model. Our JavaScript folder now looks like this: Controllers AddController.js ListController.js Models User.js Views AddView.js ListView.js main.js require.js Got the structure ready? Great! Lets start implementing the simplest part: the Model.

The Model: User.js


In this example, a User will be a simple class with a name attribute:
1 2 3 4 5 6 7 8 define(function(){ function User(name){ this.name = name || 'Default name'; } return User; });

If we now come back to our main.js file, we can declare the dependency to User in the require method, and manually create a set of users for the purpose of this example:
1 2 3 4 5 6 7 8 9 10 11 12 require(['Models/User'], function(User){ var users = [new User('Barney'), new User('Cartman'), new User('Sheldon')]; for (var i = 0, len = users.length; i < len; i++){ console.log(users[i].name); } localStorage.users = JSON.stringify(users); });

http://verekia.com/requirejs/build-simple-client-side-mvc-app-require-js

4 / 16

Build a simple client-side MVC app with RequireJS | @verekia's blog

4/16/2013

We then serialize in JSON the users array and store it in the HTML5 local storage to make it accessible just like a database:

Note: JSON serialization with stringify and deserialization with parse need a polyfill to work in IE7 and inferiors. You should use Douglas Crockfords json2.js from his Github repository for this.

Displaying the users list


Its time to display those users in the app interface! Well have to work with ListController.js and ListView.js to do that. Those 2 components are obviously related, and theyll be linked someway. There are many ways we can do that, and to keep this example simple, here is what I suggest: The ListView will have a render method and our ListController will simply get the users from the local storage and call ListViews render method by passing the users as a parameter. So obviously, ListController needs ListView as a dependency. Just like with require, you can pass an array of dependencies to define if the module relies on other modules. Lets also create a start method (or any other name that makes sense to you like run or main), to put the main behavior of the controller in it:
1 2 3 4 5 6 7 8 9 10 11 define(['Views/ListView'], function(ListView){ function start(){ var users = JSON.parse(localStorage.users); ListView.render({users:users}); } return { start:start }; });

Here we deserialize the users from the local storage and pass it to render as an object. Now, all we have to do is implementing a render method in ListView.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 define(function(){ function render(parameters){ var appDiv = document.getElementById('app'); var users = parameters.users; var html = '<ul>'; for (var i = 0, len = users.length; i < len; i++){ html += '<li>' + users[i].name + '</li>'; } html += '</ul>'; appDiv.innerHTML = html; } return { render:render }; });

This method simply loops on our users to concatenate them in an HTML string we inject in the #app element.

Important : Using plain HTML in a JavaScript file like this is not an ideal solution, because its very hard to maintain. You should instead consider templating. Templates are an elegant way to insert data in HTML markup. Many very good templating systems are available on the web. You can for instance use jQuery-tmpl or Mustache.js. But this is beyond the scope of this article and it would add complexity to the current architecture, so I prefer keeping it simple.
http://verekia.com/requirejs/build-simple-client-side-mvc-app-require-js 5 / 16

Build a simple client-side MVC app with RequireJS | @verekia's blog

4/16/2013

Now, all we need to do is to run our ListController module. To do that lets declare it as a dependency of require in our main.js file, and call ListController.start():
1 2 3 4 5 6 7 8 9 10 require(['Models/User', 'Controllers/ListController'], function(User, ListController){ var users = [new User('Barney'), new User('Cartman'), new User('Sheldon')]; localStorage.users = JSON.stringify(users); ListController.start(); });

You can now refresh your page to get this wonderful list of users:

Woooaaaah, it works! Congratulations if you coded this too!

Note: For the moment, we can only manually declare the controller we want to run since we dont have any routing system yet. But well create a very simple one pretty soon, be patient!

Adding a user
We now want to be able to add users to our list. Well display a simple text input and a button, with an event handler when the button is clicked to add the user to the local storage. Lets start with AddController, just like we did in the previous section. This file will be pretty simple since we dont have any parameter to give to the view. Here is AddController.js:
1 2 3 4 5 6 7 8 9 10 define(['Views/AddView'], function(AddView){ function start(){ AddView.render(); } return { start:start }; });

And its corresponding view:


1 2 3 4 5 6 7 8 9 10 11 define(function(){ function render(parameters){ var appDiv = document.getElementById('app'); appDiv.innerHTML = '<input id="user-name" /><button id="add">Add this user</button>'; } return { render:render }; });

You can now declare AddController as a dependency in your main file and call its start method to successfully get the expected view:

http://verekia.com/requirejs/build-simple-client-side-mvc-app-require-js

6 / 16

Build a simple client-side MVC app with RequireJS | @verekia's blog

4/16/2013

But since we dont have any event bind on the button yet, this view is not very useful Lets work on that. I have a question for you: Where should we put the event logic for this event? In the view? In the controller? If we put it in the view it would be the right place to add the events listeners, but putting the business logic in a view would be a very bad practice. Putting the event logic in the controller seems to be a better idea, even if its not perfect because we dont want to see any divs ID in there, which belong to the view.

Note: The best way to go would be having event listeners in the view, which would call business logic methods located in the controller or in a new dedicated events module. This is really easy to do but it would make this example more complex and I dont want you to be lost. Feel free to try doing it for practicing!

As I said, lets put all the event logic in the controller. We can create a bindEvents function in AddController and call it after the view has finished rendering the HTML:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 define(['Views/AddView', 'Models/User'], function(AddView, User){ function start(){ AddView.render(); bindEvents(); } function bindEvents(){ document.getElementById('add').addEventListener('click', function(){ var users = JSON.parse(localStorage.users); var userName = document.getElementById('user-name').value; users.push(new User(userName)); localStorage.users = JSON.stringify(users); require(['Controllers/ListController'], function(ListController){ ListController.start(); }); }, false); } return { start:start }; });

In bindEvents, we simply add an event listener for clicks on the #add button (feel free to use your own function to deal with IEs attachEvent or just use jQuery). When the button is clicked, we get the users string from the local storage, deserialize it to get the array, push a new user with the name contained in the #user-name input field, and put the updated users array back to the local storage. After that we finally require the ListController to execute its start method so we can see the result:

Brilliant! Its time for you to take a break, youve done a very good job if youre still doing this example with me. You deserve a cup of coffee before we continue!

Navigation between views with routes


http://verekia.com/requirejs/build-simple-client-side-mvc-app-require-js 7 / 16

Build a simple client-side MVC app with RequireJS | @verekia's blog

4/16/2013

Okay back to work. Our little app is pretty cool but it really sucks that we still cannot navigate between views to add more users. What is missing is a routing system. If youve worked with server-side MVC frameworks before, youre probably familiar with this. Each URL leads to a different view. However here were client-side and its slightly different. JavaScript single page interfaces like this one use the hash of the URL to navigate between different parts of the app. In our case, we want to be able to reach the 2 different views when hitting those URLs: http://yourlocalhostpath/#list http://yourlocalhostpath/#add This will make each page of our app bookmarkable and easily reachable.

Note: Firefox, Chrome and Opera also have a pretty good support of HTML5 history management (pushState, popState, replaceState), which saves you from dealing with hashes.

Browsers compatibility and functioning


Managing history and hash navigation can be very painful if you need a good compatibility with old browsers. Depending on the browsers you aim to support here are different solution you can consider: Only the most advanced browsers: HTML5 history management, Most of the current browsers: HTML5 hashchange event, Old browsers: Simple manual monitoring of hash changes, Very old browsers: Manual monitoring + iframe hack. In our case we will do the simple manual monitoring, which is pretty easy to implement. All we need to do is checking if the hash changed every n milliseconds, and fire some function if a change is detected.

Note: A jQuery plugin is also available to manage this for you.

The routes and the main routing loop


Lets create a Router.js file next to main.js to manage the routing logic. In this file we need a way to declare our routes and the default one if none is specified in the URL. We can for instance use a simple array of route objects that contain a hash and the corresponding controller we want to load. We also need a defaultRoute if no hash is present in the URL:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 define(function(){ var routes = [{hash:'#list', controller:'ListController'}, {hash:'#add', controller:'AddController'}]; var defaultRoute = '#list'; var currentHash = ''; function startRouting(){ window.location.hash = window.location.hash || defaultRoute; setInterval(hashCheck, 100); } return { startRouting:startRouting }; });

When startRouting will be called, it will set the default hash value in the URL, and will start a repetition of calls to hashCheck that we havent implemented yet. The currentHash variable will be used to store the current value of the hash if a change is detected.

Check for hash changes


And here is hashCheck, the function called every 100 milliseconds:
1 function hashCheck(){ 2 if (window.location.hash != currentHash){ http://verekia.com/requirejs/build-simple-client-side-mvc-app-require-js

8 / 16

Build a simple client-side MVC app with RequireJS | @verekia's blog 3 for (var i = 0, currentRoute; currentRoute = routes[i++];){ 4 if (window.location.hash == currentRoute.hash) 5 loadController(currentRoute.controller); 6 } 7 currentHash = window.location.hash; 8 } 9 }

4/16/2013

hashCheck simply checks if the hash has changed compared to the currentHash, and if it matches one of the routes, calls loadController with the corresponding controller name.

Loading the right controller


Finally, loadController just performs a call to require to load the controllers module and execute its start function:
1 2 3 4 5 function loadController(controllerName){ require(['Controllers/' + controllerName], function(controller){ controller.start(); }); }

So the final Router.js file looks like this:


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 define(function(){ var routes = [{hash:'#list', controller:'ListController'}, {hash:'#add', controller:'AddController'}]; var defaultRoute = '#list'; var currentHash = ''; function startRouting(){ window.location.hash = window.location.hash || defaultRoute; setInterval(hashCheck, 100); } function hashCheck(){ if (window.location.hash != currentHash){ for (var i = 0, currentRoute; currentRoute = routes[i++];){ if (window.location.hash == currentRoute.hash) loadController(currentRoute.controller); } currentHash = window.location.hash; } } function loadController(controllerName){ require(['Controllers/' + controllerName], function(controller){ controller.start(); }); } return { startRouting:startRouting }; });

Using the new routing system


Now all we have to do is to require this module from our main file and call startRouting:
1 2 3 4 5 6 7 8 9 10 require(['Models/User', 'Router'], function(User, Router){ var users = [new User('Barney'), new User('Cartman'), new User('Sheldon')]; localStorage.users = JSON.stringify(users); Router.startRouting(); });

If we want to navigate in our app from a controller to another, we can just replace the current window.hash with the new controllers hash route. In our case we still manually load the ListController in AddController instead of using our new routing system:
1 2 3 require(['Controllers/ListController'], function(ListController){ ListController.start(); });

Lets replace those 3 lines with a simple hash update:


1 window.location.hash = '#list';

And this is it! Our app has now a functional routing system! You can navigate from a view to another, come back, do whatever you want with the hash in the URL, it will keep loading the right controller if it matches the routes declared in the router. Sweet! Here is an online demo of the app.
http://verekia.com/requirejs/build-simple-client-side-mvc-app-require-js 9 / 16

Build a simple client-side MVC app with RequireJS | @verekia's blog

4/16/2013

Conclusion
You can be proud of yourself, you built an entire MVC app without any framework! We just used RequireJS to link our files together, which is really the only mandatory tool to build something modular. So now what are the next steps? Well if you liked the minimalist Do It Yourself approach I had in this tutorial, you can enrich our little framework with new features as your app grows and has new technical needs. Here are some ideas of potential interesting next steps: Integrate a templating system, Create a small external library to put all what is not purely related to your app (like the routing system) to be able to reuse it on other projects, Define what a Model, a View and a Controller are with objects in this library, Create a new abstraction layer to deal with getting the data from various sources (RESTful APIs, localStorage, IndexedDB). This DIY approach is excellent to learn, but the current state of our framework is really not sufficient for real life projects at this point. If youre too lazy to implement the features listed above (and this list is absolutely not exhaustive!), you can also start learning how to use an existing MVC framework. The most popular are: Backbone JavaScriptMVC Sproutcore ExtJS Knockout I personally like Backbone because its lightweight (less than 5kb minified), so my next tutorial will be about mixing RequireJS and Backbone, which works pretty well! Follow @verekia for updates about this. You should also follow Addy Osmani and read his tutorials about large scale JavaScript applications and modular JavaScript, and James Burke the creator of RequireJS. Both are very good sources of information for building modular JavaScript apps. Addy Osmani also started a project called TodoMVC to compare how different MVC frameworks can be used to build the same simple web app, which is really helpful to choose the right framework for your needs. Thats all for today folks, thanks for reading! Follow @verekia 7,057 followers

This entry w as posted in RequireJS and tagged Addy Osmani, AMD, App , architecture, asynchronous, Asynchronous Module Definition , Backbone, Best practices, Client-side, Controller, data-main , define, demo , dependencies, DIY, events, example, Front-end , hash , hashchange, History, HTML5 , HTTP requests, James Burke, jQuery, jQuery-tmpl, JSON, Large-scale, local storage, Model, Modular, Module Pattern , Mustache, MVC, Object Oriented Programming , OOP , organize, parallel, parse, performance, Require, require.js, Revealing Module Pattern , Routes, Script , script loading , serialization , stringify, structure, Templates, Templating , TodoMVC, tutorial, View , Web App , webperf by Jonathan . Bookmark the permalink.
25 THOUGHTS ON BUILD A SIMPLE CLIENT-SIDE MVC APP WITH REQUIREJS

Julien Cabanes on November 4, 2011 at 1:11 AM said:

Great article, Im using RequireJS & Backbone every day and this is definitely a good way to go for large scale web app when you dont want/need big frameworks like Sencha/Sproutcore. About templating, for those wanting simple (micro) templates as AMD modules, Ive made a RequireJS plugin based on UnderscoreJSs templates https://github.com/ZeeAgency/requirejs-tpl
Reply

Jonathan on November 8, 2011 at 4:07 PM said:

Hi Julien,
http://verekia.com/requirejs/build-simple-client-side-mvc-app-require-js 10 / 16

Build a simple client-side MVC app with RequireJS | @verekia's blog

4/16/2013

I just tried your plugin and it works exactly as expected, so Im probably going to write a blog post about it soon. Thank you very much for your contribution to the community!
Reply

Steve on November 12, 2011 at 2:06 PM said:

Thanks very much for the tutorial. You say at the start that: Public methods are declared using the object literal notation, which is not very convenient. Can you explain why its not convenient? Is it to do with JS performance?
Reply

Jonathan on November 12, 2011 at 6:28 PM said:

Hi Steve, Its just about syntax and personal preferences, not performance. If you dont bother declaring your function with the object literal notation, you can use the simple Module Pattern. The Revealing Module Pattern is just here to add some sugar!
Reply

dzejkej on November 12, 2011 at 3:48 PM said:

Really great article! Cannot wait for more goodies from you :).
Reply

Todd W olfson on November 12, 2011 at 4:11 PM said:

I am actually already using this technique for building out my new UI. I like this a lot more than the current MVCs out there because it allows you to structure the design as you want. Currently, client side MVCs allow Views to talk directly to Models and I find that as a flawed pattern. This allows me to make my own as well as preserve the state with hashes.
Reply

http://verekia.com/requirejs/build-simple-client-side-mvc-app-require-js

11 / 16

Build a simple client-side MVC app with RequireJS | @verekia's blog

4/16/2013

Dante on November 13, 2011 at 12:37 AM said:

Great post. I have the same structure. Controllers are the ones who can talk to the View and Model. Views cant talk to Models. When it comes to events, you mentioned to define it in the view and it will call the business logic in the controller. Does it mean that when defining the View you need to pass a reference to the Controller?
Reply

Jonathan on November 13, 2011 at 5:29 PM said:

Hi Dante, Yes, thats how I would do it. You can for instance pass this as the second parameter of render in the controller (its probably the simplest way to do it), or implement a more generic solution to bind a controller to a view.
Reply

eric on December 6, 2011 at 10:20 PM said:

really great article! whats the alternatives of using setInterval() for routing? Is every n millisec. function-call a burden of performance?
Reply

Jonathan on December 13, 2011 at 8:16 AM said:

Hi Eric, You could use feature detection to know if the browser supports hashChange. If not use the setInterval stuff to make it work in IE7 and 6! Hope it helps :)
Reply

Subigre on December 7, 2011 at 6:27 AM said:

Great article but I have one question about integration of data access layer using REST services. In fact, I need to call different services in order to populate my view and need to render different parts of my view This is my implementation of start method but I do not know if it is good way or not:
1 2 3 4 5 6 7 8 9 10 11 12 13 define(["views/HomePageView", "models/ResourceSearchCriteria"], function(HomePageView, ResourceSearchCriteria) { .... function start() { HomePageView.render(); bindEvents(); var lastRecentlyAdded = new ResourceSearchCriteria(); lastRecentlyAdded.size = 5; lastRecentlyAdded.view = "medium"; resourceClient.findResourcesByCriteria(lastRecentlyAdded, { success: function(data) { HomePageView.displayResources($("#recentlyAddedBox .resourcelibrary-gallery-items"), data);

http://verekia.com/requirejs/build-simple-client-side-mvc-app-require-js

12 / 16

Build a simple client-side MVC app with RequireJS | @verekia's blog 14 } 15 } 16 ); 17 18 resourceClient.findTags(30, { 19 success: function(data) { 20 HomePageView.displayPopularTags(data); 21 } 22 } 23 ); 24 } 25 ...

4/16/2013

Reply

Jonathan on December 13, 2011 at 8:31 AM said:

Hi Subigre, It looks good to me! However you still have an ID / class selector in this controller, which should ideally be located in the view, just like you did for displayPopularTags. Good job! :)
Reply

Subigre on December 15, 2011 at 3:11 AM said:

Thanks for your response. I have an id selector because the method displayResources is used to display the last recentrly added and the last favorites. So it is just to reuse the same code. But, I am forced to use id/class selector in bindEnvents() method ? I have also another question is it better to pass an argument in start() method or save it in localeStroage and retrieve the value in the start() method ? (for instance if I have a SearchController which needs a SearchCriteria to perform a REST request and display the results). Regards
Reply

Stan on April 15, 2012 at 11:44 PM said:

Your article is very inspiring and pretty much explains most essential components for front-end MVC . Its very good introduction for people who want to step in some MVC frameworks like backbone. Hope you can keep writing and I will definitely go back
Reply

zziuni on May 30, 2012 at 7:47 PM said:

This post is very nice. :)


http://verekia.com/requirejs/build-simple-client-side-mvc-app-require-js 13 / 16

Build a simple client-side MVC app with RequireJS | @verekia's blog

4/16/2013

Im programmer in Korea. This is really useful to front-end developers. If you dont mind, can I translate your post in my blog? I will link to your post and write origin author is you. thanks~
Reply

Jonathan on May 30, 2012 at 9:30 PM said:

Sure no problem, go for it! :)


Reply

zziuni on June 8, 2012 at 6:22 AM said:

This articles korean version is here. :) http://zziuni.pe.kr/zziuni/587


Reply

Jonathan on June 8, 2012 at 2:32 PM said:

Awesome, thanks! :)
Reply

Joe on June 6, 2012 at 1:27 PM said:

Awesome post, helped me to understand the concepts quickly and easily.


Reply

Sudhakar on July 12, 2012 at 1:14 AM said:

Hi, Can you share the source code. Not sure why modules/methods in main.js are not called. It seems like i have pointed the script correctly but no luck
Reply

Jonathan on July 13, 2012 at 2:06 AM said:

Make sure youre using the http:// protocol and not just file:// (basically working on some localhost server), thats usually the issue people run through :)
Reply

http://verekia.com/requirejs/build-simple-client-side-mvc-app-require-js

14 / 16

Build a simple client-side MVC app with RequireJS | @verekia's blog

4/16/2013

viko21 on August 26, 2012 at 9:40 PM said:

A really nice tutorial excellent job my friend :)


Reply

Robert on October 21, 2012 at 2:06 PM said:

Hi Jonathan, My compliments to you for this concise and focused article. It has really helped me gain an understanding for MVC in javascript using requirejs. Your deliberate pruning down of off topic subjects like templating, or eventing using 3rd party libraries has allowed the MVC pattern to shine through. Regards, Robert.
Reply

Bob on October 28, 2012 at 3:09 AM said:

A nice tutorial that for once doesnt confuse things by relying on a library or framework. One point that I dont think is right is accessing the underlying storage mechanism directly from the controllers rather than through the model. The point of the model is to abstract/hide all the implementation details from the rest of the system. Adding get, set and add methods to the model is easy and makes the controller code even cleaner: the addcontroller just has: var userName = document.getElementById('user-name').value; console.log(userName); User.add(userName); It would be nice to see an update to this tutorial to use custom messaging between the view and controller and between the model and controller, as a sort of halfway house to using something like backbone which does this already. Thanks a lot Bob
Reply

Greg on December 12, 2012 at 3:04 AM said:

Really enjoyed this tutorial, and learnt a lot from you bringing bits and pieces together in a way that I can follow. It was also cool to see minimal use of libraries just the necessities. Thank you.
Reply
http://verekia.com/requirejs/build-simple-client-side-mvc-app-require-js 15 / 16

Build a simple client-side MVC app with RequireJS | @verekia's blog

4/16/2013

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

Name

*
Email

*
Website

Comment

Post Comment

http://verekia.com/requirejs/build-simple-client-side-mvc-app-require-js

16 / 16

Вам также может понравиться