Building a class structure with a JavaScript MVC approach - best practices

I am looking to develop a JavaScript web application using the MVC-like principle. While my code is functional, I am facing challenges in implementing it correctly. I have created a global variable called APP where I store controllers, views, and other components. Both methods are effective, but the second option requires more code to achieve a similar outcome. I have heard about IIFE (http://en.wikipedia.org/wiki/Immediately-invoked_function_expression), but I am unsure of its advantages over my initial approach.

Is it not true that in the first method, everything is still contained within APP, thus avoiding pollution of the global namespace? Or should I opt for the second method for cleaner code?

What are the pros and cons of each approach?

Method 1:

<html>
<head>
<script type="text/javascript">
var APP = APP || {};
APP.homecontroller = {
    index: function(){
        APP.hometemplate.show();
    }
}
APP.hometemplate = {
    show: function(){
        var x=document.getElementById("content");
        x.innerHTML = "index content";
    }
}
function init(){
    APP.homecontroller.index();
}
</script>
</head>
<body>
<div id="content"></div>
<button onclick="init()">click to start</button>
</body>
</html>

Method 2:

<html>
<head>
<script type="text/javascript">
var APP = APP || {};
(function (APP) {
    APP.homecontroller = (function () {    
        function index() {
            APP.hometemplate.show();
        }
        return {
            index: index
        };
    }());
    APP.hometemplate = (function () {    
        function show() {
            var x=document.getElementById("content");
            x.innerHTML = "index content";
        }
        return {
            show: show
        };
    }());   
}(APP));

function init(){
    APP.homecontroller.index();
}
</script>
</head>
<body>
<div id="content"></div>
<button onclick="init()">click to start</button>
</body>
</html>

Answer №1

The initial example involves creating an APP object and defining public methods within it. While this approach prevents global namespace pollution by encapsulating all members inside APP, it may clutter the APP context itself with additional logic for each public function. Considering the potential size of the project, the second example offers greater robustness by allowing the definition of private methods within each "sub object".

In any case, it is crucial to keep all layers of MVC separated and facilitate communication through notifications.

Separate modules can be created for each layer, as different components of MVC often comprise various sub-mechanisms. For instance, in the Model layer, one could have observers that monitor changes in data and trigger updates in the view.

var Model = (function(){
    var data = [];

    var Observer = function(){
        // internal details..
        this.queue = []; 
    };

    var getData = function(){
        // some operations
        return data;
    };

    var addData = function(object){
        data.push(object); 
    }

    return {
        addData: addData,
        getData: getData,
        getObserver: new Observer();
    }
})();

Similarly, the View component manages the presentation layer and provides a refresh feature.

var Views = (function(){
    // implementation details..
    var parts = [];

    var refresh = function(){
        for (var i = 0; i < parts.length; i++){
            // render view..
        }
    }

    return {
        refresh: refresh
    }
})();

Lastly, the Controller serves as a intermediary between the model and controller.

As the project expands, incorporating namespaces and potentially an AMD framework to manage larger JS files might be beneficial. Ultimately, the scalability and capabilities of the project will determine the most suitable architecture. I hope this information proves helpful to you.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How can I detect a DOM element mutation based on a CSS selector, and if this is possible, how can it be accomplished?

Imagine there's a website with a specific HTML element. It seems that this element has the same class during the DOMContentLoaded event as it does during the load event. However, after the load event, this class (and possibly the ID and other HTML att ...

Trouble encountered while attempting to utilize @click="checkedInput" for displaying checkbox label in Vue.js?

const app = new Vue({ el: '#app', data: { checkedNames: [], checkedName: true, close: false }, methods: { uncheck(checkedName) { this.checkedNames = this.checkedNames.filter(name => name !== checkedName); }, ...

The building process of Ember encountered an error due to a problem with the broccoli builder

I'm currently working on an Ember project and facing an issue while trying to upgrade the version from 2.8 to 3.5.0. After changing the version and some dependencies, I encountered the following error : Error stack Even after attempting to resolve i ...

Is there a way for me to ensure that a response is only returned once a method call has been completed in

Seeking assistance with a Node.js application using Express. I am trying to create a REST endpoint that returns the response of an HTTP call. However, no matter what I attempt, it always returns before the HTTP request has completed. Can anyone provide g ...

Progress bar displaying during Ajax request

I'm currently working on an Ajax request that uploads images to the Imgur API and I want to implement a progress bar to show users the upload progress. I found some guidance in this thread, but it seems to display only 1 and stop working. This is the ...

Numerous perspectives of the TradingView Widget

I am facing an issue with the real-time chart component from tradingview.com. The chart is rendering twice at the start and every time I make a change in my code, it renders again. This results in multiple renders as shown in the image below. If anyone k ...

Utilizing CSS to Display a Variety of Colors within a Text String

Is it possible to style different words in a sentence with various colors using only CSS, without using the span element? For instance, how can I make the word "Red" appear in red, "Blue" in blue, and "Green" in green within an h1 tag? ...

Exporting variables in Angular's Ahead of Time (AoT) compiler is

I recently attempted to incorporate dynamic configuration into my project, following a guide I found in this insightful post. While everything functions smoothly with the JiT compiler, I encountered the following error when attempting to build using the A ...

Unexpected JSON token error occurs in jQuery when valid input is provided

I encountered an error that I'm struggling to pinpoint. The issue seems to be related to the presence of the ' symbol in the JSON data. After thoroughly checking, I am positive that the PHP function json_encode is not responsible for adding this ...

Dynamic Dropdown Validation During Form Submission

In the form, there are multiple rows displayed dynamically, each with a dropdown menu. The id for each dropdown is "ReasonCd#" where "#" increments from 0 based on the row number. By default, every dropdown has "Select Number" as the selected option, with ...

Eliminate repeated entries in a drop-down menu and display them with commas in between

I am working with a list that contains various language combinations: German to English German to Spanish German to Chinese German to French English to Spanish English to French English to Greek English to Portuguese Does anyone have suggestions on how ...

calls to res.send and res.render

I'm currently trying to determine if it's possible to use res.send(data) and res.render('reports') simultaneously in my code. To provide more details, when I navigate to '/reports', on the server side I am executing a REST ca ...

prevent parent jQuery functions from interfering with child function execution

I am facing an issue with conflicting jQuery functions between parent and child elements. The child function is a bootstrap function, while the parent is a custom function. The main objective is to limit the height of the parent div (refer to the code belo ...

Using Javascript, you can create a function that can disable or enable a text link based on

Here is the code snippet showcasing CSS styles and HTML elements: CSS: .enableLink{ font-family:Verdana, Geneva, sans-serif; font-size:12px; color:#069; padding-right:20px; text-decoration:underline; cursor:pointer; } .disableLink{ display:none; fon ...

What could be causing the jQuery code to not function properly when the left or right keys are pressed during mousedown?

Explanation of HTML code: <div class="wrap"> </div> Description of JavaScript code: $(document).ready(function() { $("body").mousedown(function(event) { switch (event.which) { case 1: alert('hel ...

Updating JSON data using fetch API

Hi everyone, I'm currently working on an email application and need help with implementing an archive button for each email. It seems that the function to change the archived status to true is being called, but for some reason, it's not making th ...

Having trouble getting this JavaScript query to function properly

The initial div in the code snippet below showcases the name of a university. When this name is clicked, it activates the function display_people(). This function is responsible for displaying or hiding the individuals associated with that university. The ...

The TypeScript inference feature is not functioning correctly

Consider the following definitions- I am confused why TypeScript fails to infer the types correctly. If you have a solution, please share! Important Notes: * Ensure that the "Strict Null Check" option is enabled. * The code includes c ...

Unexpected reduce output displayed by Vuex

In my Vuex store, I have two getters that calculate the itemCount and totalPrice like this: getters: { itemCount: state => state.lines.reduce((total,line)=> total + line.quantity,0), totalPrice: state => state.lines.reduce((total,line) = ...

The animation unexpectedly resets to 0 just before it begins

Currently, I am developing a coverflow image slider with jQuery animate. However, there are two issues that I am facing. Firstly, when the animation runs for the first time, it starts at `0` instead of `-500`. Secondly, after reaching the end and looping b ...