Recently, I have been delving into Aurelia and encountering a data binding issue related to a custom attribute.
I've crafted a custom attribute named square
(inspired by examples from the "Templating:Custom Attributes" guide on the Aurelia website):
square.ts:
import { bindable, autoinject } from "aurelia-framework";
@autoinject
export class SquareCustomAttribute {
@bindable sideLength = "100px";
@bindable color = "red";
constructor(private element: Element) {
this.sideLengthChanged(this.sideLength);
this.colorChanged(this.color);
}
sideLengthChanged(newValue: string) {
if (this.element instanceof HTMLElement) {
this.element.style.width = this.element.style.height = newValue;
}
}
colorChanged(newValue: string) {
if (this.element instanceof HTMLElement) {
this.element.style.backgroundColor = newValue;
}
}
}
I want to make this custom attribute usable without explicitly binding it, allowing it to default to predetermined values. For example, in this consuming view:
app.html:
<template>
<require from="./square"></require>
<div square></div>
</template>
The above code functions as intended, rendering a square with 100px sides and a red background.
However, complications arise when designating the color
property of SquareCustomAttribute
as the primary property using @bindable
's parameters like so:
Updated square.ts:
import { bindable, autoinject } from "aurelia-framework";
@autoinject
export class SquareCustomAttribute {
@bindable sideLength = "100px";
@bindable({ primaryProperty: true }) color = "red";
constructor(private element: Element) {
this.sideLengthChanged(this.sideLength);
this.colorChanged(this.color);
}
sideLengthChanged(newValue: string) {
if (this.element instanceof HTMLElement) {
this.element.style.width = this.element.style.height = newValue;
}
}
colorChanged(newValue: string) {
if (this.element instanceof HTMLElement) {
this.element.style.backgroundColor = newValue;
}
}
}
Unexpectedly, setting color
as the primary property triggers the colorChanged
callback twice: first within the constructor with the default value, then again during some phase of initialization with an empty value.
How can this redundant invocation of the colorChanged
callback be avoided to ensure the default value remains intact without explicit binding or supplying a value for the square
attribute in the consuming view's HTML markup?