jquery ui dialog + knockoutjs + with
Variation on http://jsfiddle.net/rniemeyer/SnPdE/ -- Allows to use a with to open/close a dialog depending on an observable being null or not.
HTML
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/themes/base/jquery-ui.css">
<script src="http://knockoutjs.com/downloads/knockout-2.2.1.js"></script>
<h1 class="header" data-bind="text: label"></h1>
<div id="dialog" data-bind="with: editedPerson, withDialog: {autoOpen: false, title: 'Dialog test', close: function() { alert('closing');} }">
Person editor<br/>
Name:<br/><input type="text" data-bind="value: $data.name"></input><br/>
Age:<br/><input type="text" data-bind="value: $data.age"></input><br/>
<button data-bind="click: $parent.savePerson">Ok</button>
<button data-bind="click: $parent.clearPerson">Cancel</button>
</div>
<div>
<button data-bind="click: clearPerson">Clear person</button>
<button data-bind="click: newPerson">New person</button>
</div>
<hr/>
<div data-bind="text: ko.toJSON($root)"></div>
CSS
.header {
font-size: 16px;
font-family: sans-serif;
font-weight: bold;
margin-bottom: 20px;
}
JavaScript
// Variation on Niemeyer's http://jsfiddle.net/rniemeyer/SnPdE/
/*
This binding works in a simple way:
1) bind an observable using "with" binding
2) set the dialog options for the ui dialog using "withDialog" binding (as you'd do with an standard jquery UI dialog) Note that you can specify a "close" function in the options of the dialog an it will be invoked when the dialog closes.
Once this is done:
- when the observable is set to null, the dialog closes
- when the observable is set to something not null, the dialog opens
- when the dialog is cancelled (closed with the upper right icon), the binded observable is closed
Please, note that you can define the defaults for your binder. I recommend setting here the modal state, and the autoOpen to false.
*/
ko.bindingHandlers.withDialog = {
init: function(element, valueAccessor, allBindingsAccessor) {
var defaults = {
modal: true,
autoOpen: false,
};
var options = ko.utils.unwrapObservable(valueAccessor());
//do in a setTimeout, so the applyBindings doesn't bind twice from element being copied and moved to bottom
$.extend(defaults, options)
setTimeout(function() {
var oldClose = options.close;
defaults.close = function() {
if (options.close) options.close();
allBindingsAccessor().with(null);
};
$(element).dialog(defaults);
}, 0);
//handle disposal (not strictly necessary in this scenario)
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$(element).dialog("destroy");
});
},
update: function(element, valueAccessor, allBindingsAccessor) {
var shouldBeOpen = ko.utils.unwrapObservable(allBindingsAccessor().with),
...