JSFiddle - React, Tailwind, and code Playground

by Antonin Loury

HTML

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.1.0/knockout-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<table>
    <tbody data-bind="foreach: intervens">
        <tr>
            <td>
                <input type="text" data-bind="value: name" />
            </td>
            <td>
                <table>
                    <tbody data-bind="foreach: natures">
                        <tr>
                            <td>
                                <select class='filterSelect' data-bind="options: $root.naturesRef, optionsText: 'label', optionsValue:'id', value: id" />
                            </td>
                            <td>
                                <td>
                                    <input type="button" value="-" data-bind="click: $root.removeNature.bind($data,$parent)" />
                                </td>
                                <td>
                                    <input type="button" value="+" data-bind="click: $root.addNature.bind($data,$parent)" />
                                </td>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </td>
            <td>
                <input type="button" value="-" data-bind="click: $root.removeInterven" />
            </td>
        </tr>
    </tbody>
</table>
<input type="button" value="submit" data-bind="click: update" />
<input type="button" value="add" data-bind="click: addInterven" />
<hr>
<div data-bind="foreach: intervens"> <span data-bind="text: name"></span> :
    <!-- ko foreach: natures --> <span data-bind="text: id"></span>

    <!-- /ko -->
</div>

JavaScript

var data = {
    'intervens': [{
        'id': '1',
            'name': 'inter1',
            'natures': [{
            'id':
                '2'
        }]
    }],
        'naturesRef': [{
        'id': '1',
            'label': 'nature1'
    }, {
        'id': '2',
            'label': 'nature2'
    }, {
        'id': '3',
            'label': 'nature3'
    }]
};

var ViewModel = function (data) {
    var self = this;
    var dat = ko.mapping.fromJS(data, {}, self);

    // Ko mapping créé des objets observables sur les objets nested, ainsi que sur les objets contenus dans les tableaux.
    // console.log(dat.intervens()[0].natures()[0].id());

    self.update = function () {
        console.log(ko.toJSON(self.intervens()));
    };

    self.removeInterven = function (item) {
        self.intervens.remove(item);
    };

    self.addInterven = function (item) {
        self.intervens.push({
            'id': '',
                'name': '',
            // Ici on doit créer un observable pour que l'ajout ou la suppression d'un objet notifie le changement à la vue.
            'natures': ko.observableArray([{
                'id': '1'
            }])
        });
    };

    self.removeNature = function (parent, subitem) {
        console.log(parent);
        console.log(subitem);
        parent.natures.remove(subitem);
    };

    self.addNature = function (parent, subitem) {
        parent.natures.push({
            id: 1
        });
    };

    // Filtrage des natures déjà sélectionnées au sein d'un intervenant.
    self.filterSelect = function (naturesSelect) {
        var selectedValues = [];
        $.each(naturesSelect, function (i, el) {

            console.log('Pour chaque nat : ' + selectedValues);
               
            $(el).empty();
            $.each(buildSelectOptionsFiltered(self.naturesRef(), selectedValues), function() {
                $(el).append(this);
            });
            
            selectedValues.push($(el).val());
        });
...