llamar - popup javascript ejemplo
Evento de cambio de tamaƱo de ventana angular (13)
Me gustaría realizar algunas tareas basadas en el evento de cambio de tamaño de la ventana (en carga y dinámicamente).
Actualmente tengo mi DOM de la siguiente manera:
<div id="Harbour">
<div id="Port" (window:resize)="onResize($event)" >
<router-outlet></router-outlet>
</div>
</div>
El evento se dispara correctamente
export class AppComponent {
onResize(event) {
console.log(event);
}
}
¿Cómo recupero el ancho y la altura de este objeto de evento?
Gracias.
Aquí hay una mejor manera de hacerlo. Basado en Birowsky''s respuesta Birowsky''s .
Paso 1: Cree un
angular service
con 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
};
};
Paso 2: inyecte el
service
anterior y suscríbase a cualquiera de los
Observables
creados dentro del servicio donde desee recibir el evento de cambio de tamaño de la ventana.
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
});
}
}
Una buena comprensión de la programación reactiva siempre ayudará a superar los problemas difíciles. Espero que esto ayude a alguien.
Basado en la solución de @cgatian, sugeriría la siguiente simplificación:
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
}));
}
}
Uso:
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) { }
}
El siguiente código permite observar cualquier cambio de tamaño para cualquier div dado en Angular.
<div #observed-div>
</div>
luego en el Componente:
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;
}
En Angular2 (2.1.0) uso ngZone para capturar el evento de cambio de pantalla.
Echa un vistazo al ejemplo:
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);
});
};
}
Espero esta ayuda!
Escribí esta biblioteca para encontrar una vez que el cambio del tamaño del límite del componente (redimensionar) en Angular, puede ayudar a otras personas. Puede ponerlo en el componente raíz, hará lo mismo que cambiar el tamaño de la ventana.
Paso 1: importe el módulo
import { BoundSensorModule } from ''angular-bound-sensor'';
@NgModule({
(...)
imports: [
BoundSensorModule,
],
})
export class AppModule { }
Paso 2: agregue la directiva como a continuación
<simple-component boundSensor></simple-component>
Paso 3: reciba los detalles del tamaño del límite
import { HostListener } from ''@angular/core'';
@Component({
selector: ''simple-component''
(...)
})
class SimpleComponent {
@HostListener(''resize'', [''$event''])
onResize(event) {
console.log(event.detail);
}
}
Esta no es exactamente la respuesta a la pregunta, pero puede ayudar a alguien que necesita detectar cambios de tamaño en cualquier elemento.
He creado una biblioteca que agrega eventos
resized
a cualquier elemento:
evento de cambio de tamaño angular
.
Utiliza internamente
ResizeSensor
de las
consultas de elementos CSS
.
Ejemplo de uso
HTML
<div (resized)="onResized($event)"></div>
Mecanografiado
@Component({...})
class MyComponent {
width: number;
height: number;
onResized(event: ResizedEvent): void {
this.width = event.newWidth;
this.height = event.newHeight;
}
}
Hay un servicio ViewportRuler en angular CDK. Se ejecuta fuera de la zona y también funciona con renderizado del lado del servidor.
La forma correcta de hacer esto es utilizar la clase EventManager para vincular el evento. Esto permite que su código funcione en plataformas alternativas, por ejemplo, representación del lado del servidor con 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);
}
}
El uso en un componente es tan simple como agregar este servicio como proveedor a su módulo de aplicación y luego importarlo en el constructor de un componente.
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();
}
}
}
La respuesta de @ Günter es correcta. Solo quería proponer otro método.
También puede agregar el enlace de host dentro del
@Component()
.
Puede colocar el evento y la llamada a la función deseada en la propiedad de metadatos del host de la siguiente manera:
@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
}
}
No he visto a nadie hablando de
MediaMatcher
de
angular/cdk
.
Puede definir un MediaQuery y adjuntarle un oyente; luego, en cualquier lugar de su plantilla (o ts) puede invocar cosas si el Matcher coincide. LiveExample
App.Component.ts
import {Component, ChangeDetectorRef} from ''@angular/core'';
import {MediaMatcher} from ''@angular/cdk/layout'';
@Component({
selector: ''app-root'',
templateUrl: ''./app.component.html'',
styleUrls: [''./app.component.css'']
})
export class AppComponent {
mobileQuery: MediaQueryList;
constructor(changeDetectorRef: ChangeDetectorRef, media: MediaMatcher) {
this.mobileQuery = media.matchMedia(''(max-width: 600px)'');
this._mobileQueryListener = () => changeDetectorRef.detectChanges();
this.mobileQuery.addListener(this._mobileQueryListener);
}
private _mobileQueryListener: () => void;
ngOnDestroy() {
this.mobileQuery.removeListener(this._mobileQueryListener);
}
}
App.Component.Html
<div [class]="mobileQuery.matches ? ''text-red'' : ''text-blue''"> I turn red on mobile mode
</div>
App.Component.css
.text-red {
color: red;
}
.text-blue {
color: blue;
}
fuente: https://material.angular.io/components/sidenav/overview
Sé que esto se preguntó hace mucho tiempo, ¡pero ahora hay una mejor manera de hacerlo! Sin embargo, no estoy seguro de si alguien verá esta respuesta. Obviamente sus importaciones:
import { fromEvent } from "rxjs/observable/fromEvent";
import { Observable } from "rxjs/Observable";
import { Subscription } from "rxjs/Subscription";
Luego en su componente:
resizeObservable$: Observable<Event>
resizeSubscription$: Subscription
ngOnInit() {
this.resizeObservable$ = fromEvent(window, ''resize'')
this.resizeSubscription$ = this.resizeObservable$.subscribe( evt => {
console.log(''event: '', evt)
})
}
¡Entonces asegúrese de darse de baja en destruir!
ngOnDestroy() {
this.resizeSubscription$.unsubscribe()
}
Suponiendo que <600px significa móvil para usted, puede usar este observable y suscribirse a él:
Primero necesitamos el tamaño actual de la ventana. Entonces creamos un observable que solo emite un único valor: el tamaño de la ventana actual.
initial$ = Observable.of(window.innerWidth > 599 ? false : true);
Luego, necesitamos crear otro observable, para saber cuándo se cambió el tamaño de la ventana. Para esto podemos usar el operador "fromEvent". Para obtener más información sobre los operadores de rxjs, visite: rxjs
resize$ = Observable.fromEvent(window, ''resize'').map((event: any) => {
return event.target.innerWidth > 599 ? false : true;
});
Combine estas dos corrientes para recibir nuestro observable:
mobile$ = Observable.merge(this.resize$, this.initial$).distinctUntilChanged();
Ahora puedes suscribirte así:
mobile$.subscribe((event) => { console.log(event); });
Recuerde darse de baja :)
<div (window:resize)="onResize($event)"
onResize(event) {
event.target.innerWidth;
}
o
@HostListener(''window:resize'', [''$event''])
onResize(event) {
event.target.innerWidth;
}
Los objetivos globales admitidos son
window
,
document
y
body
.
Hasta que https://github.com/angular/angular/issues/13248 se implemente en Angular, es mejor que el rendimiento se suscriba a los eventos DOM de forma imperativa y use RXJS para reducir la cantidad de eventos como se muestra en algunas de las otras respuestas.