1

I'm working on a project that uses the mvc 4 api combined with vanilla mvc 4 for routing and views. Because we're using the web api\json all the data calls are client driven so we're creating a lot of javascript code.

To help with this we decided to create one global prototype javascript object for handling the stuff that is shared and include one javascript file per view to handle all client side code for that specific view. ( I know this isn't optimal )

My problem is with the per view javascript files. Should we create a prototype object per view, or use closures?

Without an object per view we see a trend, we usually end up with a $(document).ready, event wire ups like $(document).on('click', ..., view models, and a bunch of old school functions. It seems like there should be a way to organize these areas into something better. I've seen some suggestions on SO on how to do so but they don't show how to incorporate that jQuery load, event wire ups, and view models. Does anyone have any suggestions, or possible a simple example?

Here are the areas we normally end up with

$(document).ready(function () {....

$(document).on('click', '.button', function(e) {.....

function FooBar(){.....

2 Answers 2

2

I don't think there are any hard and fast rules for how to best accomplish this - lots of ways to skin this cat.

But here's what I do: I tend to create one (or more if necessary) closure objects for the page. It'll have an initialize method contains the $().ready() handler which then does all the event handler hookups, and any other page global initialization that needs to happen.

Something like this:

(function() {
    function Page() {
        var me = this;            

        // plain properties
        this.prop = "value";

        // compiled templates
        this.template = HandleBars.compile($("#template1").html());

        this.intialize =  function () {
            $().ready(function () {                    
                $("#button1").click( me.button1Click );
                $("#field1").change( me.field1Change );
            });
        };
        this.button1Click = function () {
            alert("click");
            me.doSomething();
        };
        this.field1Change = function () {
            alert("change");
        },
        this.doSomething = function (parm) {
            alert("doSomething");
        }
    }        
    var page = new Page();
    page.intialize();
})();
Sign up to request clarification or add additional context in comments.

Comments

0

You should use one view model per view, and bind it to your view (html) with KnockoutJs, or any other resembling javascript library, which gives something like that (taken from there first example) :

view (html) :

​<html>
    <body>
        <p>First name: <input data-bind="value: firstName" /></p>
        <p>Last name: <input data-bind="value: lastName" /></p>
        <h2>Hello, <span data-bind="text: fullName"> </span>!</h2>       
    </body>
</html>​​​​​​​​​​​​​​

view model (javascript) :

var ViewModel = function(first, last) {
    this.firstName = ko.observable(first);
    this.lastName = ko.observable(last);

    this.fullName = ko.computed(function() {
        return this.firstName() + " " + this.lastName();
    }, this);
};

get data from server, and populate view model (and view, consequently)

$.get('/info/path/', function(data) {
    ko.applyBindings(new ViewModel(data.Planet, data.Earth));    
});

Of course, if you're last part isn't at the end of the page, you can put it in a document.ready, or any similar method.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.