Asked By: Anonymous
I want to create an attribute to show or hide elements based on some global state.
Example:
<div state='new,unknown'>yadayadayada</div>
This attribute will then transform the div element to be effectively:
<div if.bind="['new','unknown'] | state & signal : 'state-change'">...</div>
The state value converter will convert the array to a boolean.
The goal is if the current global state is any of the provided states, then show the element else hide it.
I don’t want a custom element with compose in it.
Solution
Answered By: Anonymous
Aurelia cheat sheet has an example of naive-if custom attribute. I craft a solution based on it. The only differences are:
- The logic to calculate show or hide (of course)
- Subscribe to the global state too, instead of only
valueChanged
Code:
import {BoundViewFactory, ViewSlot, customAttribute, templateController, inject} from 'aurelia-framework';
import {BindingEngine} from 'aurelia-binding';
import {State} from './state';
@customAttribute('naive-if')
@templateController
@inject(BoundViewFactory, ViewSlot, BindingEngine, State)
export class NaiveIf {
constructor(viewFactory, viewSlot, bindingEngine, state) {
this.show = false;
this.viewFactory = viewFactory;
this.viewSlot = viewSlot;
this.bindingEngine = bindingEngine;
this.state = state;
}
bind() {
this.updateView();
this.subscription = this.bindingEngine.propertyObserver(this.state, 'value')
.subscribe((newValue, oldValue) => this.updateView());
}
unbind() {
if (this.subscription) this.subscription.dispose();
}
valueChanged(newValue) {
this.updateView();
}
updateView() {
let isShowing = this.show;
let showStates = this.value.split(',');
this.show = showStates.indexOf(this.state.value) != -1;
if (this.show && !isShowing) {
let view = this.viewFactory.create();
this.viewSlot.add(view);
} else if (!this.show && isShowing) {
this.viewSlot.removeAll();
}
}
}
Or GistRun