Various selects

by ZenMaster

HTML

<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.3.5/knockout.mapping.js"></script>
<ul data-bind="foreach: { data: questions, as: 'question' }">
    <li data-bind="template: { name: question.controlType, data: question }" />
    <li><strong data-bind="text: question.answer"></strong></li>
    <li>&nbsp;</li>
</ul>

<script type="text/html" id="textBox">
    <label data-bind="text: text"></label>
    <br />
    <input type="text" data-bind="value: answer" />
</script>

<script type="text/html" id="picker">
    <!-- ko foreach: pickers -->
    <label data-bind="text: name"></label>
    <select data-bind="options: options, value: value, optionsCaption: 'Choose...'"></select>
    <!-- /ko -->
</script>

CSS

ul {
    list-style: none;
    margin: 0;
    padding: 0;
}

JavaScript

var json = JSON.stringify({
    questions: [{
        text: "master question",
        answer: null,
        controlType: "textBox"
    }, {
        text: "dependent on master question",
        answer: null,
        controlType: "picker",
        pickers: [
            { name: "Size", options: ['Large', 'Medium', 'Small'], value: '' },
            { name: "Color", options: ['Red', 'Blue', 'Green'], value: '' }
        ]
    },{
        text: "some other question",
        answer: null,
        controlType: "picker",
        pickers: [
            { name: "Gender", options: ['Male', 'Female'], value: '' },
            { name: "Ethnicity", options: ['White', 'Asian', 'Latino'], value: '' },
            { name: "Age", options: ['0-17', '18-25', '25+'], value: '' }
        ]
    },]
});

var model = JSON.parse(json);
var viewModel = ko.mapping.fromJS(model);

viewModel.questions().forEach(function (question) {
    if (question.controlType() === 'picker') {
        question.answer = ko.computed(function() {
            var answers = [];
            question.pickers().forEach(function(i) {
                if (i.value())
                    answers.push(i.value());
            });
            return answers.length === question.pickers().length ?
                answers.join(' ') : '';
        });
    }
});

ko.applyBindings(viewModel);