KO Component Widget with template

Inserts a template component that contains a child component

by Doug Hill

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-debug.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<table>
    <tbody data-bind="foreach:filters">
        <tr>
            <th data-bind="text:name"></th>
            <td data-bind="template:{name:template}"></td>
        </tr>
    </tbody>
</table>

<span data-bind="text:ko.mapping.toJSON(queryData)"></span>

<template id="stringfilter">
    <input data-bind="value:value"/>
</template>
<template id="dropdownfilter">
    <select data-bind="value:value,options:values"></select>
</template>
<template id="rangefilter">
    <input data-bind="value:value1"/><input data-bind="value:value2"/>
</template>

JavaScript

var data={
    filters: [
        {
            name: "Frequency",
            type: "dropdown",
            config: {
                values: [
                    "High",
                    "Low"
                ]
            },
            value: "Low"
        }, 
        {
            name: "ATTUID",
            type: "string",
            config: null,
            value: "123"
        }, 
        {
            name: "Range",
            type: "range",
            config: null,
            value: {value1:"1",value2:"2"}
        }
        
    ]
};

var filterModels={
    "stringfilter": {
        viewModel:function (def) {
            var self = this;
            self.value=ko.observable(def.value);
        }
    },
    "dropdownfilter": {
        viewModel:function (def) {
             var self = this;
             self.value=ko.observable(def.value);
             self.values=def.config.values;
        }
    },
    "rangefilter": {
        viewModel: function (def) {
            var self = this;
            self.value1=ko.observable(def.value.value1);
            self.value2=ko.observable(def.value.value2);
            self.value=ko.computed(function(){
                return {
                    value1: self.value1(),
                    value2: self.value2()
                };
            });
        }
    }
}
    



var parentViewModel=function(){
	var self=this;
	
	self.filters=ko.observableArray();
	
	self.loadFilters=function(filterData){
        var filters=[];
		ko.utils.arrayForEach(filterData.filters,function(filterDef){
			var filter=new filterModels[filterDef.type+ 'filter'].viewModel(filterDef);
            filter.template=filterDef.type + 'filter';
            filter.name=filterDef.name;
            filters.push(filter);
		});
        self.filters(filters);
	}
    
    self.queryData=ko.computed(function(){
        return ko.utils.arrayMap(self.filters(),function(filter){
            return {
                name:filter.name,
               ...