Knockout and Google Charts with ES6 and UnderscoreJs

A sample showing how KnockOut can be applied to Google Charts, using ES6. It uses UnderscoreJs to performsome functional operations.

by Jaume Vinyes

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-debug.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout-validation/2.0.3/knockout.validation.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<div class='ViewModelScope'...

Babel + JSX

/***** Boiler Plate Bootstrap *****/
$(document).ready(() => {
  const data = $(".ViewModelScope").data("model");
  const viewModel = new ChartViewModel(data);  
  viewModel.Initialize();
});
 
/***** ViewModelBase ******/
class ViewModelBase {
  constructor(data) {
    if (this.constructor === ViewModelBase) {
      throw new TypeError("Cannot construct abstract class ViewModelBase.");
    }
    this.Original = data; 
  }

  Initialize() {
    let knockoutValidationSettings = {
      insertMessages: false,
      decorateElement: true,
      errorElementClass: "input-error", // defined at site.css
      grouping: {
        deep: true,
        observable: true,
        live: true
      }
    };
    ko.validation.init(knockoutValidationSettings, true);
    ko.mapping.fromJS(this.Original, {}, this);
    ko.applyBindings(this, document.getElementsByClassName("ViewModelScope")[0]);
  }
};    
  
/***** ChartViewModel *****/
class ChartViewModel extends ViewModelBase {
  constructor(data) {
    super(data);
  }   
 
  Initialize() {     
  	this._first = true;
    google.charts.load("current", {packages: ["corechart"]});
    google.charts.setOnLoadCallback(() =>	{  
    	this.DataTable = ko.observable(this.GetFirstDataTable());  
      this.ChartOptions = ko.observable(this.GetFirstChartOptions())
      this.SetBindingHandlers();
      super.Initialize();
    })
  }  
   
  SetBindingHandlers() {
  	ko.bindingHandlers.data = {
       	update: function (element, valueAccessor, allBindingsAccesor, viewModel, bindingContext) 				 {       
       	 	viewModel.data = ko.unwrap(valueAccessor());
					viewModel.DrawChart(element);
        }
     };
     ko.bindingHandlers.options = {
       	update: function (element, valueAccessor, allBindingsAccesor, viewModel, bindingContext) 				 {       
       	 	viewModel.options = ko.unwrap(valueAccessor());
					viewModel.DrawChart(element);
         }
     }; 
  }
  
	DrawChart(element) {
  	var chart = new...