I'm having the following problem: I have a list of items, any of which a user can click on to edit. At this time, a bootstrap modal dialog shows with fields for each of the editable values. I'm updating the values for the fields from an underlying Knockout viewmodel, so when the user edits an item on the modal dialog, they can see the field being modified in the background. So, the modifying currently works fine. However, when the dialog first opens, it doesn't have the values from the item the user selected; instead, it has the values that were loaded previously. But, when the user starts to edit a field, it instantly updates to what the value is supposed to be, and allows the user to continue editing the correct field. Not sure what's going on here.
Here is my modal:
<script id="myModal" type="text/html">
<div class="modal-header">
<button type="button" class="close" data-bind="click: close" aria-hidden="true">×</button>
<h3 data-bind="html: header"></h3>
</div>
<div class="modal-body">
<div class="form-group">
<label>First Name</label>
<input type="text" data-bind="value: modal.firstName, valueUpdate: 'afterkeydown'" class="form-control" />
<label>Last Name</label>
<input type="text" data-bind="value: modal.lastName, valueUpdate: 'afterkeydown'" class="form-control" />
<label>Phone</label>
<input type="text" data-bind="value: modal.phone, valueUpdate: 'afterkeydown'" class="form-control" />
<label>Email</label>
<input type="text" data-bind="value: modal.email, valueUpdate: 'afterkeydown'" class="form-control" />
</div>
</div>
<div class="modal-footer">
<a href="#" class="btn" data-bind="click: close, html: closeLabel"></a>
<a href="#" class="btn btn-primary" data-bind="click: action, html: primaryLabel"></a>
</div>
</script>
<!-- Create a modal via custom binding -->
<div data-bind="bootstrapModal: modal" data-keyboard="false" data-backdrop="static"></div>
Here is the part where the list is populated via knockout:
<ul data-bind="foreach: tasks">
<li>
<div style="border:double">
<div>
<label data-bind="text: firstName"></label>
</div>
<div>
<label data-bind="text: lastName"></label>
</div>
<div>
<label data-bind="text: phone"></label>
</div>
<div>
<label data-bind="text: email"></label>
</div>
<div>
<button data-bind="click: editI.bind(this)">Edit</button>
@*<button data-bind="click: $parent.removeUser">Delete</button>*@
</div>
</div>
</li>
</ul>
<form @*data-bind="submit: addUser"*@>
<button type="submit">Add User</button>
</form>
<button @*data-bind="click: save"*@>Save</button>
Here is where I set the modal values, which works, when the knockout viewmodel is loaded:
viewModel.modal = {
header: ko.observable("This is a modal"),
firstName: ko.observable("a"),
lastName: ko.observable("a"),
phone: ko.observable("a"),
email: ko.observable("a"),
body: ko.observable("test body"),
closeLabel: "Close",
primaryLabel: "Do Something",
show: ko.observable(false), /* Set to true to show initially */
onClose: function () {
viewModel.onModalClose();
},
onAction: function () {
viewModel.onModalAction();
}
Finally, here is the edit function that gets called when the modal is opened. This is where things go awry. Item elements are set to the modal viewmodel, but aren't shown in the modal until a user starts editing that item...then, bam, the item shows in the field.
self.editI = function (item) {
viewModel.modal.body = item.email;
viewModel.modal.firstName = item.firstName;
viewModel.modal.lastName = item.lastName;
viewModel.modal.phone = item.phone;
viewModel.modal.email = item.email;
prevState = item;
viewModel.modal.show(true);
Note: I've found a couple of SO posts similar to this one: how to destroy bootstrap modal window completely? They haven't really helped though.