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 tutorial, you will be able to build an app similar to the screenshot below.
Here is the HTML code for the app. Pretty straight 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, however, 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 in the above code, I have split it 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 set to null initially.
This property is basically set to 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.
Top comments (0)