JSFiddle - React, Tailwind, and code Playground
HTML
<script src="http://code.jquery.com/jquery-1.9.0.min.js"></script>
<script src="http://ajax.microsoft.com/ajax/jquery.ui/1.10.0/jquery-ui.js"></script>
<link rel="stylesheet" href="http://ajax.microsoft.com/ajax/jquery.ui/1.8.5/themes/redmond/jquery-ui.css">
<script src="http://knockoutjs.com/downloads/knockout-3.3.0.js"></script>
<div id="template"> <a href="#" data-bind="koCommandButton: commandObject"></a>
<a href="#"
data-bind="koCommandButton: staticCommand"></a> <a href="#" data-bind="koCommandButton: dynamicObservableCommand"></a>
<label
for="canExecute">Enable / Disable Buttons</label>
<input type="checkbox" id="canExecute"
/>
<div id="content">
<div id="commandObjectDetails" class="details" style="display:none;">
<p>This command is an implementation of a js Command class with a ko.observable()
text property and static canExecute and execute methods.</p>
</div>
<div id="staticObjectDetails" class="details" style="display:none">
<p>This staticCommand is an object literal without any ko.observable() properties
of any kind.</p>
</div>
<div id="dynamicObservableObjectDetails" class="details" style="display:none">
<p>The dynamicObservable command is an object literal and uses a ko.computed()
canExecute() method and ko.observable() text property.</p>
</div>
</div>
</div>
JavaScript
// I still need to figure out how to pass the viewModel to the canExecute() function when it is a ko.computed() function.
ko.bindingHandlers.koCommandButton = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContenxt) {
$(element).button();
var valueUnwrapped = ko.utils.unwrapObservable(valueAccessor());
$(element).click(function () {
valueUnwrapped.execute(viewModel);
});
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var valueUnwrapped = ko.utils.unwrapObservable(valueAccessor());
if (ko.isObservable(valueUnwrapped.text)) {
text = ko.utils.unwrapObservable(valueUnwrapped.text());
} else {
text = valueUnwrapped.text || "[text]";
}
$(element).text(text);
if (valueUnwrapped.canExecute()) {
$(element).button("enable");
} else {
$(element).button("disable");
}
}
};
function Command(options) {
var defaults = {
canExecute: function (data) {
return true;
},
execute: function (data) {
alert("No command execution function has been assigned.");
},
text: "[text]"
};
var settings = $.extend({}, defaults, options);
var api = {
text: ko.observable(settings.text),
canExecute: ko.computed(settings.canExecute),
execute: settings.execute
};
return api;
}
function ViewModel() {
var isChecked = ko.observable(false);
function hideDetails() {
$(".details").hide();
}
var api = {
text: ko.observable("title"),
isChecked: isChecked,
commandObject: new Command({
...