JSFiddle - React, Tailwind, and code Playground

by antouank

HTML

<h2>Category : Trousers</h2>
<h3>Sizes</h3>
<ul data-bind="foreach: products">
    <li>
        <input type="checkbox" data-bind="value: size.id, filterChange: size.name" />
        <label data-bind="text: size.name"></label>
    </li>
</ul>
<h3>Colors</h3>
<ul data-bind="foreach: colorFilter">
    <li>
        <input name="colorFilter" type="checkbox" data-bind="value: name, checked: on" />
        <label for="colorFilter" data-bind="text: name"></label>
    </li>
</ul>
 <h3>Products</h3>
<ul data-bind="foreach: filteredItems">
    <li>
        <label data-bind="text: name"></label>-
        <label data-bind="text: size.name"></label>-
        <label data-bind="text: color.name"></label>
    </li>
</ul>

CSS

body{
    background-color: #444;
    color: #ccc;
}

JavaScript

function Color(id, name) {
    return {
        id: ko.observable(id),
        name: ko.observable(name)
    };
};

function Size(id, name) {
    return {
        id: ko.observable(id),
        name: ko.observable(name)
    };
}

function Product(id, name, size, color) {
    var newItem = {
        id: ko.observable(),
        name: ko.observable(name),
        size: size,
        color: color
    };
    
    checkFilters(newItem);
    
    return newItem;
};

function checkFilters(item){
    
    var exists = false;
    if(item.color){
        for (var item in CategoryViewModel.colorFilter()){
            if(item.name === item.color.name()){
                exists = true;
                return false;
            }
        }
        if(!exists){
            CategoryViewModel.colorFilter.push({
                name: item.color.name(),
                on: true
            });
            return true;
        }
    }
    
}

var CategoryViewModel = {
    id: ko.observable(1),
    name: ko.observable("Trousers"),
    sizes: ko.observableArray(),
    colorFilter: ko.observableArray(),
    products: ko.observableArray(),
    filter: ko.observable({
        prop: '',
        value: ''
    })
};

ko.bindingHandlers.filterChange = {
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        console.log('filterChange');
    }
};

//filter the items using the filter text
CategoryViewModel.filteredItems = ko.computed(function() {
    var filterProp = this.filter().prop,
        filterValue = this.filter().value;
    
    function filterThis(item) {
        if(item[filterProp] && item[filterProp].name() === filterValue){
            return item;
        }
        return;
    }
    
    if (!filterValue) {
        return this.products();
    } else {
        return ko.utils.arrayFilter(this.products(), filterThis);
    }
}, CategoryViewModel);

ko.applyBindings(CategoryViewModel);

CategoryViewModel.products([
    new Product(1,...