skip to Main Content

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


  1. As mentioned in MDN, initial-value is required for @property to be valid, unless the value for syntax is *, which is not your case.

    The @property rule must include both the syntax and inherits descriptors; if either are missing, the entire @property rule is invalid and ignored. The initial-value descriptor is also required, unless the syntax is the * universal syntax definition (e.g., syntax: "*"). If the initial-value descriptor is required and omitted, the entire @property rule is invalid and ignored.

    /*Valid example*/
    @property --grid-columns {
      syntax: "<integer>";
      inherits: false;
      initial-value: 1;
    }
    

    In fact, if the --grid-columns is correctly defined by @property, the fallback value 1 in var(--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.

    Login or Signup to reply.
  2. 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,

    The initial-value descriptor is also required, unless the syntax is the * universal syntax definition (e.g., syntax: "*").

    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.

    @property --grid-row-gap {
      syntax: "<length>";
      inherits: false; /* I generally prefer the `true` inheritance behavior, but it's up to you */
      initial-value: 0px; /* doesn't really matter */
    }
    
    .table-container {
      /* an internal prop with a default fallback value */
      --_row-gap: var(--grid-row-gap, 0px);
    
      /* ✂️ */
    
      row-gap: var(--_row-gap);
    }
    

    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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search