Reputation: 107
I have created a custom element based on bootstrap-toggle that looks as follows:
toggle.ts:
import {bindingMode, bindable, customElement} from "aurelia-framework";
@customElement('toggle')
export class Toggle {
@bindable({ defaultBindingMode: bindingMode.twoWay }) checked;
input;
attached() {
$(this.input).bootstrapToggle();
}
}
toggle.html:
<template>
<require from="bootstrap-toggle/css/bootstrap2-toggle.min.css"></require>
<require from="bootstrap-toggle"></require>
<input ref="input" data-toggle="toggle" type="checkbox" checked.bind="checked">
</template>
The problem ist that the binding for the checked
attribute is never updated when the switch is toggled via the UI. I am aware of the common pitfalls when using Aurelia with jQuery based components as described here. However, in my understanding this should not apply to bootstrap-toggle, as this component triggers a change event on the input
element on toggle. I have verified that this change event bubbles up to my custom component.
The workaround I currently use is this:
toggle.ts:
import {bindingMode, bindable, customElement} from "aurelia-framework";
@customElement('toggle')
export class Toggle {
@bindable({ defaultBindingMode: bindingMode.twoWay }) checked;
input;
attached() {
$(this.input).bootstrapToggle().on('change', (event) => this.checked = event.target.checked);
}
}
However, I do not understand why this should be necessary. I have created a test project based on Aurelia's navigation-skeleton that can be downloaded here.
I would appreciate some help in understanding this!
Upvotes: 0
Views: 561
Reputation: 8047
The event listener used by jquery uses the capture phase and presumably does preventDefault
or something among those lines that prevents the event from bubbling back up.
The change event dispatched by this line: if (!silent) this.$element.change()
does not actually propagate to the bubble phase. Aurelia uses the bubble phase and thus never receives the event.
You can see the difference if you dispatch one manually in your browser console like so:
document.querySelector("[data-toggle]").dispatchEvent(new CustomEvent("change"));
This will result in the appropriate listeners being invoked and updates the bound property.
What this line does: .on('change', (event) => this.checked = event.target.checked);
is also add a listener on the capture phase which then of course works. But then you might as well remove the checked.bind='checked'
because that effectively does nothing.
There isn't necessarily any straight-forward fix for this, these CSS frameworks tend to just have very intrusive javascript. I would generally recommend against including their scripts and look for (or implement) them natively in Aurelia. It's very easy to do so and just works a lot better.
Upvotes: 0