Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

All properties on nativeElement.style are empty

I am trying to create a select that will resize to the width of the selected item.

Here's the implementation in jQuery/Javascript: Drop down list width fit selected item text

The problem I'm having is that the styles are always empty. If I try to set the mainSelectElement to hiddenSelectElement, it almost disappears. The reason is that nativeElement.style.width is blank. I logged the style property to the console, and every property is blank. We also have global styles applied to select, and those are not appearing either.

Does anyone know why my styles are blank? Does this have something to do with the shadow DOM? And best of all, any solutions?

import { Component, Input, Output, EventEmitter, forwardRef, ViewChild, ElementRef, Renderer } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

const SELECT_RESIZE_VALUE_ACCESSOR: any = {
  provide: NG_VALUE_ACCESSOR,
  useClass: forwardRef(() => SamSelectResizableComponent),
  multi: true
}

@Component({
  selector: 'sam-select-resizable',
  template: `
    <select #mainSelectElement [ngModel]="selected" (ngModelChange)="updateSelected($event)">
      <ng-content></ng-content>
    </select>

    <select #hiddenSelectElement>
      <option >{{selected}}</option>
    </select>
  `,
  providers: [
    SELECT_RESIZE_VALUE_ACCESSOR
  ]
})
export class SamSelectResizableComponent implements ControlValueAccessor {

  @ViewChild('hiddenSelectElement') hiddenSelectElement: ElementRef;
  @ViewChild('mainSelectElement') mainSelectElement: ElementRef; 

  public selected: any;

  private onChangeCallback: (_: any) => void = (_: any) => {};
  private onTouchedCallback: () => void = () => {};

  get value(): any {
    return this.selected;
  }

  set value(val: any) {
    if (val !== this.selected) {
      this.selected = val;
      this.onChangeCallback(this.selected);
    }
  }

  constructor(private renderer: Renderer) {}

  updateSelected(event) {
    this.selected = event;
    const hiddenWidth = this.hiddenSelectElement.nativeElement.style.width;
    this.renderer.setElementStyle(this.mainSelectElement.nativeElement, 'width', hiddenWidth);
  }

  writeValue(value: any) {
    if (value !== this.selected) {
      this.selected = value;
      this.onChangeCallback(this.selected);
    }
  }

  registerOnChange(fn: any) {
    this.onChangeCallback = fn;
  }

  registerOnTouched(fn: any) {
    this.onTouchedCallback = fn;
  }
}
like image 446
Colin Alford Avatar asked Jan 04 '23 06:01

Colin Alford


1 Answers

Here is some nice way to fetch the styles once they are applied. Initially all the style properties are empty for any HTML element.

window.getComputedStyle() may resolve your issue.

// fetch styles for an element
style = window.getComputedStyle(hiddenSelectElement.nativeElement, null);

// fetch the property values for any style attribute
console.log(style.getPropertyValue("width"));

For pseudo elements like ::before and ::after

// fetch styles for an element
style = window.getComputedStyle(hiddenSelectElement.nativeElement, ':before');

// fetch the property values for any style attribute
console.log(style.getPropertyValue("width"));

Reference : https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle

like image 71
Amit Chigadani Avatar answered Jan 06 '23 19:01

Amit Chigadani