I'm trying to have a twitter bootstrap modal open to a window that has a text area in it which is editable, then on save, it saves the appropriate data. My current code:
HTML:
<table class=display table table-striped>
<tbody data-bind=foreach: entries>
<tr>
<td>
Placeholder
</td>
<!-- ko foreach: entry_data -->
<td>
<div class=input-group>
<input type=text class=form-control col-sm-2 data-bind=value: entry_hours>
<span class=input-group-addon><a class=comment data-bind=click: function() { $root.modal.comment($data); $root.showModal(); }, css: { 'has-comment': comment.length > 0, 'needs-comment': comment.length == 0 }, attr: { title: comment }><span class=glyphicon glyphicon-comment></span></a></span>
</div>
</td>
<!-- /ko -->
</tr>
</tbody>
</table>
<!-- Modal template -->
<script id=commentsModal class=modal-dialog type=text/html>
<div class=modal-dialog>
<div class=modal-content>
<div class=modal-header>
<button type=button class=close data-bind=click:close aria-hidden=true>×</button>
<h4 data-bind=html:header class=modal-title></h4>
</div>
<div class=modal-body>
<textarea class=form-control rows=3 data-bind=value: $root.modal.comment.comment></textarea>
</div>
<div class=modal-footer>
<button type=button class=btn btn-default data-bind=click:close,html:closeLabel>Close</button>
<button type=button class=btn btn-primary data-bind=click:action,html:primaryLabel id=save-changes>Save changes</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</script>
<!-- Create a modal via custom binding -->
<div data-bind=bootstrapModal:modal class=modal fade id=commentsModal tabindex=-1 role=dialog data-keyboard=false data-backdrop=static></div>
JS:
/* Custom binding for making modals */
ko.bindingHandlers.bootstrapModal = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var props = valueAccessor(),
vm = bindingContext.createChildContext(viewModel);
ko.utils.extend(vm, props);
vm.close = function() {
vm.show(false);
vm.onClose();
};
vm.action = function() {
vm.onAction();
}
ko.utils.toggleDomNodeCssClass(element, modal fade, true);
ko.renderTemplate(commentsModal, vm, null, element);
var showHide = ko.computed(function() {
$(element).modal(vm.show() ? 'show' : 'hide');
});
return {
controlsDescendantBindings: true
};
}
}
var entriesdata = [{entry_id:51794,project_id:2571,user_id:89,entry_data:[{entry_data_id:359192,entry_id:51794,entry_hours:0.00,entry_date:2013-12-22,comment:},{entry_data_id:359193,entry_id:51794,entry_hours:8.00,entry_date:2013-12-23,comment:Test comment},{entry_data_id:359194,entry_id:51794,entry_hours:8.00,entry_date:2013-12-24,comment:Test comment},{entry_data_id:359195,entry_id:51794,entry_hours:0.00,entry_date:2013-12-25,comment:},{entry_data_id:359196,entry_id:51794,entry_hours:8.00,entry_date:2013-12-26,comment:Test comment},{entry_data_id:359197,entry_id:51794,entry_hours:8.00,entry_date:2013-12-27,comment:Test comment},{entry_data_id:359198,entry_id:51794,entry_hours:0.00,entry_date:2013-12-28,comment:}]}];
var projectsdata = [{project_txt:Test Project,project_id:12345}];
var TimeEntriesModel = function(entries, projects) {
var self = this;
self.projects = ko.observableArray(projects);
self.entries = ko.observableArray(ko.utils.arrayMap(entries, function(entry) {
return {
entry_id : entry.entry_id,
project_id : entry.project_id,
user_id : entry.user_id,
entry_data : ko.observableArray(entry.entry_data)
}
}));
self.save = function () {
ko.utils.stringifyJson(self.entries);
}
self.modal = {
header: Add/Edit Comment,
comment: ko.observableArray([{comment: test}]),
closeLabel: Cancel,
primaryLabel: Save,
show: ko.observable(false), /* Set to true to show initially */
onClose: function() {
self.onModalClose();
},
onAction: function() {
self.onModalAction();
}
}
console.log(ko.isObservable(self.modal.comment));
self.showModal = function() {
self.modal.show(true);
}
self.onModalClose = function() {
// alert(CLOSE!);
}
self.onModalAction = function() {
// alert(ACTION!);
self.modal.show(false);
}
}
ko.applyBindings(new TimeEntriesModel(entriesdata, projectsdata));
Fiddle: http://jsfiddle.net/sL3HK/
As you can see in the fiddle, the modal opens with the text box, but I'm unable to figure out how to get the 'comment' text into the modal or update the comment when the 'save' button is pressed.
Any ideas?
Also, I'm very new to Knockout, so if there's anything in there that doesn't look quite right, please feel free to correct me on it.
UPDATE:
I've been fiddling with the code, and have been able to get the comment into the modal, but I've not been able to successfully update it up to this point. And another problem I will eventually run into is that I only want the comment to be updated when Save is clicked, rather than the normal update on blur. I really think I'm going about this the wrong way, but I'm not sure what the right way is. Any more help is greatly appreciated.