JSFiddle - React, Tailwind, and code Playground
by kwon
HTML
<script src="http://cloud.github.com/downloads/SteveSanderson/knockout/knockout-2.0.0.js"></script>
<script src="https://raw.github.com/SteveSanderson/knockout.mapping/master/build/output/knockout.mapping-latest.js"></script>
<table border="1" width="100%">
<thead>
<tr>
<th colspan="2">Day(s)</th>
<th>(optional)</th>
<th colspan="3">Time</th>
<th></th>
</tr>
</thead>
<tbody data-bind="foreach: hours, visible: hours().length > 0">
<tr>
<td data-bind="css: {'cell-error': from_error()}">
<select data-bind="options: $parent.days_of_week, optionsCaption: 'From...', value: from"></select>
</td>
<td style="text-align: center">-</td>
<td>
<select data-bind="options: $parent.days_of_week, optionsCaption: 'To...', value: to"></select>
</td>
<td data-bind="css: {'cell-error': from_time_error()}">
<select data-bind="options: $parent.available_hours, value: from_hour, optionsCaption: 'From'"></select>
<select data-bind="options: $parent.am_pm, value: from_am_pm, optionsCaption: ' '"></select>
</td>
<td style="text-align: center">-</td>
<td data-bind="css: {'cell-error': to_time_error()}">
<select data-bind="options: $parent.available_hours, value: to_hour, optionsCaption: 'To'"></select>
<select data-bind="options: $parent.am_pm, value: to_am_pm, optionsCaption: ' '"></select>
</td>
<td style="text-align: center">
<nav>
<a href="#" data-bind="click: $parent.remove_hours">-</a>
</nav>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="6">
<button data-bind="click: save, visible: hours().length > 0">Save hours</button>
</td>
<td...
SCSS
table {
th, td {
padding: 5px;
}
}
.cell-error {
background-color: red;
}
JavaScript
var days_of_week = ['Mon', 'Tues', 'Wed', 'Thur', 'Fri', 'Sat', 'Sun'];
var am_pm = ['AM', 'PM'];
var available_hours = ['1:00', '1:30', '2:00', '2:30', '3:00', '3:30'];
var hoursLineView = function(data) {
var self = this;
self.id = ko.observable();
self.from = ko.observable();
self.from_hour = ko.observable();
self.from_am_pm = ko.observable();
self.to = ko.observable();
self.to_hour = ko.observable();
self.to_am_pm = ko.observable();
ko.mapping.fromJS(data, {}, this);
self.from_error = ko.observable();
self.from_time_error = ko.observable();
self.to_time_error = ko.observable();
self.validate = function() {
console.log('item validate');
if (!self.from()) {
self.from_error("can't be blank");
}
if (!self.from_hour() || !self.from_am_pm()) {
self.from_time_error("can't be blank");
}
if (!self.to_hour() || !self.to_am_pm()) {
self.to_time_error("can't be blank");
}
};
self.from.subscribe(function() {
if (self.from()) {
self.from_error("");
}
});
self.from_hour.subscribe(function() {
if (self.from_hour() && self.from_am_pm()) {
self.from_time_error("");
}
});
self.from_am_pm.subscribe(function() {
if (self.from_hour() && self.from_am_pm()) {
self.from_time_error("");
}
});
self.to_hour.subscribe(function() {
if (self.to_hour() && self.to_am_pm()) {
self.to_time_error("");
}
});
self.to_am_pm.subscribe(function() {
if (self.to_hour() && self.to_am_pm()) {
self.to_time_error("");
}
});
self.valid = function() {
self.validate();
if (self.from_error() || self.from_time_error() ||
self.to_time_error()) {
return false;
}...