问题
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