Build A Simple App with JavaScript Object Literal Pattern

   Raja Tamil • Nov 17 • • 1 comments

In this JavaScript design pattern tutorial, you are going to learn how to build a simple web app using object Literal pattern.

At the end of this tutorials, you will be able to buid an app similar to the screenshot below.

Learn Javascript – How to write clean, well-organized and maintainable code with MVC and Object Literal Pattern

Here is the HTML code for the app and pretty staright forward

index.html

<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8">
    <title>Country List App with MVC</title>
    <link rel="stylesheet" href="style.css">
  </head>

  <body>
    <h1>Javascript MVC -  Object Literal Pattern</h1>
    <p> Country List App</p>
    <section class="wrap"> <!--container-->
      <!--leftview-->
      <div class="wrap-listview">
        <ul id="contry-list"></ul>
      </div>
        <!--rightview-->
        <div class="wrap-detailsview">
          <!--img-view-->
          <div class="img-view">
            <img src=""  width='300' id="country-flag"/>
          </div>
          <!--text-view-->
          <div class="text-view">
            <h2 id="country-name"></h2>
            <h3>Country</h3>
            <h2 id="country-capital"></h2>
          	<h3>Capital</h3>
           	<h2 id="country-language"></h2>
           	<h3>Language(s)</h3>
          </div>
        </div> <!-- /wrap-detailsview -->
      </section>  <!-- /container -->

      <script
        src="httpss://code.jquery.com/jquery-3.1.1.min.js"
        integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
        crossorigin="anonymous"></script>
        <script src="app.js"></script>
      </body>

</html>

style.css

/*=======reset===========*/

* {
  box-sizing:border-box;
}

body, h1, h2, h3 {
  margin:0;
  padding:0;
  font-family:Arial;
}

h1 {
  text-align: center;
  padding:20px;
  background:black;
  font-weight:300;
  color:#999;
  font-size:1.4em;
}

p {
  padding:5px 10px;
  background: orange;
  display:inline-block;
  margin:10px;
}

/*=======container===========*/

.wrap {
  padding:10px;
}

/* ======left-listView====== */

.wrap-listview, .img-view {
  min-width:250px;
  float:left;
}

.img-view {
   min-width:50px;
}


.text-view {
  margin-top:-4px;
  text-indent:10px;
}

.text-view h2 {
  font-size:1.3em;
  color:#666;
  font-weight:500;
}

.text-view h3 {
  font-size:1em;
  font-weight:300;
  color:#999;
}

ul {
  margin:0;
  padding:0;
}

li {
  border:1px solid #cccccc;
  border-bottom:none;
  list-style-type:none;
  padding:10px;
}

li:last-of-type {
   border-bottom:1px solid #cccccc;
}

li:hover, li:hover h2,  li:hover h3{
  cursor:pointer;
  background:#63c7fc;
  color:white;
}

.active {
  background:#63c7fc;
}

/* ========right-detailsView====== */

.wrap-detailsview {
  overflow:auto;
  padding-left:10px;
}

.wrap-detailsview .img-view{
  min-width:300px;
}

.wrap-detailsview .text-view {
  overflow:auto;
}

.wrap-detailsview .text-view  h2 {
  margin-top:5px;
}

.wrap-detailsview .text-view  h3 {
    margin-bottom:25px;
}

MVC – Model-View-Controller

MVC has been around since 1970 and is highly recommended by Apple and other companies. M – Model is responsible for all your data and business logic. V- View is responsible for your views (This is what the user actually sees and interacts with). C – Controller is a mediator that connects your Model and View.

Model and View should NEVER interact with each other. They can only talk through Controller. Now you understand the rules applying MVC in your application. I know it’s kind of vague and it will make more sense when we apply them in action.

Object Literal Pattern

var Human = {
   this.name = "Raja",

    speak : function() {
       return this.name + 'can speak';
    }
};

As you can see in the above example, you create a simple javascript object literal {} as you normally do but this time I added variables (properties) and functions (methods) into it, as one self-contained module. This is how we are going to organize our code using MVC (separation of concerns). One module for Model, One for Controller and one for View. You can add more than one in any of MVC buckets as your application gets bigger.

Now, you understand what’s MVC and Object Literal pattern. Let’s see the well-organized code below and will explain after:

(function(){

"use strict";

// ================ Model ======================
const countryList = {
    selectedItem:null,
    countries: [
      {name: 'Canada' , continent: "North America", flagUrl: 'https://flagpedia.net/data/flags/normal/ca.png', capital: "Ottawa", language: "English and French"},
      {name: 'USA' , continent: "North America", flagUrl: 'https://flagpedia.net/data/flags/normal/us.png', capital: "New York", language: "English"},
      {name: 'Singapore' , continent: "Asia", flagUrl: 'https://flagpedia.net/data/flags/normal/sg.png', capital: "Singapore", language: "English, Tamil, Malay, Mandarin"}
    ]
};


// ================ Controller ==================
const countryListApp = {

  init:function(){
    // set first index of an array object as a currentItem
    countryList.selectedItem = countryList.countries[0];



    // initialize two view - ListView (left) and DetailsView (right)
    countryListView.init();
    countryDetailsView.init();

  },

  getCountryList:function(){
    return countryList.countries;
  },

  getSelectedObject:function(){
    return countryList.selectedItem;
  },

  setSelectedObject:function(newSelectedObj){
    countryList.selectedItem = newSelectedObj;
  }

}

// ================ View ======================


// listview
const countryListView = {

    init:function(){
      this.cacheDom();
      this.render();
    },

    cacheDom:function(){
      // cacheDom
      this.$ul = $("#contry-list");
    },

    doClickListItem:function(selectedCountryObject){
      return function(){
        countryListApp.setSelectedObject(selectedCountryObject);
        countryDetailsView.render();
      }
    },

    render:function(){

      // temp vars
      let i, $li, $lichild;

      // add and give event listener at the same time
      const clArray = countryListApp.getCountryList();

      // ----- loop -------
      for(i = 0; i < clArray.length; i++) {
        console.log(clArray[i].name);

        // you could use templet for this
        $li = document.createElement("li");
        $li.innerHTML = `<div class="img-view">
                  <img src="${ clArray[i].flagUrl}"  width="50"/>
                </div>

                 <div class="text-view">
                       <h2>${ clArray[i].name}</h2>
                       <h3>${ clArray[i].continent}</h3>
                      </div>
                `;

        // adding event listener to li
         $li.addEventListener("click", this.doClickListItem(clArray[i]));

        // append li to ul
         this.$ul.append($li);

      }
      // ----- loop -------

    }

}

// detailsview
const countryDetailsView = {
  init:function(){
    this.cacheDOM();
    this.render();
  },

  cacheDOM:function(){
    this.$countryName = $('#country-name');
    this.$countryFlag = $('#country-flag');
    this.$countryCapital = $('#country-capital');
    this.$countryLanguage = $('#country-language');
  },

  render:function(){
    var selectedCountryObj = countryListApp.getSelectedObject();
    this.$countryName.html(selectedCountryObj.name);
    this.$countryFlag.attr("src", selectedCountryObj.flagUrl);
    this.$countryCapital.html(selectedCountryObj.capital);
    this.$countryLanguage.html(selectedCountryObj.language);
  }
}


// ================ Start Point ======================
countryListApp.init();


})();

As you can see the above code, I have split into three sections by adding comments: Model, View, and Controller.

Let’s take a look at the Model first:

countryList Object Literal that contains some data. In this case, we have one property named selectedItem is set to null initially.

This property is basically set the currently selected object when the user clicks a list item. This might be new to you but YES we are storing that information into Model, not in a click event that lives inside View.

We have another property named a countries array which contains all the country objects. That’s it for Model Object Literal.

Controller:

we have an another Object literal called countryListApp which is responsible for talking back and forth between Model and View(s). It has an init() method in which we are setting selectedItem (M) property to the first index of an array object.

Then, we are initializing two views (In this example I used two Views – one for left that shows all the countries and another view that shows a specific country information).  We have also a few helper methods such as getCountryList(), getSelectedObject(), setSelectedObject().

As you can see all of the help methods are either getters or setters. So that we do not have to set or get any information directly from Model to the View.

View:

countryListView Object Literal has init() method and it has two another methods cacheDOM() and render().

As you know, it’s more efficient to cache the DOM elements into variables then reuse them whenever we need ti. One the other hand, the reason for the render() method that we can call it to update the view whenever we change the data (Model).

This View is responsible for looping through the country array and creating the left country list view and bind the click event inside the loop and it has callback function doClickListItem() which is responsible for returning the currently clicked item’s object.

countryDetailsView Object literal has also init() function which is responsible for creating a county details view on the right.

As you can it’s pretty straight forward, it has cacheDOM() and render() methods very similar to the above view.

Finally, countryListApp.init() method will initialize the application to get everything going. That’s it!

You can find the full source code on Github.

Sharing is caring!