var Conditions = { 'Number': ['=', '!=', '>', '<'], 'String': ['Contains', '=', '!='], findByType: function(type) { for (p in this) { if (typeof this[p] === "object" && p == type) { return this[p]; } } return []; } }; var _columns = [ { Column: 'DeveloperName', Display: 'Developer', Type: 'String'}, { Column: 'IssueID', Display: 'Issue ID', Type: 'Number'}, { Column: 'IssuetTitle', Display: 'Issue Title', Type: 'String'}, { Column: 'IssuetDescription', Display: 'Issue Description', Type: 'String'} ]; function findFilterColumn(column) { for (var i = 0; i < _columns.length; i++) { if (_columns[i].Column == column) { return _columns[i]; } } return null; }; var Filter = function(column, condition, nextFilterBinaryCondition, type, value) { this.ColumnObj = ko.observable(findFilterColumn(column || "")); this.ColumnObj.subscribe( function(value) { this.Value(null); }, this); this.Column = ko.dependentObservable( function() { return (this.ColumnObj() != null) ? this.ColumnObj().Column : ""; }, this); this.Condition = ko.observable(condition || null); this.NextFilterBinaryCondition = ko.observable(nextFilterBinaryCondition || "AND"); this.Type = ko.dependentObservable( function() { return (this.ColumnObj() != null) ? this.ColumnObj().Type : null; }, this); this.AvailableConditions = ko.dependentObservable( function() { var conditions = Conditions.findByType(this.Type()); return conditions; }, this); this.Value = ko.observable(value || ""); this.IsValid = ko.dependentObservable( function () { var valueAndColumnAreValid = (this.ColumnObj() != null && this.Value() != null && this.Value().length > 0); return valueAndColumnAreValid; }, this); }; function ViewModel(columnsSource) { this.nextFilterBinaryConditions = ['AND', 'OR']; this.columns = ko.observableArray(columnsSource); this.filters = ko.observableArray([new Filter()]); this.addFilter = function(filterObj) { var invalidFilter = ko.utils.arrayFirst(this.filters(), function (filter) { return filter.IsValid() === false; }); if (invalidFilter == null) { var currentIndex = ko.utils.arrayIndexOf(this.filters(), filterObj); this.filters.splice(currentIndex + 1, 0, new Filter()); } }; this.removeFilter = function(filterObj) { this.filters.remove(filterObj); if (this.filters().length == 0) { this.addFilter(); } }; this.postFilters = function() { var items = ko.toJS(this.filters()); var mappedItems = ko.utils.arrayMap(items, function(filter) { delete filter.ColumnObj; delete filter.AvailableConditions; return filter; }); alert(ko.toJSON(mappedItems)); }; }; ko.applyBindings(new ViewModel(_columns));