I’m working on a angular-project.
I have the following component class:
export class ReservationTableComponent implements OnInit {
@Input({ required: true }) table!: Table;
@Input() set colMinWidth(value: string) {
this.renderer.setStyle(this.el.nativeElement, "--grid-column-min-width", value);
}
@Input() set colMaxWidth(value: string) {
this.renderer.setStyle(this.el.nativeElement, "--grid-column-max-width", value);
}
@Input() set rowGap(value: string) {
this.renderer.setStyle(this.el.nativeElement, "--grid-row-gap", value);
}
@Input() set colGap(value: string) {
this.renderer.setStyle(this.el.nativeElement, "--grid-col-gap", value);
}
@Input() selectedCells: Cell[] = [];
@Output() onSingleCellClicked: EventEmitter<Cell> = new EventEmitter();
constructor(private el: ElementRef, private renderer: Renderer2) { }
ngOnInit(): void {
this.renderer.setStyle(this.el.nativeElement, "--grid-flow", this.table.direction === LineDirection.ROW ? "row" : "column");
this.renderer.setStyle(this.el.nativeElement, "--grid-columns", this.table.longestCol);
this.renderer.setStyle(this.el.nativeElement, "--grid-rows", this.table.longestRow);
}
And the css for the component:
@property --grid-flow {
syntax: "row | column";
inherits: false;
initial-value: column;
}
@property --grid-columns {
syntax: "<integer>";
inherits: false;
}
@property --grid-rows {
syntax: "<integer>";
inherits: false;
}
@property --grid-column-max-width {
syntax: "<length> | max-content | min-content | fit-content(<length-percentage>)";
inherits: false;
}
@property --grid-row-gap {
syntax: "<length>";
inherits: false;
}
@property --grid-col-gap {
syntax: "<length>";
inherits: false;
}
.table-container {
display: grid;
grid-template-columns: repeat(
var(--grid-columns, 1),
minmax(min-content, var(--grid-column-max-width, max-content))
);
grid-template-rows: repeat(var(--grid-rows), auto);
grid-auto-flow: var(--grid-flow, column);
box-sizing: border-box;
width: 100%;
row-gap: var(--grid-row-gap, 0px);
column-gap: var(--grid-col-gap, 0px);
align-items: stretch;
overflow-x: auto;
}
Now if I set the –grid-flow property inside the component class it is ignored, or overwriten by the inital-value of the property.
If I remove the inital-value: column from the property, everything works fine. If the inital-value ist set, changes on the input doesn’t take any effect.
If I don’t set a inital-value I got some error:
An @property rule is ignored because it contains an invalid property or is missing a required one:
initial-value
How to solve this situation, and why does this happen?
Does anyone have an idea?
Thanks 😀
2
Answers
As mentioned in MDN, initial-value is required for
@property
to be valid, unless the value forsyntax
is*
, which is not your case.In fact, if the
--grid-columns
is correctly defined by@property
, the fallback value 1 invar(--grid-columns, 1)
in your code will never be used. Fallback value is not for this, but for when the custom property is not defined. A valid custom-property, whether or not defined by @property, always has a initial value.Love seeing this kind of CSS-based component API!
The main thing is that
initial-value
is required in most cases for@property
. As MDN says,To get around this issue, I generally use the pattern of having an internal custom prop that gets the value of the public variable when its set, but falls back to a default value.
Now, when
--grid-row-gap
is set from the outside, it’ll use that value, but if it’s not it’ll be--_row-gap
’s fallback value.