J'aimerais effectuer certaines tâches en fonction de l'événement de redimensionnement de la fenêtre (en charge et de manière dynamique).
Actuellement, j'ai mon DOM comme suit:
<div id="Harbour">
<div id="Port" (window:resize)="onResize($event)" >
<router-outlet></router-outlet>
</div>
</div>
L'événement se déclenche correctement
export class AppComponent {
onResize(event) {
console.log(event);
}
}
Comment récupérer la largeur et la hauteur de cet objet événement?
Merci.
<div (window:resize)="onResize($event)"
onResize(event) {
event.target.innerWidth;
}
ou
@HostListener('window:resize', ['$event'])
onResize(event) {
event.target.innerWidth;
}
Les cibles globales prises en charge sont window
, document
et body
.
Jusqu'à ce que https://github.com/angular/angular/issues/13248 soit implémenté dans Angular, il est préférable pour les performances de s'abonner impérativement aux événements DOM et d'utiliser RXJS pour réduire le nombre d'événements indiqué dans autres réponses.
@ La réponse de Günter est correcte. Je voulais juste proposer encore une autre méthode.
Vous pouvez également ajouter la liaison hôte à l'intérieur de la @Component()
- décorator. Vous pouvez placer l'événement et l'appel de fonction souhaité dans la propriété Host-metadata-property de la manière suivante:
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
Host: {
'(window:resize)': 'onResize($event)'
}
})
export class AppComponent{
onResize(event){
event.target.innerWidth; // window width
}
}
Pour ce faire, utilisez la classe EventManager pour lier l'événement. Cela permet à votre code de fonctionner sur d'autres plates-formes, par exemple le rendu côté serveur avec Angular Universal.
import { EventManager } from '@angular/platform-browser';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { Injectable } from '@angular/core';
@Injectable()
export class ResizeService {
get onResize$(): Observable<Window> {
return this.resizeSubject.asObservable();
}
private resizeSubject: Subject<Window>;
constructor(private eventManager: EventManager) {
this.resizeSubject = new Subject();
this.eventManager.addGlobalEventListener('window', 'resize', this.onResize.bind(this));
}
private onResize(event: UIEvent) {
this.resizeSubject.next(<Window>event.target);
}
}
L'utilisation dans un composant est aussi simple que d'ajouter ce service en tant que fournisseur à votre app.module, puis de l'importer dans le constructeur d'un composant.
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'my-component',
template: ``,
styles: [``]
})
export class MyComponent implements OnInit {
private resizeSubscription: Subscription;
constructor(private resizeService: ResizeService) { }
ngOnInit() {
this.resizeSubscription = this.resizeService.onResize$
.subscribe(size => console.log(size));
}
ngOnDestroy() {
if (this.resizeSubscription) {
this.resizeSubscription.unsubscribe();
}
}
}
Voici une meilleure façon de le faire. Basé sur Birowsky's answer.
Étape 1: Créez un angular service
avec RxJS Observables .
import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject } from 'rxjs';
@Injectable()
export class WindowService {
height$: Observable<number>;
//create more Observables as and when needed for various properties
hello: string = "Hello";
constructor() {
let windowSize$ = new BehaviorSubject(getWindowSize());
this.height$ = (windowSize$.pluck('height') as Observable<number>).distinctUntilChanged();
Observable.fromEvent(window, 'resize')
.map(getWindowSize)
.subscribe(windowSize$);
}
}
function getWindowSize() {
return {
height: window.innerHeight
//you can sense other parameters here
};
};
Étape 2: Injectez la service
ci-dessus et abonnez-vous à l'une des Observables
créées dans le service, où que vous souhaitiez recevoir l'événement de redimensionnement de la fenêtre.
import { Component } from '@angular/core';
//import service
import { WindowService } from '../Services/window.service';
@Component({
selector: 'pm-app',
templateUrl: './componentTemplates/app.component.html',
providers: [WindowService]
})
export class AppComponent {
constructor(private windowService: WindowService) {
//subscribe to the window resize event
windowService.height$.subscribe((value:any) => {
//Do whatever you want with the value.
//You can also subscribe to other observables of the service
});
}
}
Une bonne compréhension de la programmation réactive aidera toujours à surmonter des problèmes difficiles. J'espère que ça aide quelqu'un.
Je sais que cela a été demandé il y a longtemps, mais il existe un meilleur moyen de le faire maintenant! Je ne suis pas sûr si quelqu'un verra cette réponse cependant. Évidemment vos importations:
import { fromEvent } from "rxjs/observable/fromEvent";
import { Observable } from "rxjs/Observable";
import { Subscription } from "rxjs/Subscription";
Puis dans votre composant:
resizeObservable$: Observable<Event>
resizeSubscription$: Subscription
ngOnInit() {
this.resizeObservable$ = fromEvent(window, 'resize')
this.resizeSubscription$ = this.resizeObservable$.subscribe( evt => {
console.log('event: ', evt)
})
}
Alors, assurez-vous de vous désabonner de destroy!
ngOnDestroy() {
this.resizeSubscription$.unsubscribe()
}
En supposant que <600px signifie mobile pour vous, vous pouvez utiliser cet observable et vous y abonner:
Nous avons d’abord besoin de la taille actuelle de la fenêtre. Nous créons donc un observable qui n'émet qu'une seule valeur: la taille de la fenêtre actuelle.
initial$ = Observable.of(window.innerWidth > 599 ? false : true);
Ensuite, nous devons créer une autre observable, afin de savoir quand la taille de la fenêtre a été modifiée. Pour cela, nous pouvons utiliser l'opérateur "fromEvent". Pour en savoir plus sur les opérateurs de rxjs, rendez-vous sur: rxjs
resize$ = Observable.fromEvent(window, 'resize').map((event: any) => {
return event.target.innerWidth > 599 ? false : true;
});
Fusion de ces deux flux pour recevoir notre observable:
mobile$ = Observable.merge(this.resize$, this.initial$).distinctUntilChanged();
Maintenant, vous pouvez vous y abonner comme ceci:
mobile$.subscribe((event) => { console.log(event); });
N'oubliez pas de vous désabonner :)
Basé sur la solution de @cgatian, je suggérerais la simplification suivante:
import { EventManager } from '@angular/platform-browser';
import { Injectable, EventEmitter } from '@angular/core';
@Injectable()
export class ResizeService {
public onResize$ = new EventEmitter<{ width: number; height: number; }>();
constructor(eventManager: EventManager) {
eventManager.addGlobalEventListener('window', 'resize',
e => this.onResize$.emit({
width: e.target.innerWidth,
height: e.target.innerHeight
}));
}
}
Usage:
import { Component } from '@angular/core';
import { ResizeService } from './resize-service';
@Component({
selector: 'my-component',
template: `{{ rs.onResize$ | async | json }}`
})
export class MyComponent {
constructor(private rs: ResizeService) { }
}
Ce n'est pas une réponse exacte à la question, mais cela peut aider quelqu'un qui doit détecter des changements de taille sur n'importe quel élément.
J'ai créé une bibliothèque qui ajoute un événement resized
à un élément - Evénement de redimensionnement angulaire.
Il utilise en interne ResizeSensor
de CSS Element Queries .
<div (resized)="onResized($event)"></div>
@Component({...})
class MyComponent {
width: number;
height: number;
onResized(event: ResizedEvent): void {
this.width = event.newWidth;
this.height = event.newHeight;
}
}
J'ai écrit cette bibliothèque pour trouver une fois le changement de taille de composant (redimensionnement) dans Angular, que cela puisse aider d'autres personnes. Vous pouvez le mettre sur le composant racine, fera la même chose que redimensionner une fenêtre.
Etape 1: Importer le module
import { BoundSensorModule } from 'angular-bound-sensor';
@NgModule({
(...)
imports: [
BoundSensorModule,
],
})
export class AppModule { }
Étape 2: Ajouter la directive comme ci-dessous
<simple-component boundSensor></simple-component>
Étape 3: Recevez les détails de la taille de la limite
import { HostListener } from '@angular/core';
@Component({
selector: 'simple-component'
(...)
})
class SimpleComponent {
@HostListener('resize', ['$event'])
onResize(event) {
console.log(event.detail);
}
}
Sur Angular2 (2.1.0), j'utilise ngZone pour capturer l'événement de changement d'écran.
Regardez l'exemple:
import { Component, NgZone } from '@angular/core';//import ngZone library
...
//capture screen changed inside constructor
constructor(private ngZone: NgZone) {
window.onresize = (e) =>
{
ngZone.run(() => {
console.log(window.innerWidth);
console.log(window.innerHeight);
});
};
}
J'espère que cette aide!
Il existe un service ViewportRuler dans angular CDK. Il fonctionne en dehors de la zone et fonctionne également avec le rendu côté serveur.
Le code ci-dessous permet d'observer tout changement de taille pour un div donné en angulaire.
<div #observed-div>
</div>
puis dans le composant:
oldWidth = 0;
oldHeight = 0;
@ViewChild('observed-div') myDiv: ElementRef;
ngAfterViewChecked() {
const newWidth = this.myDiv.nativeElement.offsetWidth;
const newHeight = this.myDiv.nativeElement.offsetHeight;
if (this.oldWidth !== newWidth || this.oldHeight !== newHeight)
console.log('resized!');
this.oldWidth = newWidth;
this.oldHeight = newHeight;
}