How to get a screen resize dimension from a service in angular 2+?

帅比萌擦擦* 提交于 2019-12-23 21:32:23

问题


First this not duplicated take time to read, because there is lot of similar question but they are in the @Component decorator

I got the idea to catch screen resizing in a service then sharing some css value by an observable, but it seem that my service is not working (not able to catch screen resize event).

Here is my code

import { Injectable, HostListener } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
 providedIn: 'root',
})
export class BreakPointService {

    normal: {
        background: 'w3-teal',
        inputColor: 'w3-light-grey',
        css_parent: 'w3-container w3-teal'
    };
    breakpoint: {
        background: 'w3-dark-blue',
        inputColor: 'w3-white',
        css_parent: 'w3-container w3-light-grey'
    };
    breakPointValue: number;


    css_behaviour = new BehaviorSubject(JSON.stringify(this.breakpoint));

    current_css = this.css_behaviour.asObservable();

    @HostListener('window:resize', ['$event'])
    onResize(event) {
        console.log();
        this.breakPointValue = window.innerWidth;
        console.log(this.breakPointValue);
        if (this.breakPointValue > 768) {
            console.log(JSON.stringify(this.normal));
            this.css_behaviour.next(JSON.stringify(this.normal));
        } else {
            console.log(JSON.stringify(this.breakpoint));
            this.css_behaviour.next(JSON.stringify(this.breakpoint));
        }
    }

    public css() {
        if (this.breakPointValue > 768) {
            return this.normal;
        }
        return this.breakpoint;

    }

    constructor() { }
}

Is there any way to do this or this is incheavable from a service ?


回答1:


So I did not see in your OP where you are initializing the service. I had to do this almost exact thing in one app. We watch for screen size changes which triggers changes in some user preferences in local storage:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { TableViewTypes, MediaSizes, UserPreferencesDefaults, TableView, getTableViewDefaults } from '../models/user-preferences.model';
import { StorageService } from './storage.service';

@Injectable()
export class UserPreferencesService {

    private tableViewSubject = new BehaviorSubject<TableView>(UserPreferencesDefaults.tableView);
    tableView$ = this.tableViewSubject.asObservable();

    constructor(
        private storageService: StorageService
    ) {}

    init() {
        this.tableViewSubject.next(
            !(window.outerWidth > MediaSizes.sm) ?
            getTableViewDefaults(false) :
            UserPreferencesDefaults.tableView
        );
        window.addEventListener('resize', () => {
            this.tableViewSubject.next(
                !(window.outerWidth > MediaSizes.sm) ?
                getTableViewDefaults(false) :
                this.storageService.userPreferences.tableView
            );
        });
    }

    storeTableView(tableType: TableViewTypes, value: boolean) {
        this.storageService.userPreferences = {
            ...this.storageService.userPreferences,
            tableView: {
                ...this.storageService.userPreferences.tableView,
                [tableType]: value
            }
        };
    }

    toggleTableView(tableType: TableViewTypes, value?: boolean) {
        value = value !== undefined && value !== null ? value : !this.storageService.userPreferences.tableView[tableType];
        this.tableViewSubject.next({
            ...this.storageService.userPreferences.tableView,
            [tableType]: value
        });
        this.storeTableView(tableType, value);
    }

}

Then in order for the service to work it is initialized by injecting it into the app.component.ts in the constructor param

constructor(
    private userPreferenceService: UserPreferencesService,
) {this.userPreferenceService.init();}



回答2:


Thanks for all replies.

I m still wanting to catch the resise event in the service, but thanks @ABOS and some tutorials about components communication, I got the Idea to use the root component to catch scren size event then to feed my service with changes in it observable, this way all subscribed component will get the breakpoint css values

no more talk here is my implementation

app.component

import { Component, OnInit, HostListener } from '@angular/core';
import { BreakPointService } from './providers/break-point.service';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
    title = 'twithashWebApp';
    css_parent = '';
    breakPointValue: number;
    constructor() {
    }

    ngOnInit() {
        BreakPointService.current_css.subscribe(value => {
            console.log('value is ' + value);
            this.css_parent = JSON.parse(value).css_parent;
        });
    }

    @HostListener('window:resize', ['$event'])
    onResize(event) {
        console.log();
        this.breakPointValue = window.innerWidth;
        console.log(this.breakPointValue);
        if (this.breakPointValue > 768) {
            console.log(JSON.stringify(BreakPointService.normal));
            BreakPointService.css_behaviour.next(JSON.stringify(BreakPointService.normal));
        } else {
            console.log(JSON.stringify(BreakPointService.breakpoint));
            BreakPointService.css_behaviour.next(JSON.stringify(BreakPointService.breakpoint));
        }
    }


}

break-point.service

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
    providedIn: 'root',
})
export class BreakPointService {

    static normal = {
        background: 'w3-teal',
        inputColor: 'w3-light-grey',
        css_parent: 'w3-container w3-teal'
    };
    static breakpoint = {
        background: 'w3-dark-blue',
        inputColor: 'w3-white',
        css_parent: 'w3-container w3-light-grey'
    };


    static css_behaviour = new BehaviorSubject<string>(JSON.stringify(BreakPointService.breakpoint));

    static current_css = BreakPointService.css_behaviour.asObservable();



    constructor() { }
}

corresponding template

<!--The content below is only a placeholder and can be replaced.-->
<div class="{{css_parent}}" style="text-align:center" style="height: 100%">
<app-tweet-list></app-tweet-list>
</div>



回答3:


You may want to check into Angular's Flex-Layout Package. You can inject its ObservableMedia service. Which will allow you to then subscribe to it a listen to window size changes.

    import {MediaChange, ObservableMedia} from '@angular/flex-layout';

    @Injectable({
     providedIn: 'root',
    })
    export class BreakPointService {

     constructor(media: ObservableMedia) {}

     resize(){
      return this.media.pipe(map(change: MediaChange) => {
      //if changes doesn't have the width available on it, access it from the window object
      if (window.innerWidth > 768) {       
            return JSON.stringify(this.normal);
        } else {
            return JSON.stringify(this.breakpoint);
        }
      }));
     }
   }

will log the media change object to your console whenever you resize your window. After you subscribe to it in your component.



来源:https://stackoverflow.com/questions/53688140/how-to-get-a-screen-resize-dimension-from-a-service-in-angular-2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!