KnockoutJS - letronghieu4897/magento GitHub Wiki

KnockoutJS

Header


1.Tree

KnockoutJS In Magento 2___________________________________________________________
β”œβ”€β”€ General Concepts
|	β”œβ”€β”€ Aliases 
|	└── Binding values 	
|
β”œβ”€β”€ Custom Magento bindings 
|	β”œβ”€β”€ after render 
|	β”œβ”€β”€ autoselect
|	β”œβ”€β”€ bindHtml
|	β”œβ”€β”€ collapsible
|	β”œβ”€β”€ datepicker
|	β”œβ”€β”€ fadeVisible
|	β”œβ”€β”€ i18n
|	β”œβ”€β”€ keyboard
|	β”œβ”€β”€ magelnit
|	β”œβ”€β”€ optgroup
|	β”œβ”€β”€ outerClick
|	β”œβ”€β”€ range
|	β”œβ”€β”€ resizable
|	β”œβ”€β”€ scope
|	β”œβ”€β”€ staticChecked
|	β”œβ”€β”€ template
|	└── tooltip
._____________________________________________________________________________________

2.General Concepts

Aliases

  • In KnockoutJS use [data-bind="<binding_name>: "]
  • In Magento 2 use can use alias*
    • [<binding_alias>="<value">]
    • [<binding_alias> args=""]

Custom Magento bindings

1.afterRender : (element: Element, viewModel: Object) => void

WHAT

binding notifies its subscriber when an associated element is inserted into the DOM.
Source : <Magento_Ui_module_dir>/view/base/web/js/lib/knockout/bindings/after-render.js
define([
    'ko',
    '../template/renderer'
], function (ko, renderer) {
    'use strict';

    ko.bindingHandlers.afterRender = {

        /**
         * Binding init callback.
         */
        init: function (element, valueAccessor, allBindings, viewModel) {
            var callback = valueAccessor();

            if (typeof callback === 'function') {
                callback.call(viewModel, element, viewModel);
            }
        }
    };

    renderer.addAttribute('afterRender');
});
define([
    'ko',
    '../template/renderer'
], function (ko, renderer){
//set value for param. ko is 'ko' , renderer is '../template/renderer' 
}
'use_strict'; 
//Can not use undeclared variables
init: function (element){} || function init(element){}
\\The same meaning

HOW TO USE IT

<div afterRender="function (target, viewModel) {}"></div>
or
//alias : afterRender
<div afterRender="loginFunction"></div> 
<script>
loginFunction : function(){}
</script>

2.autoselect : Boolean

WHAT

Auto highlights the text when it gets focus
Source : <Magento_Ui_module_dir>/view/base/web/js/lib/knockout/bindings/autoselect.js 
define([
    'ko',
    'jquery',
    '../template/renderer'
], function (ko, $, renderer) {
    'use strict';

    /**
     * 'Focus' event handler.
     *
     * @param {EventObject} e
     */
    function onFocus(e) {
        e.target.select();
    }

    ko.bindingHandlers.autoselect = {

        /**
         * Adds event handler which automatically
         * selects inputs' element text when field gets focused.
         */
        init: function (element, valueAccessor) {
            var enabled = ko.unwrap(valueAccessor());

            if (enabled !== false) {
                $(element).on('focus', onFocus);
            }
        }
    };

    renderer.addAttribute('autoselect');
});

HOW TO USE IT

// as an attribute
<input type="text" autoselect/>

// in a standard KO form 
<input type="text" data-bind="autoselect: true"/>

3.bindHtml : String

WHAT

HOW TO USE IT


4.collapsible : Object

WHAT

It can automatically collapse panel when clicking outside of the associated node, toggle optional CSS class when node changes its visibility. 

HOW TO USE IT


5.datepicker : String | Object

WHAT

an adapter for the calendar mage/calendar.js

HOW TO USE IT

<input type="text" data-bind="datepicker: value"/>

6.fadeVisible : Boolean

WHAT

The fadeVisible binding performs the gradual change of the element’s visibility (with an animation effect).

HOW TO USE IT

<div data-bind="fadeVisible: isVisible">Foo Bar</div>
<button click="function () { isVisible(!isVisible()); }">Toggle</button>

7.i18n : string

WHAT

Translate a string according currently enable locale

HOW TO USE IT

//Way 1
<div data-bind="i18n: 'Translate as a standard knockout binding'"></div>

//Way 2
<div translate="'Translate using the attribute'"></div>

//Way 3
<translate args="'Translate using the tag'"></translate>

8.keyboard : [name: number]: (e: KeyboardEvent) => void

WHAT

Allowing setting up keypress event of a specific key

HOW TO USE IT

<input type="text" keyboard="{
    13: function (e) {
        console.log('Enter key has been pressed!');
    }
}"/>

9.magelnit : [path: string]: Object

WHAT

an adapter for the [data-mage-init] attribute that is used to initialize jQuery widgets

HOW TO USE IT

<div mageInit="{
    'Magento_Ui/js/modal/modal': {
        autoOpen: true,
        buttons: false,
        modalClass: 'modal-system-messages',
        title: 'Hello world!'
    }
}"></div>

10.optgroup : Array | Array

WHAT

A decorator for the standard Knockout’s options binding which adds the support of nested options, and renders them as the <optgroup> element.

HOW TO USE IT

<select data-bind="
    optionsValue: 'value',
    optionsText: 'label',
    optgroup: [{
        label: 'Swedish Cars',
        value: [{
            label: 'Volvo',
            value: 'volvo'
        }, {
            label: 'Saab',
            value: 'saab'      
        }]
    }, {
        label: 'German Cars',
        value: [{
            label: 'Mercedes',
            value: 'mercedes'
        }]
    }]"></select>

11.outerClick : Function()

WHAT

Allowing click event that happends outside of the boundaries of the asscociated element.

HOW TO USE IT

<div id="target" outerClick="function () {
    console.log('Clicked outside of the "target" node.');
}">
</div>

12.range : Object

WHAT

an adapter for the jQuery UI Slider widget.

HOW TO USE IT

<div
    class="data-slider"
    range="{
        value: scale,
        min: 1,
        max: 200,
        step: 1
}"></div>

13.resizable : Object

WHAT

 an adapter for the jQuery UI Resizable widget

HOW TO USE IT

<div data-bind="resizable: {maxHeight: 200}"></div>

14.scope : String

WHAT

HOW TO USE IT

<!-- as an attribute -->
<div ko-scope="'name.of.component'"></div>

<!-- in a standard KO form -->
<div data-bind="scope: 'name.of.component'"></div>

<!-- without an extra container node -->
<scope args="'name.of.component'"></scope>

15.staticChecked : Boolean | String | Number | Array <String|Number|Number>

WHAT

Use it for a checkbox (<input type='checkbox'>) or a radio button (<input type='radio'>) 

staticChecked doesn’t change the array of the already selected elements if the value of the associated DOM element changes.

HOW TO USE IT

<input type="checkbox" data-bind="staticChecked: observable"/>

16.template : String | Object

WHAT

A customization of the existing Knockout template binding.
It is used to render a template inside of the associated element

HOW TO USE IT

<div data-bind="template: 'path/to/the/template'"></div>

17.tooltip : Object

WHAT

Magento custom knockout binding for displaying a tooltip.

HOW TO USE IT

//As ATTRIBUTE
<div tooltip="
     trigger: '[data-tooltip-trigger=trigger]', 
     action: 'click', 
     delay: 300, 
     track: true,
     position: 'top' 
 "> Tooltip data </div>
 
<div data-tooltip-trigger="trigger"/>

//As Node
<div data-bind="
    tooltip: {
        trigger: '[data-tooltip-trigger=trigger]',
        action: 'click', 
        delay: 300, 
        track: true,
        position: 'top' 
    }  
"> Tooltip data </div>
 
<div data-tooltip-trigger="trigger"/>

3.Knockout syntax

function myViewModel() {
	self = this;

		// ===========> ko.observable('') : LIST VALUE OF firstname, Announce if  firstname has anything change
	self.firstname = ko.observable('');
	self.lastname = ko.observable('');
	self.increment = ko.observable(1);
	
		// ===========> self.firstname() : READ DATA FROM self.firstname
		// ===========> self.lastname() : READ DATA FROM self.lastname 
	self.fullname = ko.computed(function(){ self.firstname() + ' ' + self.lastname()} , self); 
		
		// ===========> To working with list, collection, array... we use ko.observableArray
	self.array = ko.observableArray([{name: 'Hieu', age: '22'}])
		
		// Function incre value of increment by one.
	Increment = function() {
		self.increment((self.increment() + 1))
	}	
}
ko.applyBindings(new myViewModel());

TEST HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" type="text/css" href="css/style.css">
    <script type='text/javascript' src='knockout/knockout-3.5.0.js'></script>
</head>
<body>
    <div class="cart-items" >
			// ===========> data-bind mouseover call function addClass 
        <div id="cart-item-firt" class="cart-item" data-bind="event: {mouseover: addClass, mouseout:removeClass}, class:classAppend " >
            <p>HELLO</p>
            <button class="cart-item-button" data-bind="click: clickAppend, class:clickAppendClass, ">CLICK</button>
        </div>
        <div class="cart-item" data-bind="event: {mouseover: addClassTwo, mouseout:removeClassTwo}, class:classAppend" >
            <p>HELLO</p>
            <button class="cart-item-button" data-bind="click: clickAppend,  class:clickAppendClass">CLICK</button>
        </div>
        <div id="cart-item-second" class="cart-item" data-bind="click: disable, visible: visible">
        </div>
    </div>
    <table class="table-test" data-bind='foreach: arrayTest'>
        <tr class="row-test">
            <th class="value-test" data-bind="text: firstname"></th>
            <th class="value-test" data-bind="text: lastname"></th>
            <th class="value-test">
                <button class="edit-button" >EDIT</button>
                <button class="delete-button" data-bind="click: removeArray">DELETE</button>
                <button class="add-button" data-bind="click: addArray">ADD</button>
            </th>
        </tr>
    </table>
    <script type='text/javascript' src='js/action.js'></script>
</body>
</html>

TEST KNOCKOUT JS

function viewModel() {
    self = this;
    self.classAppend = ko.observable(''),
    self.indexBlock = ko.observable(0),
    self.classAppendBlockTwo = ko.observable(''),
    self.clickAppendClass = ko.observable(''),
    self.clickAppendIndex = ko.observable(1),
    self.visible = ko.observable(true)
    self.arrayTest = ko.observableArray([{
        firstname: 'Hieu', lastname: 'Le'
    }])
    addClass = function(){
        self.classAppend('yellow-background fontsize-hover')
    },
    addClassTwo = function(){
        self.classAppendBlockTwo('yellow-background fontsize-hover')
    },
    removeClass = function(){
        self.classAppend('')
    },
    removeClassTwo = function() {
        self.classAppendBlockTwo('')
    }
    clickAppend = function() {
        if(self.clickAppendIndex() == 1) {
            self.clickAppendClass('button-after-click')
            self.clickAppendIndex(0)
        }
        else {
            self.clickAppendClass('')
            self.clickAppendIndex(1)
        }
    }
    disable = function() {
        self.visible(false)
    }
    addArray = function() {
        self.arrayTest.push({firstname: 'Hieu', lastname:'Le'})
    }
    removeArray = function() {
        self.arrayTest.pop();
    }
}
ko.applyBindings(new viewModel());

TWO WAY TO USE DATA-BINDS

<span data-bind="text: status"><span> 

= 

<span> <!--ko text: status --><!--/ko--> <span>

Footer

⚠️ **GitHub.com Fallback** ⚠️