Stack Exchange
Pre-generate HTML elements using knockout based on available data
I have a database that saves products and categories (each category belongs to one product and each product has many categories)
To accept the input I have an HTML form for creating new records that is populated using knockoutjs


var productList = [{
  id: 1,
  name: 'product1',
  categories: [{
    id: 1,
    name: 'category1'
  }, {
    id: 2,
    name: 'category2'
  }]
}, {
  id: 2,
  name: 'product2',
  categories: [{
    id: 3,
    name: 'category3'
  }, {
    id: 4,
    name: 'category4'
  }]
},{
  id: 3,
  name: 'product3',
  categories: [{
    id: 5,
    name: 'category5'
  }, {
    id: 6,
    name: 'category6'
  }]
}]

function Product(productList) {
  var self = this

  self.productList = productList
  self.selectedProduct = ko.observable()
  self.selectedCategories = ko.observable()

  self.categoryList = ko.computed(function() {
    var product = self.selectedProduct();
    var filtered = ko.utils.arrayFirst(self.productList, function(p) {
      if (p.id == product) {
        return p
      }
    });
    if (!filtered) {
      return []
    } else {
      return filtered.categories;
    }
  })
}

function ProductViewModel() {
  var self = this

  self.products = ko.observableArray([new Product(productList)])

  self.addProduct = function() {
    self.products.push(new Product(productList))
  }.bind(self)

  self.removeProduct = function(product) {
    self.products.remove(product)
  }
}

ko.applyBindings(new ProductViewModel())
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind='foreach: products'>
  <label>Product</label>
  <select data-bind="attr: {name: 'products['+$index()+']'}, options: productList, optionsCaption: 'Select Product', optionsText: 'name', optionsValue: 'id', value: selectedProduct"></select>
  <div data-bind='with: selectedProduct'>
    <label>Categories</label>
    <select class='categories-select' data-bind="attr: {name: 'categories['+$index()+'][]', multiple: 'multiple'}, options: $parent.categoryList, optionsText: 'name', optionsValue: 'id', value: $parent.selectedCategories"></select>
  </div>
</div>
<a href='#' data-bind='click: addProduct'> Add </a>



Now I want to create a similar HTML form which fetches the data from the backend and pre generates with the existing values it in the similar layout. Note that there might be multiple sets of such dropdown boxes in the data fetched. I want the product and categories selected as well as per the values.
The JSON might look something like:
var productList = [{
  id: 1,
  name: 'product1',
  selected: true,
  categories: [{
    id: 1,
    name: 'category1'
    selected: true
  }, {
    id: 2,
    name: 'category2'
  }]
}, {
  id: 2,
  name: 'product2',
  selected: true,
  categories: [{
    id: 3,
    name: 'category3',
    selected: true
  }, {
    id: 4,
    name: 'category4',
    selected: true
  }]
},{
  id: 3,
  name: 'product3',
  categories: [{
    id: 5,
    name: 'category5'
  }, {
    id: 6,
    name: 'category6'
  }]
}]


when you say pre-generate do you mean you want the HTML to come filled with data from your server?  Or something else...

Yes, I want the html to come filled with data

Ok, so it sounds like you're trying to fill knockout templates on the server.  You can use jsDOM and knockout in nodejs directly.  If your server isn't nodejs, you'd have to make a nodejs server and call it through an API.  You'd pass in your template and data, it would pass out HTML.  The only problem is that this is somewhat slow.
If you feel like you're all alone doing these crazy things with knockout on the server, don't worry, you're in good company: other people are trying to use the same templating language on the server as they do on the client.  Knockoff is cool because it parses only the bare minimum knockout template syntax that you're likely to use on the server, leaves the rest of the syntax intact so you can use it on the client, and does all this blazing fast.
