Reputation: 10561
I'm looking for a way to one-way bind a checkbox in aurelia, whilst still allowing the checkbox to accept a click from the user.
Assume a view similar to the following that displays one of a list of selectable items:
<template>
<div click.trigger="selected()">
<label......>${vm.code}</label>
<label....>${vm.description}</label>
<img...../>
<input type="checkbox" checked.one-way="vm.selected"></input>
</div>
</template>
The user should be able to click anywhere in the view to select the item, thus the click.trigger="selected()"
is attached to the container. Within selected()
, the vm.selected
property that the checkbox is bound to is updated.
The checkbox should also be clickable as well, but should allow selection to be controlled by the selected()
method.
readonly
can not be used on the input control for the checkbox
as that is used to control input.value
and in this case it is the checked
property that is of interest.
Calling preventDefault
on the event args disables default checkbox checked behavior, which can be achieved in Aurelia by returning false from the click delegate. That would require attaching another handler to the input control, and has the problem that the click gets handled by the input control and doesn't bubble up to the delegate attached to the container (selected()
) to actually control selection.
Maybe there is another approach to this that I am missing, one that I was considering was to use two font-awesome icons that look like checked and unchecked checkboxes and switch between the two based on the value of vm.selected.
Upvotes: 3
Views: 4095
Reputation: 14995
On the delegation of events this answer does solve the issue if you are not using a checkbox but the browser prevents the state from toggling on the checkbox so as we discussed the best approach is probably to use an icon or sprite to show the 'state' of the checked piece since the control should be one-way only, which can be accomplished like this -
<i class="fa fa-${this.selected ? 'check-square-o' : 'square-o'}"></i>
If we use delegate
instead of trigger
then our event bubbles and we can handle it a bit more gracefully and prevent the state from changing -
<div click.delegate="clicked()">
<input type="checkbox" click.delegate="clicked(false)" checked.one-way="vm.selected" />
</div>
And then in our view model we can handle the click event that bubbles -
clicked(event){
if (event !== false) {
// do something
} else {
return false;
}
}
This isn't a perfect solution but it should prevent the event from occurring which changes the state of the control but still allow the event to take place at the div level.
Upvotes: 3