Tutorials

Tutorial List


Disqus for Google Sites


Immutable Data with Immutable.js

posted Dec 17, 2017, 7:03 PM by Benedictus Jason Reinhart   [ updated Dec 17, 2017, 7:06 PM ]

"Immutable list can be used as keys in Immutable.map tooIn object-oriented and functional programming, an immutable object (unchangeable object) is an object whose state cannot be modified after it is created. This is in contrast to a mutable object (changeable object), which can be modified after it is created. In some cases, an object is considered immutable even if some internally used attributes change but the object's state appears to be unchanging from an external point of view." (Wikipedia)

If you have read somewhere that immutability is important and such use cases are in your current JS project, Immutable.js is probably what you are looking for. The library itself does not have any dependencies, so you can just load it independently without any additional package managers such as npm, even though it is still recommended to use build tools such as webpack to ship Immutable.js.

Immutable.js can be included in your pages simply with a <script src="Immutable.js"></script> or using npm (npm install immutable).

In modern web applications, many operations are done asynchronously such as fetching data and event handling. These operations can be confusing as you cannot really predict when things will happen and what data should you expect within an operation. With immutable objects, things become predictable and consistent across your application.

Moreover, some Javascript data structure APIs are inconsistent. For example, Array.prototype.map and Array.prototype.filter in Javascript ES5 does not mutate the current array, but Array.prototype.sort, Array.prototype.shift and Array.prototype.unshift mutate the array. These kinds of inconsistencies may lead to bugs and confusion. To anticipate these we can use Immutable.js.

First, add Immutable.js to your page.
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.min.js"></script>

Then, start constructing an immutable array.
// using javascript plain array
var numbers = Immutable.List([1, 2, 5, 4, 3]);

Now, the inconsistencies in the plain Javascript array are gone, and all kind of operations on the array will result in a brand new array.
var sortedNumbers = numbers.sort();
console.log(numbers); // logs [1, 2, 5, 4, 3]
console.log(sortedNumbers); // logs [1, 2, 3, 4, 5]
console.log(numbers === sortedNumbers); // logs false
// while in plain Javascript the operations will result in numbers and sortedNumbers being the same object reference.

We can also try the same with filter and shift.
var oddNumbers = numbers.filter(n => n % 2 == 1);
var shiftedNumbers = numbers.shift();
console.log(numbers); // [1, 2, 3, 4, 5]
console.log(oddNumbers); // [1, 3, 5]
console.log(shiftedNumbers); // [2, 3, 4, 5]

Here, the numbers can be manipulated many times without altering the object (array). We filtered the numbers, then shifted it, but numbers will always be the same. In a component based app, sometimes there's a parent-child relationship between components, and usually the parent passes the data to the child. However, this may lead to bug in the parent component if the children try to alter the data passed from the parent, especially if the passed data is a reference such as objects and arrays. With immutable data, the parent should not be concerned if the data passed to the child will be manipulated or not.

We can also use Immutable.Map for objects and maps. The concept is the same as objects and maps, just a slightly different usage.
First, construct an Immutable.Map:
var person = Immutable.Map();
person.set('name', 'Bob');
person.set('age', 15);
person.set(Immutable.List([1, 2, 3], 'Immutable list can be used as keys in Immutable.map too');
console.log(person.get('name')); // "Bob"
console.log(person.get('age')); // 15
console.log(person.get(Immutable.List([1, 2, 3])); // "Immutable list can be used as keys in Immutable.map too"

Working with immutable objects might complicate things such as comparing 2 objects. As "mutating" an object in Immutable.js creates a new object, comparing with == and === will not work properly as you expected. Thus, Immutable.js provides us a utility function, is() which is a global function. Example:
var numbers = Immutable.List([1, 2, 5, 4, 3]);
var positiveNumbers = numbers.filter(n => n >= 0);
console.log(numbers == positiveNumbers); // false
console.log(numbers === positiveNumbers); // false
console.log(is(numbers, positiveNumbers)); // true

So, remember when using Immutable.js to compare with the is() function provided, not == or ===.

VR android using Unity & Google VR SDK

posted Dec 11, 2017, 2:23 AM by Tedy Junaidi

Introduction

VR Become one of favorite device for company profile or games. Unity as a big engine provide for many platform and one of them is VR for android. It so easy if you want to create VR if you want to use them without any event handler.

Start

I have a template to create a design. If you want to the model you can ask me.


So, I have a terrain and boat but water and tree I got from template package that unity had provide. And I have created animation that boat is round a lake.


Put GameObject as a child of boat. Put GameObject upper from boat. And put camera position is 0,0,0 and rotation is 0,0,0. It was start of camera position


Now we can run the application.

File à Build and Setting



Then you build the application and install in you mobile.

But, to develop this android application you need the sdk and the jdk that I have initialized on Edit à Preferences

 

Developer

You can develop this unity project using Google VR SDK for Unity.

On my era the latest version is 1.11000.

After that, you need to import Google VR SDK to your unity program. It will create Google VR on your program.

 

And go to prefabs and you will see GvrEditorEnvironment. Just drag it to the your hierarchy and put the GvrControllerMain on controller to your hierarchy.


Now you can run it. And you can move like in VR mode.

 

 

Onsen UI Framework

posted Dec 10, 2017, 11:39 PM by Tedy Junaidi   [ updated Dec 10, 2017, 11:40 PM ]

Introduction

Mobile is one of popular device. We can easy to create mobile website using Onsen.js that provide UI for android and it opensource.  Onsen.js can combine with angular.js, react.js or vue.js.

 On this tutorial we will create calculator for mobile website with css and js.

You can download all the component on https://github.com/OnsenUI/OnsenUI-dist/releases/tag/2.8.2.

I put folder css and js in lib folder. Now you can use the Onsen.

Getting Started

We Going to create main.html. On this main I put all css and js.

main.html

1.  <!DOCTYPE html>  

2.  <html>  

3.      <head>  

4.          <!-- All css and js from onsen -->  

5.          <link rel="stylesheet" href="lib/css/onsenui.css">  

6.              <link rel="stylesheet" href="lib/css/onsen-css-components.min.css">  

7.                  <script src="lib/js/onsenui.min.js"></script>  

8.                  <link rel="stylesheet" type="text/css" href="main.css">  

9.                  </head>  

10.                  <body>  

11.                      <!-- will make side slide -->  

12.                      <ons-splitter>  

13.                          <ons-splitter-side id="menu" side="left" width="220px" collapse swipeable>  

14.                              <ons-page>  

15.                                  <!-- Component of slide -->  

16.                                  <ons-list>  

17.                                      <ons-list-item onclick="fn.load('calculator.html')" tappable>  

18.            Calculator  

19.          </ons-list-item>  

20.                                      <ons-list-item onclick="fn.load('converterLength.html')" tappable>  

21.            Length Converter  

22.          </ons-list-item>  

23.                                  </ons-list>  

24.                              </ons-page>  

25.                          </ons-splitter-side>  

26.                          <!-- the main template  -->  

27.                          <ons-splitter-content id="content" page="calculator.html"></ons-splitter-content>  

28.                      </ons-splitter>  

29.                      <!-- the pages of onsen we use template -->  

30.                      <template id="calculator.html" style="height: 100vh">  

31.                          <ons-page>  

32.                              <ons-toolbar>  

33.                                  <div class="left">  

34.                                      <ons-toolbar-button onclick="fn.open()">  

35.                                          <ons-icon icon="md-menu"></ons-icon>  

36.                                      </ons-toolbar-button>  

37.                                  </div>  

38.                                  <div class="center">  

39.          Calculator  

40.        </div>  

41.                              </ons-toolbar>  

42.                              <ons-row style="height: 40%;" >  

43.                                  <div id="result"></div>  

44.                                  <div id="formula" class="scrollable"></div>  

45.                              </ons-row>  

46.                              <ons-row style="height: 60%">  

47.                                  <ons-row style=" height: 20%">  

48.                                      <ons-button  onclick="clean()" class="actionButton C-button" > C </ons-button>  

49.                                      <ons-button  onclick="operatorClick('%')" class="actionButton"> % </ons-button>  

50.                                      <ons-button  onclick="operatorClick('/')" class="actionButton"> / </ons-button>  

51.                                      <ons-button  onclick="operatorClick('x')" class="actionButton"> × </ons-button>  

52.                                  </ons-row>  

53.                                  <ons-row style=" height: 20%">  

54.                                      <ons-button onclick="type(7)"> 7 </ons-button>  

55.                                      <ons-button onclick="type(8)"> 8 </ons-button>  

56.                                      <ons-button onclick="type(9)"> 9 </ons-button>  

57.                                      <ons-button onclick="operatorClick('-')" class="actionButton"> - </ons-button>  

58.                                  </ons-row>  

59.                                  <ons-row style=" height: 20%">  

60.                                      <ons-button onclick="type(4)"> 4 </ons-button>  

61.                                      <ons-button onclick="type(5)"> 5 </ons-button>  

62.                                      <ons-button onclick="type(6)"> 6 </ons-button>  

63.                                      <ons-button onclick="operatorClick('+')" class="actionButton"> + </ons-button>  

64.                                  </ons-row>  

65.                                  <ons-row style=" height: 20%">  

66.                                      <ons-button onclick="type(1)"> 1 </ons-button>  

67.                                      <ons-button onclick="type(2)"> 2 </ons-button>  

68.                                      <ons-button onclick="type(3)"> 3 </ons-button>  

69.                                      <ons-button onclick="equal()" class="actionButton equal-button"> = </ons-button>  

70.                                  </ons-row>  

71.                                  <ons-row style=" height: 20%">  

72.                                      <ons-button onclick="type(0)"   

73.                    style="flex: 0.725"> 0 </ons-button>  

74.                                  </ons-row>  

75.                              </ons-row>  

76.                          </ons-page>  

77.                      </template>  

78.                  </body>  

79.                  <!-- js that i create -->  

80.                  <script  src="main.js" type="text/javascript"></script>  

81.                  <script  src="converterLength.js" type="text/javascript"></script>  

82.              </html>  

Main.css

1.  .button {  

2.    display: flex;  

3.    flex: 1;  

4.    align-items: center;  

5.    justify-content: center;  

6.    font-size: 20px;  

7.    border-radius: 0px;  

8.    background-color: white;  

9.    color:black;  

10.  }  

11.    

12.  ons-row {  

13.    background: #fffcf7;  

14.  }  

15.    

16.  .actionButton {  

17.    opacity: 1;  

18.  }  

19.    

20.  .screen {  

21.    font-size: 20px;  

22.    

23.  }  

24.    

25.  .C-button{  

26.    color:red !important;  

27.  }  

28.    

29.  .equal-button{  

30.    height: 200%;  

31.    background-color: #ff7200;  

32.    color: white !important;  

33.    font-size: 30px;  

34.  }  

35.    

36.  .button-action{  

37.    height: 200%;  

38.    font-size: 30px;  

39.  }  

40.    

41.  #result{  

42.    display: flex;  

43.    justify-content: center;  

44.    align-items: center;  

45.    height: 90%;  

46.    width: 100%;  

47.    font-size: 40px;  

48.    font-weight: bold;  

49.  }  

50.    

51.  #formula{  

52.    color: #7b7c7c;  

53.    width: 100%;  

54.    text-align: right;  

55.  }  

56.    

57.  .scrollable{  

58.    overflow: scroll;  

59.  }  

60.    

61.  ::-webkit-scrollbar {  

62.      width: 0px;  

63.      background: transparent; /* make scrollbar transparent */  

64.  }  

 

JS.

Attribute

Formula : will type in screen.

EditFormula : is editable formula its gonna use for user edit.

Operator : Will accept all sign

Operand: will accept all number.

Result; is result of the formula;

EditResult : is editable result from formula;

Operation/function

Type(number) : handle event number;

OperatorClick(type) : handle event sign.

Clean() : handle event to reset all;

 

Main.js

1.  window.fn = {};  

2.    

3.  window.fn.open = function() {  

4.    var menu = document.getElementById('menu');  

5.    menu.open();  

6.  };  

7.    

8.  window.fn.load = function(page) {  

9.      reset();  

10.    var content = document.getElementById('content');  

11.    var menu = document.getElementById('menu');  

12.    content.load(page)  

13.      .then(menu.close.bind(menu));  

14.  };  

15.    

16.  var formula;  

17.  var operator;  

18.  var operand;   

19.  var result;  

20.  var editFormula;  

21.  var editResult;  

22.  var lastOperator = "";  

23.    

24.    

25.  window.onload = function(){  

26.      reset = function reset(){  

27.          formula ="";  

28.          operator = "";  

29.          operand = "0";   

30.          result = 0;  

31.          editFormula = "0";  

32.          editResult = 0;  

33.          lastOperator = "";  

34.      }  

35.      init = function init(){  

36.          reset();  

37.          show();  

38.      }  

39.    

40.      showResult = function showResult(){  

41.          document.getElementById("result").innerHTML = editResult;  

42.      }  

43.      showFormula = function showFormula(){  

44.          document.getElementById("formula").innerHTML = formula + editFormula;  

45.      }  

46.    

47.      function checkCalculate(){  

48.          if(lastOperator == ""){  

49.              editResult = result + parseInt(operand);  

50.          }else if(lastOperator == "+"){  

51.              editResult = result + parseInt(operand);  

52.          }else if(lastOperator == "-"){  

53.              editResult = result - parseInt(operand);  

54.          }else if(lastOperator == "/"){  

55.              editResult = result / parseInt(operand);  

56.          }else if(lastOperator == "x"){  

57.              editResult = result * parseInt(operand);  

58.          }else if(lastOperator == "%"){  

59.              editResult = result % parseInt(operand);  

60.          }  

61.          showResult();  

62.      }  

63.      show = function show(){  

64.          showFormula();  

65.          checkCalculate();  

66.      }     

67.      init();  

68.    

69.        

70.  }  

71.    

72.    

73.  function type(number){  

74.      if(operand == ""){  

75.          formula +=  editFormula + " ";  

76.          lastOperator = operator;  

77.          operator = "";  

78.      }  

79.      operand += number+"";  

80.      editFormula = parseInt(operand)+"";  

81.      show();  

82.  }  

83.    

84.  function operatorClick(symbol){  

85.      if(operator == ""){  

86.          result = editResult;  

87.          formula += editFormula;  

88.          operand = "";  

89.      }  

90.      operator = symbol;  

91.      editFormula = " "+symbol;  

92.      showFormula();  

93.  }  

94.  function clean(){  

95.      reset();  

96.      show();  

97.  }  

98.    

99.  function equal(){  

100.     editFormula += " = " + editResult;  

101.     showFormula();  

102.     reset();  

103. }  

And I create for converter length to for understand why we use this application.

Converter.html

1.  <ons-page>  

2.      <ons-toolbar>  

3.          <div class="left">  

4.              <ons-toolbar-button onclick="fn.open()">  

5.                  <ons-icon icon="md-menu"></ons-icon>  

6.              </ons-toolbar-button>  

7.          </div>  

8.          <div class="center">  

9.          Converter Length  

10.        </div>  

11.      </ons-toolbar>  

12.      <ons-row style="height: 40%;" >  

13.          <ons-row style="height: 50%">  

14.              <ons-select id="sourceType" onchange="editSelects(this)">  

15.                  <option value="km">km</option>  

16.                  <option value="m">m</option>  

17.                  <option value="cm">cm</option>  

18.              </ons-select>  

19.              <div style="width: 100%; text-align: right; font-size: 40px" id="source"> 0 </div>  

20.          </ons-row>  

21.          <ons-row style="height: 50%">  

22.              <ons-select id="convertType" onchange="editSelects(this)">  

23.                  <option value="km">km</option>  

24.                  <option value="m" selected="true">m</option>  

25.                  <option value="cm">cm</option>  

26.              </ons-select>  

27.              <div style="width: 100%; text-align: right; font-size: 40px" id="convert"> 0 </div>  

28.          </ons-row>  

29.      </ons-row>  

30.      <ons-row style="height: 60%">  

31.          <ons-row style=" height: 25%">  

32.              <ons-button onclick="typeConvert(7)"> 7 </ons-button>  

33.              <ons-button onclick="typeConvert(8)"> 8 </ons-button>  

34.              <ons-button onclick="typeConvert(9)"> 9 </ons-button>  

35.              <ons-button onclick="clearConvert()" class="actionButton button-action C-button"> AC </ons-button>  

36.          </ons-row>  

37.          <ons-row style=" height: 25%; flex: 0.748">  

38.              <ons-button onclick="typeConvert(4)"> 4 </ons-button>  

39.              <ons-button onclick="typeConvert(5)"> 5 </ons-button>  

40.              <ons-button onclick="typeConvert(6)"> 6 </ons-button>  

41.          </ons-row>  

42.          <ons-row style=" height: 25%">  

43.              <ons-button onclick="typeConvert(1)"> 1 </ons-button>  

44.              <ons-button onclick="typeConvert(2)"> 2 </ons-button>  

45.              <ons-button onclick="typeConvert(3)"> 3 </ons-button>  

46.              <ons-button onclick="back()" class="actionButton button-action"><   

47.              </ons-button>  

48.          </ons-row>  

49.          <ons-row style=" height: 25%; flex: 0.748">  

50.              <ons-button onclick="typeConvert(0)"> 0 </ons-button>  

51.          </ons-row>  

52.      </ons-row>  

53.  </ons-page>  

Attribute

sourceText : attribute that handle number;

source : that will show on view

sourceType : will check unit of attribute

convert : handle the result.

convertType : handle the result type;

Method

convertToMeter() : return value based on type;

typeConvert () : handle input number user

back() : remove one text.

clearConvert(): reset

converterLength.js


1.   var sourceText;  

2.   var source;  

3.   var sourceType  

4.   var convert;  

5.   var convertType;  

6.     

7.     

8.     

9.   window.onload = function(){  

10.      init = function init(){  

11.          sourceText = "0";  

12.          sourceType = "km";  

13.          convertType = "m";  

14.          source = 0;  

15.          convert =0;  

16.      }  

17.      init();  

18.  }  

19.    

20.  function convertResult(number){  

21.      source = number;  

22.      convert = convertToMeter(sourceType) * source/convertToMeter(convertType);  

23.      showAll()  

24.    

25.  }  

26.    

27.  function showAll(){  

28.      document.getElementById("source").innerHTML = source;  

29.      document.getElementById("convert").innerHTML = convert;  

30.  }  

31.    

32.  function convertToMeter(type){  

33.      if(type == "km"){  

34.          return  1000;  

35.      }else if(type == "m"){  

36.          return 1;  

37.      }else if(type == "cm"){  

38.          return 1/100;  

39.      }  

40.      return 0;  

41.  }  

42.    

43.  function typeConvert(number){  

44.      sourceText += number+"";  

45.      convertResult(parseFloat(sourceText))  

46.  }  

47.    

48.  function editSelects(data) {  

49.    var id = data.id;  

50.    if(data.id == "sourceType"){  

51.      sourceType = data.value;  

52.    }else if(data.id == "convertType"){  

53.      convertType = data.value;  

54.    }  

55.    convertResult(parseFloat(sourceText));  

56.  }  

57.    

58.  function back(){  

59.      sourceText= sourceText.slice(0, -1);  

60.      if(sourceText.length  

61.  <1) sourceText = "0";  

62.      convertResult(parseFloat(sourceText))  

63.  }  

64.    

65.  function clearConvert(){  

66.      init();  

67.      convertResult(parseFloat(sourceText));  

68.  }  





Ruby on Rails Tutorial (Part 2)

posted Dec 10, 2017, 7:11 PM by Mario Viegash   [ updated Dec 11, 2017, 11:59 PM ]

This is the second part of Ruby on Rails, in this part we will learn about how to update and deleting product that inserted using code we have built in the first tutorial.

Update and Delete Product Component

We are going to create a component that we will use to update and deleting a new product.

“[Project Name]/app/views/product/index.html.erb”

1.   <h1>All Product</h1>  

2.     

3.   <table border="1" cellspacing="0" cellpadding="0" width="50%" style="text-align: center">  

4.       <tr>  

5.           <th>No</th>  

6.           <th>Product Name</th>  

7.           <th>Product Type</th>  

8.           <th>Product Stock</th>  

9.           <th>Product Price</th>  

10.         <th>Action</th>  

11.     </tr>  

12.     <!-- Product in here get from controller and how to loop the data ? We can use .each and set to variable -->  

13.     <% @product.each do |p| %>  

14.         <tr>  

15.             <!-- The data from the table taken using column name  -->  

16.             <td><%= p.id %></td>   

17.             <td><%= p.product_name %></td>  

18.             <td><%= p.product_type %></td>  

19.             <td><%= p.product_stock %></td>  

20.             <td><%= p.product_price %></td>  

21.             <td>  

22.                 <!-- Give button or link for redirect to update and delete -->  

23.                 <%= link_to :"Edit", controller: "product", action:"edit", id:p.id %>  

24.                 or  

25.                 <%= link_to :"Delete", controller: "product", action:"delete", id:p.id%>  

26.             </td>  

27.         </tr>  

28.     <% end %>  

29. </table>  

30. <br>  

31. <!-- We can use link_to for link to different html through controller -->  

32. <%= link_to "Add New Product", controller: "product", action:"new" %>  

“[Project Name]/app/views/product/edit.html.erb”

1.   <h1>Edt Product</h1>  

2.     

3.   <%= form_for @product, url:{action:"update"}, html:{class:"form"} do |p|%>  

4.       <p>  

5.           <%= p.label(:product_name)%>  

6.           <%= p.text_field :product_name%>  

7.       </p>  

8.     

9.       <p>  

10.         <%= p.label(:product_type)%>  

11.         <%= p.text_field :product_type%>  

12.     </p>  

13.   

14.     <p>  

15.         <%= p.label(:product_stock)%>  

16.         <%= p.text_field :product_stock%>  

17.     </p>  

18.   

19.     <p>  

20.         <%= p.label(:product_price)%>  

21.         <%= p.text_field :product_price%>  

22.     </p>  

23.   

24.     <p>  

25.         <%= p.submit "Submit" %>  

26.     </p>  

27.   

28.     <p>  

29.         <%= link_to :"Back", controller: "product", action:"index" %>  

30.     </p>  

31. <%end%>  

“[Project Name]/config /routes.rb”

1.   Rails.application.routes.draw do  

2.       

3.     get 'product/index'  

4.     

5.     get 'product/new'  

6.       

7.     # Modified to get product using id   

8.     get 'product/:id/edit':to => "product#edit":as => "edit"  

9.     

10.   get 'product/:id/delete':to => "product#delete":as => "delete"  

11.   

12.   # We use method post to send the data from html form to controller  

13.   post "create":to => "product#create"  

14.   

15.   # If we want to update product, i recommend you using patch because   

16.   # patch allows for both full and partial updates of a resource, and is more suited to how Rails updates resources  

17.   patch "product/:id":to => "product#update"  

18.   

19.   # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html  

20. end  

The Main Application

The main application will be used to update and delete our data, with the update and delete product component as its child.

“[Project Name]/app.controller/product_controller.rb”

1.   class ProductController < ApplicationController  

2.     def index  

3.       # to connect the table product we can call using the model  

4.       @product = Product.all # .all in here like query SELECT * FROM product  

5.     end  

6.     

7.     def new  

8.       @product = Product.new # .new in here to create a new data from product  

9.     end  

10.   

11.   def create  

12.     @product = Product.new(product_params)  

13.     if @product.save # .save in here for save the data and check the data saved or not   

14.       redirect_to action: "index"  

15.     else  

16.       redirect_to action: "new"  

17.     end  

18.   end  

19.   

20.   def edit  

21.     @product = Product.find(params[:id]) # params in here for get id from html form by clicking button update in index.html.erb  

22.   end  

23.   

24.   def update  

25.     @product = Product.find(params[:id])  

26.   

27.     if @product.update_attributes(product_params) # .update_attributes in here for update the data and check the data updated or not  

28.       redirect_to action: "index"  

29.     else  

30.       redirect_to action: "edit"  

31.     end  

32.   end  

33.   

34.   def delete  

35.     @product = Product.find(params[:id])   

36.       

37.     @product.destroy # .destory in here for delete the data  

38.     redirect_to action: "index"  

39.   end  

40.   

41.   private  

42.   

43.   # We create method private for just thic controller can access and this method use to get data from html form  

44.   def product_params  

45.     params.require(:product).permit(:product_name:product_type:product_stock:product_price)  

46.   end  

47. end  

The Result

The result from update product, example update product price Orange Water to 8000.

“localhost:3000/product/index”


“localhost:3000/product/edit”


“locahost:3000/product/index”


“localhost:8088/phpmyadmin”


The result from delete product, example delete product The Botol.

“Localhost:3000/product/index” -> Before


“Localhost:3000/product/index” -> After


“localhost:8088/phpmyadmin”


Tips and Trick CRUD

If you see this tutorial to slowly for create CRUD not effective, I recommend you using Scaffolding for create faster CRUD. Scaffolding in Ruby on Rails refers to the auto generation of simple set of a model, views and controller usually for a single table. How to use it? You can run command “rails generate scaffold NAME [field[:type][:index] field[:type][:index]]” and then you just run the application. 

Ruby on Rails Tutorial (Part 1)

posted Dec 8, 2017, 8:09 PM by Mario Viegash   [ updated Dec 11, 2017, 11:58 PM ]

Definition

Ruby on Rails, sometimes known as “RoR” or just “Rails”, is an open source framework for Web development in Ruby, an object-oriented programming (OOP) language like Perl and Python. Ruby is an open source, interpreted, object-oriented programming language created by Yukihiro Matsumoto, who chose the gemstone’s name to suggest “a jewel of a language”.

The principle difference between Ruby on Rails and other frameworks for development lies in the speed and ease of use that developer working within the environment enjoy. How to use Ruby on Rails? Follow this tutorial and you must be understand how to use it.

 

Setting Up and Installing

For use Ruby on Rails, I recommend you to download RubyInstallers (2.3.3) and Development Kit because it is have more documentation if you find in Google.com and really easy to use for CRUD in MySQL. Ok if you have already download the installer, follow this step to install Ruby, DevKit, and Rails.

Installing Ruby

  1.    Open the Ruby Installer and wait for the wizard from the installer.
  2.    After that, you can choose to “I accept the License” and click button “Next >”.
  3.    Next step, choose the destination for install and check 3 checkboxes like this photo.
             

           and then click button “Install”.

        4.   After that, you can click “Finish” for finish your install process and you can check you Ruby installed or not using command “ruby -v”

Setup Rubygems

  1.    For setup Ruby, run the self-extracting executable for your Development Kit and select to extract it in “C:\RubyDevKit” or beside your Ruby folder.
  2.     After the extract is complete, open a Ruby command prompt and navigate to “C:\RubyDevKit”
  3.    Run the following commands

ruby dk.rb init

ruby dk.rb install

          If the process finishes you can check your Rubygems installed or not using command “gem --version”.

Installing Rails

  1.   Open a Ruby command prompt and then run this command “gem install rails”.
  2.   If the process finishes you can check your rails installed or not using command “rails -v”.

 

The Application

Initialization

Create your project using command prompt and run “rails new [Project Name] -d mysql” and wait for the process into finish or you can try following this photo.


After that you can navigate you command prompt to the project and run “rails server” or “rails s” like this photo.


After that, open localhost:3000/ in your web browser and wait it until open like this photo.


If all went well, we can start to create simple web application example insert product.

Let’s start it, for the first open the project and check the database in “database.yml” or the path “[Project Name]/config/database.yml” and see the data. You can see the file have 3 databases and then you can create all the database into your phpmyadmin, if your phpmyadmin can’t to open  you can check your xampp already opened or not.

“[Project Name]/config/database.yml”

1.   default: &default  

2.     adapter: mysql2  

3.     encoding: utf8  

4.     pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>  

5.     username: root  

6.     password:  

7.     host: localhost  

8.     

9.   development:  

10.   <<: *default  

11.   database: tutorial_development # 1 database

12.  

13.   

14. test:  

15.   <<: *default  

16.   database: tutorial_test # 1 database

17.   

18. production:  

19.   <<: *default  

20.   database: tutorial_production # 1 database 

21.   username: tutorial  

22.   password: <%= ENV['TUTORIAL_DATABASE_PASSWORD'] %>  

“localhost:8088/phpmyadmin”


After that we can start to create model using command “rails generate model NAME [field[:type][:index] field[:type][:index]]” or you can try to following this photo.


And then you can check in you project will create product model in “[Project Name]/app/models/product.rb” and run command “rake db:migrate” to insert the table into phpmyadmin.


“localhost:8088/phpmyadmin”


Now we will to create controller, open the command prompt again and run command “rails generate controller NAME [action action] [options]” or you can try to follow this photo.


After that, you can check into the project will create controller, view and route in folder controllers and views or the path like this.

“[Project Name]/app/controllers/product_controller.rb”

1.   class ProductController < ApplicationController  

2.     def index  

3.     end  

4.     

5.     def new  

6.     end  

7.     

8.     def edit  

9.     end  

10. end  

“[Project Name]/app/views/product/index.html.erb”

1.   <h1>Product#index</h1>  

2.   <p>Find me in app/views/product/index.html.erb</p>  

“[Project Name]/config/routes.rb”

1.   Rails.application.routes.draw do  

2.     get 'product/index'  

3.     

4.     get 'product/new'  

5.     

6.     get 'product/edit'  

7.     

8.     # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html  

9.   end  

“localhost:3000/product/index”


Connect to Database

Now we will start in “index.html.erb” and “product_controller.rb” to connect the database and get data from table product.

“localhost:8088/phpmyadmin”


“[Project Name]/app/views/product/index.html.erb”

1.   <h1>All Product</h1>  

2.     

3.   <table border="1" cellspacing="0" cellpadding="0" width="50%" style="text-align: center">  

4.       <tr>  

5.           <th>No</th>  

6.           <th>Product Name</th>  

7.           <th>Product Type</th>  

8.           <th>Product Stock</th>  

9.           <th>Product Price</th>  

10.     </tr>  

11.     <!-- Product in here get from controller and how to loop the data ? We can use .each and set to variable -->  

12.     <% @product.each do |p| %>  

13.         <tr>  

14.             <!-- The data from the table taken using column name  -->  

15.             <td><%= p.id %></td>   

16.             <td><%= p.product_name %></td>  

17.             <td><%= p.product_type %></td>  

18.             <td><%= p.product_stock %></td>  

19.             <td><%= p.product_price %></td>  

20.         </tr>  

21.     <% end %>  

22. </table>  

23. <br>  

24. <!-- We can use link_to for link to different html through controller -->  

25. <%= link_to "Add New Product", controller: "product", action:"new" %>  

 “[Project Name]/app/controllers/product_controller.rb”

1.   class ProductController < ApplicationController  

2.     def index  

3.       # to connect the table product we can call using the model  

4.       @product = Product.all # .all in here like query SELECT * FROM product  

5.     end  

6.     

7.     def new  

8.     end  

9.     

10.   def edit  

11.   end  

12. end  

“localhost:3000/product/index”


Insert Product Component

We are going to create a component that we will use to insert a new product.

“[Project Name]/app/views/product/new.html.erb”

1.   <h1>New Product</h1>  

2.   <!-- We can use form_for to create form product for insert new product -->  

3.<%= form_for @product, url:{action:"create"}, html:{class:"form"} do |p|%> 

    <!-- url in here using for link to the route & html in here using to identifikasi this html using for form -->  

4.       <p>  

5.           <!-- We can create component html built-in method from rails  -->  

6.           <!-- And you must field it using column name, don't forget this is case sensitive -->  

7.           <%= p.label(:product_name)%>  

8.           <%= p.text_field :product_name%>  

9.       </p>  

10.   

11.     <p>  

12.         <%= p.label(:product_type)%>  

13.         <%= p.text_field :product_type%>  

14.     </p>  

15.   

16.     <p>  

17.         <%= p.label(:product_stock)%>  

18.         <%= p.text_field :product_stock%>  

19.     </p>  

20.   

21.     <p>  

22.         <%= p.label(:product_price)%>  

23.         <%= p.text_field :product_price%>  

24.     </p>  

25.   

26.     <p>  

27.         <%= p.submit "Submit" %>  

28.     </p>  

29.   

30.     <p>  

31.         <%= link_to :"Back", controller: "product", action:"index" %>  

32.     </p>  

33. <%end%>  

“[Project Name]/config/routes.rb”

1.   Rails.application.routes.draw do  

2.       

3.     get 'product/index'  

4.     

5.     get 'product/new'  

6.       

7.     get 'product/edit'  

8.     

9.     # We use method post to send the data from html form to controller  

10.   post "create":to => "product#create"  

11.   

12.   # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html  

13. end 

“[Project Name]/app/controller/product_controller.rb”

1.   class ProductController < ApplicationController  

2.     def index  

3.       # to connect the table product we can call using the model  

4.       @product = Product.all # .all in here like query SELECT * FROM product  

5.     end  

6.     

7.     def new  

8.       @product = Product.new # .new in here to create a new data from product  

9.     end  

10.   

11.   def edit  

12.   end  

13. end  

“localhost:3000/product/new”


The Main Application

The main application will be used to store our data, with the insert product component as its child.

“[Project Name]/app/controller/product_controller.rb”

1.   class ProductController < ApplicationController  

2.     def index  

3.       # to connect the table product we can call using the model  

4.       @product = Product.all # .all in here like query SELECT * FROM product  

5.     end  

6.     

7.     def new  

8.       @product = Product.new # .new in here to create a new data from product  

9.     end  

10.   

11.   def create  

12.     @product = Product.new(product_params)  

13.     if @product.save # .save in here to check the data saved or not   

14.       redirect_to action: "index"  

15.     else  

16.       redirect_to action: "new"  

17.     end  

18.   end  

19.   

20.   def edit  

21.   end  

22.   

23.   private  

24.   

25.   # We create method private for just thic controller can access and this method use to get data from html form  

26.   def product_params  

27.     params.require(:product).permit(:product_name:product_type:product_stock:product_price)  

28.   end  

29. end  

The Result

“localhost:3000/product/new”


“localhost:3000/product/index”



“localhost:8088/phpmyadmin”



 

CSS Variables (CSS Custom Properties)

posted Nov 22, 2017, 4:51 AM by Benedictus Jason Reinhart

Tracing way back to early 2000s, theming a website requires additional complex tools and most are not really lightweight, considering internet accessibility back in 2000s. However since Chrome 49 and Firefox 31, we can use the var() function of CSS and define our custom property. This is especially useful for theming and changing styles dynamically.

For example, if you ever used SASS or LESS before, you can define the main color (primary color) and secondary color of a site with their specific variable syntax. They are great, but they are limited and static, meaning after compiling SASS or LESS to CSS files, they cannot be changed anymore until the next compilation. Imagine you can change your site's primary color dynamically without additional libraries, purely supported by the browser.

Reusability and dynamic are the reason why CSS custom property is awesome. For example, we have a primary color of lightsalmon and a secondary color of lightgreen, we can define our CSS like this:
.button-primary {
background: lightsalmon;
}
.button-secondary {
background: lightgreen;
}
.container {
background: lightsalmon;
}
.bg-secondary {
background: lightgreen;
}
.text-primary {
background: lightsalmon;
}
.text-secondary {
background: lightgreen;
}

However, this can break our site if our brand decide to change its primary and secondary color. If we ever have to revamp the color of the site, we have to change every style of our classes, which is a repetitive work and of course, boring. With CSS custom properties, we can do it better like this:
 :root {
--primary-color: lightsalmon;
--secondary-color: lightgreen;
}
.button-primary {
background: var(--primary-color);
}
.button-secondary {
background: var(--secondary-color);
}
.container {
background: var(--primary-color);
}
.bg-secondary {
background: var(--secondary-color);
}
.text-primary {
background: var(--primary-color);
}
.text-secondary {
background: var(--secondary-color);
}

You don't have to define the variables in the :root. It's just the :root in HTML represents the <html> element and is identical to the selector html, except that its specificity is higher. Now maintaining your CSS is easier as the colors are grouped and reused.

Other use case of the custom property is when you want to customize styles in media query. For example, we have a base padding of 15px in desktop resolution for many components:
.container {
padding: 15px;
}
.card {
padding: 15px;
box-shadow: 1px 1px 1px #444;
}
.box {
padding: 15px;
}
.panel {
padding: 15px;
}

@media (max-width: 768px) {
.container {
padding: 10px;
}
.card {
padding: 10px;
}
.box {
padding: 10px;
}
.panel {
padding: 10px;
}
}

Such a repetitive style declaration. With CSS custom property, we can compact the code into:
:root {
--base-padding: 15px;
}
.container {
padding: var(--base-padding);
}
.card {
padding: var(--base-padding);
box-shadow: 1px 1px 1px #444;
}
.box {
padding: var(--base-padding);
}
.panel {
padding: var(--base-padding);
}

@media (max-width: 768px) {
:root {
--base-padding: 10px;
}
}

Very elegant code, maintainable and not repetitive. Want to change the base padding somehow? Just change it in :root. Different base padding in different resolution? Use the media query to change the custom property in :root.
You can also change the custom property in Javascript. For example, if we want to make a button that increases the base padding:
var button = document.getElementById('#button');
var currentPadding = 15;
button.onclick = function() {
var rootStyle = document.documentElement.style;
currentPadding += 2;
rootStyle.setProperty('--base-padding', currentPadding + 'px');
}

CSS custom property also support fallback or default values, which is used whenever you haven't declared the custom property.
:root {
--base-padding: 15px;
}
.container {
padding: var(--base-padding, 1em);
}
.card {
padding: var(--base-padding, 1em);
box-shadow: 1px 1px 1px #444;
}
.box {
padding: var(--base-padding, 1em);
}
.panel {
padding: var(--base-padding, 2em);
}

@media (max-width: 768px) {
:root {
--base-padding: 10px;
}
}

[Javascript] Easy AJAX Call Using Browser's Fetch API

posted Nov 21, 2017, 3:56 AM by Benedictus Jason Reinhart

Fetch API allows you as developer to make an AJAX call (or XMLHttpRequest) natively in browser without additional libraries like jQuery and such. The main advantage of using Fetch API is that it uses the Promise feature, avoiding dependencies and callback hell. If you are not familiar with promises, you can learn about it here.

The Fetch API is pretty accessible with 78% global support according to caniuse. Moreover, it helps you as developer to implement AJAX call as many libraries implement them differently. To better support old browsers, there’s a fetch polyfill library here along with the promise polyfill library here.

 The syntax is pretty straightforward:

fetch(url, options)

The function will return a promise which you can chain using then method, for example:

fetch('https://jsonplaceholder.typicode.com/posts/1')

.then(r => r.json())

.then(r => console.log(r.title))

By default, the fetch API will make a HTTP GET request to the provided URL. The .json() method will parse the response body into a JSON object. The headers are automatically set by the browser such as Accept (default is *), Content-Type (default is text/html), etc.

In real use case, you won’t be messing with only GET request and only text/html content type. In that case, the second parameter options plays in. You can specify the request method, most headers (some headers are restricted such as Origin), mode (CORS or same-origin), credentials, etc.

For example, if we want to make a new post:

fetch('https://jsonplaceholder.typicode.com/posts', {

       method: 'post',

       headers: {

              'Content-Type': 'application/json',

              Accept: 'application/json',

       },

       body: JSON.stringify({

              title: 'Hello world',

              body: 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit',

}),

}).then(r => {

       alert('Create post success!');

});

Here, we specify the request method to POST, set the headers, and put the data to be sent in the body property. If the server recognizes application/json content type and we sure that the response is also application/json, then this will work for sure. 

In authorized environment, you might want to call an API by also sending the default credentials, usually using session cookie. By default, the Fetch API does not send your credentials like session cookie (such as .PHPSESSIONID and .ASPXAUTH). This means that whenever you request something to the server, it cannot recognize who you are, resulting in an anonymous and/or unauthorized call. To solve this, add the credentials property to the options parameter.

fetch('https://jsonplaceholder.typicode.com/posts', {

       method: 'post',

       credentials: 'include',

       headers: {

              'Content-Type': 'application/json',

              Accept: 'application/json',

       },

       body: JSON.stringify({

              title: 'Hello world',

              body: 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit',

}),

}).then(r => {

       alert('Create post success!');

});

 

The credentials property accepts 3 kind of values:

·         include à session cookie will be sent to EVERY kind of request regardless of origin.

·         same-origin à credentials only sent with the same origin policy.

·         omit à no credentials are sent.

Starting with Chrome 50, you can also put FederatedCredential and PasswordCredential instances to credentials property.

Vue Js Tutorial

posted Mar 30, 2017, 4:24 AM by Denny Angkasa

Setting Up and Installing Dependencies

 

Create a folder that we are going to use for our project. Open a command window inside the folder and use the command “npm init” to create a package.json file for our project.

 

Now we are going to install the dependencies for our project. Use the command

npm install vue vue-resource bootstrap --save

 

Now our dependencies should be installed and we are ready to code our application.

 

The Application

 

Initialization

Create the files index.html and app.js. We will use index.html as our view and app.js as the base for our Vue application. The goal of this tutorial is to help readers understand Vue.js basics, data binding, and components. By the end of the tutorial we would have a very simple application for product management.

 

Let’s start with index.html. The base of our Vue application is going to be very simple. We are going to use a div with a specific ID and bind it to our Vue Javascript. Let’s use a div with id=products for that.

1.   <!DOCTYPE html>  

2.   <html>  

3.   <head>  

4.       <title>Vue Test</title>  

5.       <link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css">  

6.   </head>  

7.   <body>  

8.       <div id="products">  

9.         

10.     </div>  

11.   

12.     <script src="node_modules/vue/dist/vue.js"></script>  

13.     <script src="node_modules/vue-resource/dist/vue-resource.js"></script>  

14.     <script src="app.js"></script>  

15. </body>  

16. </html>  

 

Hello World

Now we’re going to app.js to set up our Vue Application.

1.   new Vue({  

2.       el: '#products',  

3.       data: {  

4.           text: 'Hello World'  

5.       }  

6.   });  

 

As you may have noticed, we initialize the application by creating a new Vue object. The el attribute refers to the id of element in the view, and data attribute is used to contain the data for our application. In the above example, we have a data with the name of “text” and the value of “Hello World”. Now we are going to use the text data in our view. To print out data in view is a very simple task. We use the syntax {{ DATA_NAME }}.

1.   <!DOCTYPE html>  

2.   <html>  

3.   <head>  

4.       <title>Vue Test</title>  

5.       <link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css">  

6.   </head>  

7.   <body>  

8.       <div id="products">  

9.           {{text}}  

10.     </div>  

11.   

12.     <script src="node_modules/vue/dist/vue.js"></script>  

13.     <script src="node_modules/vue-resource/dist/vue-resource.js"></script>  

14.     <script src="app2.js"></script>  

15. </body>  

16. </html>  

 

 

Components

We can use components for reusability and modularize our application. Let’s try creating a component.

1.   Vue.component('test-component', {  

2.       props: ['text'],  

3.       template: `  

4.           <div>  

5.               {{text}}  

6.           </div>  

7.       `  

8.   });  

9.     

10. new Vue({  

11.     el: '#products',  

12.     data: {  

13.         text: 'Hello World'  

14.     }  

15. });  

 

And use it in our view

1.   <!DOCTYPE html>  

2.   <html>  

3.   <head>  

4.       <title>Vue Test</title>  

5.       <link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css">  

6.   </head>  

7.   <body>  

8.       <div id="products">  

9.           <test-component :text="text">  

10.         </test-component>  

11.     </div>  

12.   

13.     <script src="node_modules/vue/dist/vue.js"></script>  

14.     <script src="node_modules/vue-resource/dist/vue-resource.js"></script>  

15.     <script src="app2.js"></script>  

16. </body>  

17. </html>  

 

As you may notice, we passed the text property to the child component, and use it as output in the child component.

 

Insert Product Component

We are going to create a component that we will use to insert a new product.

1.   Vue.component('insert-product-component', {  

2.       props: ['products'],  

3.       data: function() {  

4.           return {  

5.               previousId: 3,  

6.               product: {  

7.                   name: '',  

8.                   stock: 0,  

9.                   price: 0  

10.             }  

11.         };  

12.     },  

13.     methods: {  

14.         addProduct: function() {  

15.             this.product.id = ++this.previousId;  

16.             this.product.price = parseInt(this.product.price);  

17.             this.product.stock = parseInt(this.product.stock);  

18.             this.products.push(this.product);  

19.   

20.             this.product = {  

21.                 name: '',  

22.                 price: 0,  

23.                 stock: 0  

24.             };  

25.         }  

26.     },  

27.     template: `  

28.         <div class="container">  

29.             <form v-on:submit.prevent="addProduct">  

30.                 <div class="page-header">  

31.                     <h1>Insert</h1>  

32.                 </div>  

33.                 <div class="form-group">  

34.                     <label>Name</label>  

35.                     <input type="text" class="form-control" v-model="product.name"/>  

36.                 </div>  

37.                 <div class="form-group">  

38.                     <label>Price</label>  

39.                     <input type="number" class="form-control" min="0" v-model="product.price"/>  

40.                 </div>  

41.                 <div class="form-group">  

42.                     <label>Stock</label>  

43.                     <input type="number" class="form-control" min="0" v-model="product.stock"/>  

44.                 </div>  

45.                 <button class="btn btn-primary">Save</button>  

46.             </form>  

47.         </div>  

48.     `  

49. });  

 

The Main Vue Application

The main Vue application will be used to store our data, with the insert product component as its child. We are also going to put in 3 dummy data as starting data.

1.   new Vue({  

2.       el: '#products',  

3.       data: {  

4.           product: {  

5.               name: '',  

6.               price: 0,  

7.               stock: 0  

8.           },  

9.           products: []  

10.     },  

11.     mounted: function() {  

12.         this.fetchProducts();  

13.     },  

14.     methods: {  

15.         fetchProducts: function() {  

16.             var products = [  

17.                 {  

18.                     id: 1,  

19.                     name: 'Test',  

20.                     price: 15000,  

21.                     stock: 50  

22.                 },  

23.                 {  

24.                     id: 2,  

25.                     name: 'Test2',  

26.                     price: 13000,  

27.                     stock: 67  

28.                 },  

29.                 {  

30.                     id: 3,  

31.                     name: 'Test3',  

32.                     price: 25000,  

33.                     stock: 40  

34.                 }  

35.             ];  

36.   

37.             this.$set(this'products', products);  

38.         }  

39.     }  

40. });  

 

Now we will adjust our index.html

1.   <!DOCTYPE html>  

2.   <html>  

3.   <head>  

4.       <title>Vue Test</title>  

5.       <link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css">  

6.   </head>  

7.   <body>  

8.       <div id="products">  

9.           <insert-product-component :products="products">  

10.         </insert-product-component>  

11.         <table class="table table-striped table-hover" style="margin-top: 20px;">  

12.             <tr>  

13.                 <th>Id</th>  

14.                 <th>Name</th>  

15.                 <th>Price</th>  

16.                 <th>Stock</th>  

17.             </tr>  

18.             <tr v-for="product in products">  

19.                 <td>{{ product.id }}</td>  

20.                 <td>{{ product.name }}</td>  

21.                 <td>{{ product.price }}</td>  

22.                 <td>{{ product.stock }}</td>  

23.             </tr>  

24.         </table>  

25.     </div>  

26.   

27.     <script src="node_modules/vue/dist/vue.js"></script>  

28.     <script src="node_modules/vue-resource/dist/vue-resource.js"></script>  

29.     <script src="app.js"></script>  

30. </body>  

31. </html>  

 

The Result



[JavaScript] MVVM Implementation Using Knockout.js

posted Mar 15, 2017, 5:37 AM by Benedictus Jason Reinhart

Introduction

MVVM consists of 3 layers, the Model, View and ViewModel. The model layer represents the data of your application, the view layer represents the UI (user interface) or what users see on your application, and lastly the view model does not represent anything in particular, it handles your data binding (model) to your application view. Designing application using the MVVM pattern is great when your application requirement is not really big. Binding data model to your view makes your code more readable, but does not scale really well on a bigger system. It becomes more confusing on which bind on what. It also is an "overkill" for a simple UI or application operation logic when the operation can actually be executed in a simple steps.

Knockout.js is a simple library that helps developers to build a simple page with MVVM structure. With only 25 kb (min+gz), Knockout.js able to do data bindings to make your UI automatically refreshes as your data change while maintaining dependencies by tracking it with chains of relationships between model data. Additionally, Knockout.js does not have any dependency. That means you can use Knockout.js without worrying if it will interfere with your existing libraries, e.g. using Knockout.js with jQuery.

You can download Knockout.js in their official site.

Getting Started

Suppose that we want to build a "Product page" with a shopping cart in it. In order to show the products, we need to pull the data from a server, usually using AJAX request. Knockout.js does not handle these kind of things as it is not the part of the presentation layer, so you probably want to handle these tasks using things like Fetch, jQuery AJAX, etc. The main focus of using Knockout is building your view to present data and while handling any changes that may occur while user interacts with your application.

To start, let's build a simple plain HTML page. Make sure you have downloaded Knockout.js (or install it via npm, whichever way you like the most).
index.html:
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.     <title></title>  
  5.     <script src="knockout-3.4.1.js"></script>  
  6.     <script src="script.js"></script>  
  7. </head>  
  8. <body>  
  9.     <div align="center">  
  10.         <h1>MVVM Shop</h1>  
  11.         <table border="1" cellspacing="0" cellpadding="10">  
  12.             <tr>  
  13.                 <th>Product Name</th>  
  14.                 <th>Product Price</th>  
  15.                 <th>Add to Cart</th>  
  16.             </tr>  
  17.         </table>  
  18.   
  19.         <br><br>  
  20.   
  21.         <h2>My Cart</h2>  
  22.         <table border="1" cellspacing="0" cellpadding="5">  
  23.             <tr>  
  24.                 <th>Name</th>  
  25.                 <th>Price</th>  
  26.                 <th>Quantity</th>  
  27.                 <th>Subtotal</th>  
  28.                 <th>Action</th>  
  29.             </tr>  
  30.             <tr>  
  31.                 <td colspan="3" align="right"><b>Grand Total</b></td>  
  32.                 <td colspan="1" align="right"></td>  
  33.                 <td></td>  
  34.             </tr>  
  35.             <tr>  
  36.                 <td colspan="5" align="center">  
  37.                     <button>Checkout / Clear Cart</button>  
  38.                 </td>  
  39.             </tr>  
  40.         </table>  
  41.     </div>  
  42. </body>  
  43. </html>  


First, we load the Knockout.js library and a script file for our code. We create a table as a container for our products and a cart to store items that users choose. User can choose the quantity of an item they wish to add to the cart, and the cart will dynamically refresh as the user interacts with it. The checkout button is used to clear the cart only, nothing special will happen (no sending data, as it is not our main topic here).

Moving to script.js, we will code everything in our onload function to make sure our DOM is ready. Here, I make a Product "class" to wrap what each of our product has.
  1. window.onload = function() {  
  2.     var Product = function Product(name, price) {  
  3.         this.name = name;  
  4.         this.price = price;  
  5.         this.quantity = 0;  
  6.     }  


We will use the quantity attribute to keep track the number of the product inserted into the cart. 

Bindings

In Knockout.js, we need to make a ViewModel (the VM in MVVM) as the representation of our UI model. The view model will hold our product data, which we will later bind it to the UI using data-bind attribute in HTML and let Knockout.js do the rest. Add the ViewModel, then immediately bind it to our view:
  1. var ViewModel = function ViewModel(name) {    
  2.     this.products = ko.observableArray([    
  3.         new Product('Potato', 50),    
  4.         new Product('Carrot', 40),    
  5.         new Product('Broccoli', 55),    
  6.         new Product('Tomato', 53),    
  7.     ]);    
  8. };    
  9.   
  10. var viewModel = new ViewModel();  
  11. ko.applyBindings(viewModel);  

Our ViewModel will have products (an observable array, special type that lets Knockout.js to bind data to view) with 4 items. To show the products array, modify your code in your HTML:
  1. <table border="1" cellspacing="0" cellpadding="10">  
  2.     <tr>  
  3.         <th>Product Name</th>  
  4.         <th>Product Price</th>  
  5.         <th>Add to Cart</th>  
  6.     </tr>  
  7.     <!-- ko foreach: products -->  
  8.     <tr>  
  9.         <td><span data-bind="text: name"></span></td>  
  10.         <td><span data-bind="text: price"></span></td>  
  11.         <td>  
  12.             <input style="width: 40px;" type="number" data-bind="value: $data.quantity">  
  13.             <button data-bind="click: $parent.addToCart.bind($data)">Add to Cart</button>  
  14.         </td>  
  15.     </tr>  
  16.     <!-- /ko -->  
  17. </table>


To loop in your observable array Knockout.js does it in a special syntax, comment:
<!-- ko foreach: products -->
will loop the products attribute in our ViewModel (which currently has 4 elements). The loop will repeat everything inside the <!-- ko ... --> until it meets <!-- /ko -->. We bind the name of the current element in the products to the span. User will see the value of the name and price attribute inside the product, because we bind it to the text.

Notice the input of the cart: 
<input style="width: 40px;" type="number" data-bind="value: $data.quantity">

We want to make sure that every time the input element changes, the value of quantity inside the product will also change. We can use the data-bind attribute to bind the value of quantity of the product to the value of the input element.

On the button element, we have something different:
<button data-bind="click: $parent.addToCart.bind($data)">Add to Cart</button> 

We can bind events like click event on a button to the ViewModel. In this case, we bind the click event to the parent of the product, which is the ViewModel itself. Simply said, products is a child of ViewModel, so if we access the parent of products, we would get ViewModel. In the code above, the context of the event binding is still in products, so calling $parent will give us access to ViewModel. Now, when we click on the button, the addToCart function of the ViewModel will be called within the context of $data, the product itself. However, we still do not have the addToCart function so we need to create it:
  1. var ViewModel = function ViewModel(name) {  
  2.     // ...  
  3.     // ...  
  4.     this.cart = ko.observableArray([]);  
  5.   
  6.     this.addToCart = function(product) {  
  7.         var p = Object.assign({}, product);  
  8.         this.cart.push(p);  
  9.         this.calculateGrandTotal();  
  10.     }.bind(this);  
  11.   
  12.     this.grandTotal = ko.observable(0);  
  13.   
  14.     this.calculateGrandTotal = function() {  
  15.         var t = 0;  
  16.         for (var item of this.cart()) {  
  17.             t += item.price * item.quantity;  
  18.         }  
  19.         this.grandTotal(t);  
  20.     }.bind(this);  
  21. };


Now to show the content of the cart, add the following code to your HTML:
  1. <h2>My Cart</h2>  
  2. <table border="1" cellspacing="0" cellpadding="5">  
  3.     <tr>  
  4.         <th>Name</th>  
  5.         <th>Price</th>  
  6.         <th>Quantity</th>  
  7.         <th>Subtotal</th>  
  8.         <th>Action</th>  
  9.     </tr>
  10.     <!-- ko foreach: cart -->  
  11.     <tr>  
  12.         <td data-bind="text: name"></td>  
  13.         <td data-bind="text: price"></td>  
  14.         <td data-bind="text: quantity"></td>  
  15.         <td data-bind="text: (quantity * price)" align="right"></td>  
  16.         <td>  
  17.             <button data-bind="click: $parent.removeFromCart.bind($data)">Remove</button>  
  18.         </td>  
  19.     </tr>  
  20.     <!-- /ko -->  
  21.     <tr>  
  22.         <td colspan="3" align="right"><b>Grand Total</b></td>  
  23.         <td colspan="1" align="right" data-bind="text: grandTotal"></td>  
  24.         <td></td>  
  25.     </tr>  
  26.     <tr>  
  27.         <td colspan="5" align="center">  
  28.             <button data-bind="click: checkout">Checkout / Clear Cart</button>  
  29.         </td>  
  30.     </tr>  
  31. </table>


Here we show all the element inside the cart using foreach loop like how we show the products data. Note that on the checkout button, we do not need to access the parent because we are already in the context of the ViewModel while in the foreach loop, we have to access the $parent because the context is in the product.

We need to add a few more functions that are called above:
  1. this.checkout = function() {  
  2.     this.cart.removeAll();  
  3.     this.calculateGrandTotal();  
  4. }.bind(this);  
  5.   
  6. this.removeFromCart = function(product) {  
  7.     this.cart.remove(product);  
  8.     this.calculateGrandTotal();  
  9. }.bind(this);  


That's it, building an MVVM page is really easy using Knockout.js, and the result is really amazing. Data binding becomes very easy as Knockout.js handles it really nicely, making your page really dynamic and responsive to user's interaction. There are still more in Knockout.js, but this tutorial will only cover on the basic.

React hot reload & Redux (Part 2)

posted Dec 5, 2016, 1:59 AM by Andi Muqsith Ashari   [ updated Dec 5, 2016, 6:56 PM by Surya Wang ]


This is the second part of React hot reload & Redux, in this part we will learn about how to update and deleting product item that inserted using code we have built in the first tutorial, the first thing is modifying actions/index.js by adding updateProduct and deleteProduct method as action:

export const ADD_PRODUCT = 'ADD_PRODUCT';
export const UPDATE_PRODUCT = 'UPDATE_PRODUCT';
export const DELETE_PRODUCT = 'DELETE_PRODUCT';

let nextProductId = 1;

export function addProduct(product)
{
product.id = nextProductId++; 
    return {
        type: ADD_PRODUCT,
        product: product
    };
}

export function updateProduct(product){
return {
type : UPDATE_PRODUCT, 
product: product
}
}

export function deleteProduct(product){
return {
type : DELETE_PRODUCT,
product : product
}
}

Now we have 3 actions, addProduct, updateProduct, and deleteProduct, the next step is creating update and delete reducer by modifying reducer/products.js:

import { ADD_PRODUCT, UPDATE_PRODUCT, DELETE_PRODUCT } from '../actions';

const initialState = {
    products: []
};

export function crudApp(state = initialState, action) {

    switch(action.type)
    {

        case ADD_PRODUCT: {
            return Object.assign({}, state, {
                products: [
                    ...state.products,
                    action.product
                ]
            });
        }

        case UPDATE_PRODUCT:{
            state.products.forEach(function(val,key){
                if(action.product.id==val.id){
                    state.products[key] = action.product;
                }
            });
            return Object.assign({}, state, {
                products: [
                    ...state.products
                ]
            });
        }

        case DELETE_PRODUCT: {
            state.products.forEach(function(val,key){
                if(action.product.id==val.id){
                    state.products.splice(key,1);
                }
            });
            return Object.assign({}, state, {
                products: [
                    ...state.products
                ]
            });
        }

    }

    return state;
}

Our actions and reducers are ready to use, the last thing is importing our new action into our react component and use them as a functionality of our application (Insert, Update and Delete):

import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';

import { crudApp } from './reducers/products';
import { addProduct, updateProduct, deleteProduct } from './actions';

var store = createStore(crudApp);

class App extends React.Component {

    constructor(){
        super();
        this.state = {
            products: [],
            product: {
                id : '',
                name : '',
                description : ''
            }
        };
    }

    componentWillMount(){
        store.subscribe(() => {
            var state = store.getState();
            this.setState({
                products: state.products
            });
        });
    }

    handleSubmitForm(e)
    {
        e.preventDefault();
        if(this.state.product.id){
            store.dispatch(updateProduct(this.state.product));
        }else{
            store.dispatch(addProduct(this.state.product));
        }
        this.setState({
            product:{
                id:'',
                name:'',
                description:''
            }
        });
    }

    handleSelectProduct(product,e){
        this.setState({
            product:product
        });
    }

    handleDeleteProduct(product,e){
        store.dispatch(deleteProduct(product));
        this.setState({
            product:{
                id:'',
                name:'',
                description:''
            }
        });
    }

    handleProductNameChange(e){
        this.setState({
            product: {
                id : this.state.product.id,
                name : e.target.value,
                description:this.state.product.description
            },
        });
    }

    handleProductDescriptionChange(e){
        this.setState({
            product: {
                id : this.state.product.id,
                name:this.state.product.name,
                description : e.target.value
            },
        });
    }

    handleProductIdChange(e){
        this.setState({
            product: {
                id : e.target.value,
                name:this.state.product.name,
                description : this.state.product.description
            },
        });
    }   

    render () {

        var mode = "Add Product";
        if(this.state.product.id) mode = "Update Product";

        return(
            <div>
                <p>HMR is cool</p>
                <form onSubmit={this.handleSubmitForm.bind(this)}>
                    <table>
                        <tbody>
                            <tr>
                                <td>Product Id</td>
                                <td><input value={this.state.product.id} disabled="disabled" type="text" onChange={this.handleProductIdChange.bind(this)}/></td>
                            </tr>
                            <tr>
                                <td>Product Name</td>
                                <td><input value={this.state.product.name} type="text" onChange={this.handleProductNameChange.bind(this)}/></td>
                            </tr>
                            <tr>
                                <td>Product Description</td>
                                <td><input value={this.state.product.description} type="text" onChange={this.handleProductDescriptionChange.bind(this)}/></td>
                            </tr>
                        </tbody>
                    </table>
                    <input type="submit" value={mode}/>
                </form>
                <hr />
                <table width="500">
                    <thead>
                        <tr>
                            <th>Id</th>
                            <th>Name</th>
                            <th>Description</th>
                            <th>Action</th>
                        </tr>
                    </thead>
                    <tbody>
                    {
                        this.state.products.map((product,i)=>{
                            return (
                                <tr key={i}>
                                    <td>{product.id}</td>
                                    <td>{product.name}</td>
                                    <td>{product.description}</td>
                                    <td>
                                        <button onClick={this.handleSelectProduct.bind(this,product)}>Select</button>
                                        <button onClick={this.handleDeleteProduct.bind(this,product)}>Delete</button>
                                    </td>
                                </tr>
                            )
                        })
                    }
                    </tbody>
                </table>
            </div>
        );
    }
};

render(<App/>, document.getElementById('app'));

module.hot.accept();

Now we can inserting, viewing, updating, and deleting our data by using our simple React & Redux application.


1-10 of 74