web-dev-qa-db-fra.com

Comment obtenir la largeur d'un élément (DOM) dans Angular2

il y a quelques fils similaires mais je ne pouvais pas trouver de réponse appropriée à mes besoins. Donc, cet accès direct DOM doit être strictement évité dans angular2. Je me demande simplement quelle est la meilleure pratique pour cela.

Ce que je ne veux pas réaliser, c'est le redimensionnement d'un élément en fonction de la largeur actuelle.

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>

Connexes: https://github.com/angular/angular/issues/6515

28
kkern

Je ne connais pas le moyen d'obtenir la largeur de l'élément Host sans accéder à nativeElement, mais vous pouvez utiliser les paramètres suivants:

@HostListener('window:resize', ['$event.target']) 
onResize() { 
  this.resizeWorks();
}

@HostBinding('style.height.px')
elHeight:number;

private resizeWorks(): void {
  this.elHeight = this.el.nativeElement.width;
}

Si vous pouvez ajouter un élément dans votre modèle de composants comme

<div style="width: 100%;" #div (window:resize)="elHeight = div.getBoundingClientRect()">
  <!-- your template here -->
</div>

alors cela fonctionnerait sans accès direct au DOM (mais pas après init).

17
Günter Zöchbauer

J'ai essayé la solution @ GünterZöchbauer et l'ai affinée. Vous n'avez pas besoin de HostListener pour obtenir les limites de div. Comme avec 'click' ou un autre événement (event) = "function ()", cette fonction sera activée. J'espère que quelqu'un trouvera cela utile.

<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) - il s'agit de la variable nécessaire pour obtenir la cible de mesure. Il ne doit pas nécessairement s'agir du même nom que element, il peut s'agir de n'importe quel nom.

Une autre façon d’obtenir des dimensions d’élément consiste à utiliser la classe ElementRef de Angular Core, mais vous devez ensuite trouver cet élément enfant qui a les propriétés width et height. Je l’ai utilisé dans Angular 2 Cartes pour obtenir la largeur et la hauteur du conteneur, mais j’ai découvert que, en utilisant cette méthode, je devais trouver dans l’élément element tree qui possédait ces propriétés et qu’il s’agissait du deuxième enfant de l’élément racine. - est juste une classe avec la hauteur et la largeur que j'ai faite pour contenir ces propriétés.

<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
    };
}
10
Imants Volkovs

J'ai testé de cette façon et tout simplement travaillé! Il semble que la liaison a fait ce travail.

<div #foto [style.height.px]="foto.getBoundingClientRect().width / 2">
2
Charleston

Vous pouvez obtenir la largeur du composant lui-même si celui-ci a une propriété d'affichage définie (telle que "bloc" dans l'exemple ci-dessous). Notez que vous devriez être capable de définir ce style (en utilisant dom shadowing):

:Host {
    display:block;
}

Si vous n'utilisez pas l'observation de dom (Ionic 2-3):

my-component {
    display:block;
}

Voici le contrôleur (exposant la largeur en tant qu'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;
    }
}
1
Flavien Volken