KnockoutJs with Sitecore

KnockoutJs with Sitecore

If you are moving to SItecore9 thats brilliant and you can use the popular frontend frameworks like Angular or React.

However, with SItecore 8.X you need to use more javascript and Jquery which are a bit hard to manage Model-binding and testing as well.

So, Knockout Js can be an approach to help you dealing with this issue and managing your frontend model much easier.

KnockoutJs has key concepts like Declarative Binding, Automatic UI Refresh, Dependency Tracking. To get more help knockoutjs.com can be a great source of documentation.

How KnockoutJs works with Sitecore

You need to add a npm dependency to knockoutJs then since you have a MVC view form, you can simply add an attribute to the elements you want to track and bind them using knockoutJs.

Here is a sample to use it:

Simple Sample

in the view Identify the element like your email input which tacks your element changes as well:

<input class="input-field" type="email"  data-bind="value: email" name="@fieldName"

It means that you bind this element to a viewmodel in the scripts called email. The script looks like this:

import $ from 'jquery';
import ko from 'knockout';

let emailInputComponents;
let isEmailDirty=false;
$(() => {
    emailInputComponents = $('.email-input-component .join-text-input input.input-field');
    

    var viewModel = function () {
        this.email = ko.observable('').extend({keepTrack: "is email field has been changed"});
    };

 
    ko.extenders.keepTrack = function(target, option) {
        let oldEmailVal='';
        target.subscribe(function(oldValue) {
            oldEmailVal=oldValue;

        }, null, "beforeChange");

      
        target.subscribe(function(newValue) {
            if (newValue!=oldEmailVal)
                isEmailDirty=true;
            
        });
        return target;
    };

    // Activates knockout.js
    ko.applyBindings(new viewModel());
});

Apply a initial value to the bound item:

You can also use a npm library called knockout-pre-rendered which helps you initiate a initial state for your element when the page in loaded and element is bound.
you just need y=to use init in the data-bind and value to assign a default value.

<input type="hidden" name="EPS_REFERENCEID" value="1234" data-bind="init, value: orderReference"/>

You can also bind more attributes to the element by adding that to the data-bind like this:

<input class="input-field" type="email"  data-bind="value: email , attr: {'data-isRemotelyValidated': emailIsValidated }" name="@fieldName"