KO templates name and nodes

by Jorge Bustos Pereda

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-debug.js"></script>
<div id="byName" class="container">

  Select template by name: 
  <select data-bind="{options: tmplNames, value: tmplName}"></select>
  <input type="button" value="Add template"
       data-bind="click: createNewTemplate"/>
    <span data-bind="visible: loading">Loading new template...</span>
  <div data-bind="template: {name: tmplName, data: tmplData}"></div>

</div>

<div id="tmplContainer" style="display:none">
  <div id="tmplA">
    <div class="a">
      <h3>Template A</h3>
      <span data-bind="text: name"></span> <span data-bind="text: surname"></span>
    </div>
  </div>
  <div id="tmplB">
    <div class="b">
      <h3>Template B</h3>
      Name: <span data-bind="text: name"/>
    </div>
  </div>
</div>

CSS

div.container { border: solid 1px black; margin: 20px 0;}
div {padding: 5px; }
.a { background-color: #FEE;}
.b { background-color: #EFE;}
.c { background-color: #EEF;}

JavaScript

// Simulate service that return HTML
var i = 0;
var getHtml = function() {
    var deferred = $.Deferred();
	var html = 
    '<div class="'+ (i%3 == 0 ? 'a' : i%3 == 1 ? 'b' : 'c')  +'"> \
	  <h3>Dynamic template ' + i++ + '</h3> \
	  Name: <span data-bind="text: name"/> \
    </div>';
    setTimeout(deferred.resolve, 2000, html);
    return deferred.promise();
};

var Vm = function() {
  self = this;
  self.tmplIdx = 0;
  self.tmplName = ko.observable('tmplA');
  self.tmplData = ko.observable({ name: 'Helmut', surname: 'Kaufmann'});
  self.tmplNames = ko.observableArray(['tmplA','tmplB']);
  self.loading = ko.observable(false);
  self.createNewTemplate = function() {
      // simulate AJAX call to service
      self.loading(true);
      getHtml().then(function(html) {
          var tmplName = 'tmpl' + tmplIdx++;
          var $new = $('<div>');
          $new.attr('id',tmplName);
          $new.html(html);
          $('#tmplContainer').append($new);
          self.tmplNames.push(tmplName);
	      self.loading(false);
          self.tmplName(tmplName);
      });
  };
  return self;
};

ko.applyBindings(Vm(), byName);