JSFiddle - React, Tailwind, and code Playground
HTML
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/datejs/1.0/date.min.js"></script>
<div class="row-fluid">
<div class="span12">
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Time</th>
<th>Hours</th>
<th>Timesheet Code</th>
<th>Actions</th>
</tr>
</thead>
<tfoot></tfoot>
<tbody data-bind="foreach: DaysRequested">
<tr class="row1">
<td>
<div class="input-append date">
<input class="datepicker input-small required" type="text" data-bind="value: Date, uniqueName: true" /> <span class="add-on"><i class="icon-calendar"></i></span>
</div>
</td>
<td>
<div class="input-append bootstrap-timepicker">
<input class="timepicker input-small required" type="text" data-bind="value: Time, uniqueName: true" /> <span class="add-on"><i class="icon-time"></i></span>
</div>
</td>
<td>
<select class="input-small required" data-bind="options: $root.hours, value: Hours, uniqueName: true"></select>
</td>
<td>
<select class="required" data-bind="options: $root.timesheetCodes, optionsText: 'Title', optionsValue: 'Id', optionsCaption: '(Choose)', value: TimesheetCode, uniqueName: true"></select>
</td>
<td> <a href="#" data-bind="click: $root.removeDay, enable: $root.DaysRequested().length > 1" class="btn btn-danger">X</a>
</td>
</tr>
<tr class="row2">
...
JavaScript
$(document).ready(function () {
ko.applyBindings(new RequestViewModel());
function DayViewModel(day) {
var self = this;
self.Date = day.Date;
self.Time = day.Time;
self.Hours = ko.observable(day.Hours);
self.TimesheetCode = ko.observable(day.TimesheetCode);
self.Department = ko.observable(day.Department);
self.Project = ko.observable(day.Project);
self.Job = ko.observable(day.Job);
self.Comments = ko.observable(day.Comments);
self.JobIsRequired = ko.observable((day.JobIsRequired == undefined) ? false : day.JobIsRequired);
}
function RequestViewModel() {
var self = this;
self.Signature = "";
self.DaysRequested = ko.observableArray([new DayViewModel({
Date: new Date().toString("MM/dd/yyyy"),
Time: "08:00 AM",
Hours: 1,
TimesheetCode: "",
Department: 0,
Project: 0,
Job: 0,
Comments: ""
})]);
self.hours = FillHours();
self.timesheetCodes = [
{
"Id": "06",
"Title": "Comp. Time Earned",
"IsJobRequired": false
}, {
"Id": "20",
"Title": "Overtime",
"IsJobRequired": true
}
];
self.FormErrors = ko.observableArray([]);
// Total hours in the request
self.totalHours = ko.computed(function () {
var total = 0;
for (var i = 0; i < self.DaysRequested().length; i++) {
total += self.DaysRequested()[i].Hours();
}
return total;
});
// Add another day copying the previous day.
self.addDay = function () {
var array = self.DaysRequested();
var previousDay = array[array.length - 1];
previousDay.Date =...