page ejemplo change angular responsive-design angular2-routing angular2-directives

ejemplo - Cómo hacer componentes sensibles en Angular2.



page title angular 4 (2)

Estoy entrando en Angular2. Mi objetivo es crear una aplicación receptiva que cargue diferentes componentes en respuesta a diferentes consultas de medios para anchos de dispositivos. Mi ejemplo de trabajo tiene un MatchMediaService:

import { Injectable } from ''@angular/core''; @Injectable() export class MatchMediaService { constructor() { } rules = { print: "print", screen: "screen", phone: ''(max-width: 767px)'', tablet: ''(min-width: 768px) and (max-width: 1024px)'', desktop: ''(min-width: 1025px)'', portrait: ''(orientation: portrait)'', landscape: ''(orientation: landscape)'', retina: ''(-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi)'' }; Check = function (mq) { if (!mq) { return; } return window.matchMedia(mq).matches; }; /********************************************** METHODS FOR CHECKING TYPE **********************************************/ IsPhone() { return window.matchMedia(this.rules.phone).matches; }; IsTablet = function () { return window.matchMedia(this.rules.tablet).matches; }; IsDesktop = function () { return window.matchMedia(this.rules.desktop).matches; }; IsPortrait = function () { return window.matchMedia(this.rules.portrait).matches; }; IsLandscape = function () { return window.matchMedia(this.rules.landscape).matches; }; IsRetina = function () { return window.matchMedia(this.rules.retina).matches; }; /********************************************** EVENT LISTENERS BY TYPE **********************************************/ OnPhone(callBack) { if (typeof callBack === ''function'') { var mql: MediaQueryList = window.matchMedia(this.rules.phone); mql.addListener((mql: MediaQueryList) => { if (mql.matches) { callBack(mql); } }); } }; OnTablet(callBack) { if (typeof callBack === ''function'') { var mql: MediaQueryList = window.matchMedia(this.rules.tablet); mql.addListener((mql: MediaQueryList) => { if (mql.matches) { callBack(mql); } }); } }; OnDesktop(callBack) { if (typeof callBack === ''function'') { var mql: MediaQueryList = window.matchMedia(this.rules.desktop); mql.addListener((mql: MediaQueryList) => { if (mql.matches) { callBack(mql); } }); } }; OnPortrait(callBack) { if (typeof callBack === ''function'') { var mql: MediaQueryList = window.matchMedia(this.rules.portrait); mql.addListener((mql: MediaQueryList) => { if (mql.matches) { callBack(mql); } }); } }; OnLandscape(callBack) { if (typeof callBack === ''function'') { var mql: MediaQueryList = window.matchMedia(this.rules.landscape); mql.addListener((mql: MediaQueryList) => { if (mql.matches) { callBack(mql); } }); } }; }

Luego, dentro de un componente ''principal'' (HomeComponent), uso MatchMediaService para determinar qué componente secundario (HomeMobileComponent o HomeDesktopComponent) se carga según lo que MatchMediaService devuelve, así como los eventos de escucha que se activan cuando el navegador cambia de tamaño a través de diferentes dimensiones:

import { Component, OnInit, NgZone } from ''@angular/core''; import { MatchMediaService } from ''../shared/services/match-media.service''; import { HomeMobileComponent } from ''./home-mobile.component''; import { HomeDesktopComponent } from ''./home-desktop.component''; @Component({ moduleId: module.id, selector: ''home.component'', templateUrl: ''home.component.html'', providers: [ MatchMediaService ], directives: [ HomeMobileComponent, HomeDesktopComponent ] }) export class HomeComponent implements OnInit { IsMobile: Boolean = false; IsDesktop: Boolean = false; constructor( private matchMediaService: MatchMediaService, private zone: NgZone ) { //GET INITIAL VALUE BASED ON DEVICE WIDTHS AT TIME THE APP RENDERS this.IsMobile = (this.matchMediaService.IsPhone() || this.matchMediaService.IsTablet()); this.IsDesktop = (this.matchMediaService.IsDesktop()); var that = this; /*--------------------------------------------------- TAP INTO LISTENERS FOR WHEN DEVICE WIDTH CHANGES ---------------------------------------------------*/ this.matchMediaService.OnPhone( function (mediaQueryList: MediaQueryList) { that.ShowMobile(); } ); this.matchMediaService.OnTablet( function (mediaQueryList: MediaQueryList) { that.ShowMobile(); } ); this.matchMediaService.OnDesktop( function (mediaQueryList: MediaQueryList) { that.ShowDesktop(); } ); } ngOnInit() { } ShowMobile() { this.zone.run(() => { // Change the property within the zone, CD will run after this.IsMobile = true; this.IsDesktop = false; }); } ShowDesktop() { this.zone.run(() => { // Change the property within the zone, CD will run after this.IsMobile = false; this.IsDesktop = true; }); } }

<home-mobile *ngIf="(IsMobile)"></home-mobile> <home-desktop *ngIf="(IsDesktop)"></home-desktop>

Este enfoque funciona. Puedo cargar el componente apropiado en respuesta al dispositivo. Me permite personalizar un componente (contenido, estilo, funcionalidad, etc.) para el dispositivo, permitiendo así la mejor experiencia de usuario. Esto también me brinda la capacidad de dirigir diferentes componentes para dispositivos móviles, tabletas y equipos de escritorio (aunque en este caso solo me estoy enfocando en dispositivos móviles y equipos de escritorio).

¿Hay una mejor manera de hacer esto? La desventaja es que estoy obligando a que cada componente comprenda el componente principal para determinar a través de MatchMediaService qué componente secundario cargar. ¿Será escalable para funcionar en una aplicación de nivel de producción en toda regla? Estoy muy interesado en sus comentarios sobre un mejor enfoque, o si este enfoque es aceptable y escalable para una aplicación de producción completa. Gracias por sus comentarios.