Это вариант отличного обработчика связывания RP Niemeyer, который полезен для другого сценария.
Чтобы разрешить редактирование сущности, вы можете создать <div>
с элементами управления редакцией и использоватьwith
привязка, которая зависит от наблюдаемой, сделанной специально для издания.
Например, чтобы разрешить издание person
, вы можете создать и наблюдать как, например, editedPerson
, и создатьdiv с элементами управления выпуском, с такой привязкой:
data-bind="with: editedPerson"
Когда вы добавляете человека в наблюдаемую команду lke, так:
vm.editedPerson(personToEdit);
привязка делает div
видимым.Когда вы закончите издание, вы можете установить наблюдаемое на ноль, например,
vm.editedPerson(null);
и div
закроется.
Мой вариант привязки RP Niemeyer позволяет автоматически показывать этоdiv внутри диалогового окна jQuery UI.Чтобы использовать его, вам просто нужно сохранить исходную привязку with
и указать параметры диалога jQuery UI, например, так:
data-bind="with: editedPerson, withDialog: {/* jQuery UI dialog options*/}"
Вы можете получить код моего обработчика привязки и увидеть его в действии здесь:
http://jsfiddle.net/jbustos/dBLeg/
Вы можете легко изменить этот код, чтобы иметь разные значения по умолчанию для диалога, и даже сделать эти значения по умолчанию настраиваемыми, заключив обработчик в модуль js и добавив открытыйфункция конфигурации, чтобы изменить его.(Вы можете добавить эту функцию в обработчик привязки, и она будет продолжать работать).
// 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: false,
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),
$el = $(element),
dialog = $el.data("uiDialog") || $el.data("dialog");
//don't call open/close before initilization
if (dialog) {
$el.dialog(shouldBeOpen ? "open" : "close");
}
}
};
var person = function() {
this.name = ko.observable(),
this.age = ko.observable()
}
var viewModel = function() {
label= ko.observable('dialog test');
editedPerson= ko.observable(null);
clearPerson= function() {
editedPerson(null);
};
newPerson= function() {
editedPerson(new person());
};
savePerson= function() {
alert('Person saved!');
clearPerson();
};
return {
label: label,
editedPerson: editedPerson,
clearPerson: clearPerson,
newPerson: newPerson,
savePerson: savePerson,
};
}
var vm = viewModel();
ko.applyBindings(vm);
.header {
font-size: 16px;
font-family: sans-serif;
font-weight: bold;
margin-bottom: 20px;
}
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script>
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/themes/base/jquery-ui.css" rel="stylesheet"/>
<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"/><br/>
Age:<br/><input type="text" data-bind="value: $data.age"/><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>