javascript - elementref - viewchild angular 6
Cómo obtener el ancho del elemento(DOM) en Angular2 (4)
Hay algunos hilos similares pero no pude encontrar una respuesta adecuada para mis necesidades. Para que el acceso directo a DOM se evite estrictamente en angular2, me pregunto cuál es la mejor práctica para esto.
Lo que no voy a lograr es un cambio de tamaño de un elemento basado en el ancho actual.
workitemresize.component.ts
import { Directive, ElementRef, HostListener, Renderer, Input } from ''@angular/core'';
@Directive({
selector: ''[workItemResize]''
})
export class WorkItemResizeDirective implements ngAfterViewInit {
private el: HTMLElement;
private renderer: Renderer;
constructor(el: ElementRef, public renderer: Renderer)
{
this.el = el.nativeElement;
this.renderer = renderer;
}
@HostListener(''window:resize'', [''$event.target''])
onResize()
{
this.resizeWorks();
}
ngAfterViewInit() {
this.resizeWorks();
}
private resizeWorks(): void {
this.renderer.setElementStyle(this.el, ''height'', this.el.width); // <-- doesn''t work I kow that this.el.width doesn''t exist but just for demonstration purpose
this.renderer.setElementStyle(this.el, ''height'', ''500''); // <-- works
}
}
projects.template.html
<div class="posts row">
<div class="work-item col-xs-12 col-sm-6 col-no-padding" workItemResize *ngFor="let post of posts">
<!-- show some fancy image -->
<div class="img" [ngStyle]="{''background-image'':''url(''+post.better_featured_image.source_url+'')''}"></div>
</div>
</div>
Relacionados: https://github.com/angular/angular/issues/6515
¡Probé de esta manera y simplemente trabajé! Parece que la encuadernación hizo este trabajo.
<div #foto [style.height.px]="foto.getBoundingClientRect().width / 2">
No conozco una forma de obtener el ancho del elemento host sin acceder a nativeElement
pero la configuración se puede hacer como:
@HostListener(''window:resize'', [''$event.target''])
onResize() {
this.resizeWorks();
}
@HostBinding(''style.height.px'')
elHeight:number;
private resizeWorks(): void {
this.elHeight = this.el.nativeElement.width;
}
Si puede agregar un elemento dentro de su plantilla de componentes como
<div style="width: 100%;" #div (window:resize)="elHeight = div.getBoundingClientRect()">
<!-- your template here -->
</div>
entonces esto funcionaría sin acceso directo a DOM (pero no después de init).
Probé la solución @ GünterZöchbauer y la refiné. No necesita HostListener para obtener los límites de div. Al igual que con ''clic'' u otro evento (evento) = "función ()", se activará esta función. Espero que alguien encuentre esto útil.
<div #div (window:resize)="onResize(div.getBoundingClientRect())">
<!-- your template here -->
</div>
onResize() {
this.resizeWorks();
}
@HostBinding(''style.height.px'') elHeight:number;
private resizeWorks(): void {
this.elHeight = this.el.nativeElement.width;
}
(#div): esta es una variable necesaria para obtener el objetivo de medición. No tiene que ser el mismo nombre que el elemento, puede ser cualquier nombre.
Otra forma de obtener las dimensiones del elemento es usar la clase ElementRef de Angular Core, pero luego tienes que encontrar ese elemento secundario que tenga propiedades de ancho y alto. Utilicé esto en Angular 2 Maps para obtener el ancho y la altura del contenedor, pero descubrí que, utilizando este método, tenía que encontrar en el elemento del árbol de elementos que tenía estas propiedades y era el segundo hijo del elemento raíz. Es mas desordenado ElementDimensions: es solo una clase con altura y anchura que hice para contener esas propiedades.
<div (window:resize)="onResize()">
<!-- your template here -->
</div>
private getContainerDimensions(): ElementDimensions{
var rootElement = this.elementRef.nativeElement;
var childElement = rootElement.firstElementChild;
var contentElement = childElement.firstElementChild;
return {
height:contentElement.clientHeight,
width: contentElement.clientWidth
};
}
Puede obtener el ancho del componente en sí mismo si ese tiene una propiedad de visualización definida (como "bloque" en el siguiente ejemplo). Tenga en cuenta que debería poder definir este estilo (utilizando dom shadowing):
:host {
display:block;
}
Si no está utilizando dom shadowing (Ionic 2-3):
my-component {
display:block;
}
Aquí está el controlador (exponiendo el ancho como un observable):
import {AfterViewInit, Component, ElementRef, HostListener, Input} from ''@angular/core'';
import {Subject} from ''rxjs/Subject'';
@Component({
selector: ''my-component'',
template: ''{{$width|async}}'',
style: ''my-component {display: block;}''
})
export class MyComponent implements AfterViewInit {
@Input() public gridWidth: number;
private $width: Subject<number> = new Subject();
constructor(private elementRef: ElementRef) {
}
public ngAfterViewInit(): void {
this.emitWidth();
}
@HostListener(''window:resize'', [''$event.target''])
public onResize(): void {
this.emitWidth();
}
private emitWidth(): void {
this.$width.next(this.getWidth());
}
private getWidth(): number {
return this.getNativeElement().clientWidth;
}
private getNativeElement(): HTMLElement {
return this.elementRef.nativeElement;
}
}