How do I implement paging (JwPaginationModule) in my Ionic app? - css

I have a list with cars. Now I want to integrate paging because of the many records.
This is my ListViewPageModule in which I imported JwPagingationModule:
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { FormsModule } from '#angular/forms';
import { JwPaginationModule } from 'jw-angular-pagination';
import { IonicModule } from '#ionic/angular';
import { ListViewPageRoutingModule } from './list-view-routing.module';
import { ListViewPage } from './list-view.page';
import { ComponentsModule } from '../components.module';
#NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
ComponentsModule,
ListViewPageRoutingModule,
JwPaginationModule
],
declarations: [ListViewPage]
})
export class ListViewPageModule {}
My Component:
#Component({
selector: 'app-list-view',
templateUrl: './list-view.page.html',
styleUrls: ['./list-view.page.scss'],
})
export class ListViewPage implements OnInit {
structureGroups: StructureGroup[] = [];
lablesHeadlines = lablesHeadlines;
headlines = lablesHeadlines;
pageOfItems: Array<any>;
constructor(private listClientService: ListClientServiceService, private router: Router) { }
ngOnInit() {
this.listClientService.getAllCarGroupNamesWithId().subscribe(
(response) => {
this.carGroups = response;
return response;
});
}
openCarGroup(id: number) {
this.router.navigate(['/detail-view', { carGroupId: id }]);
}
onChangePage(pageOfItems: Array<any>) {
// update current page of items
this.pageOfItems = pageOfItems;
}
}
My HTML:
1 <ion-content>
2 <ion-list id="list">
3 <ion-item id="list-item" button *ngFor="let carGroup of carGroups"
4 (click)="openCarGroup(carGroup.id)">
5 <ion-label>{{carGroup.carGroupName}}</ion-label>
6 </ion-item>
7 </ion-list>
8 <div class="card-footer pb-0 pt-3">
9 <jw-pagination [carGroups]="carGroups" (changePage)="onChangePage($event)"></jw-pagination>
10 </div>
</ion-content>
My CSS
.card-footer{
width: 100%;
height: 10%;
position: absolute;
bottom: 10px;
}
I am unfortunately still very inexperienced when it comes to working with ionic and Angular. Currently I get the error:
NG0303: Can't bind to 'carGroups' since it isn't a known property of 'jw-pagination'.
This error comes from my HTML file line 9.
Question 1: How can I fix the error?
Question 2: How do I include Pagination correctly in my component? In my ngOnInit() I will have to integrate Pagination as well or?
Question 3: Currently I get "<jw-pagination [carGroups]="carGroups" (changePage)="onChangePage($event)">"
is not displayed. The div has the desired area at the end of the page but I don't see the PageController there. How can I make it visible?

According to the documentation, you should provide your data as items attribute like so:
<jw-pagination [items]="carGroups" (changePage)="onChangePage($event)"></jw-pagination>
This guide might be helpful.
https://edupala.com/how-to-implement-ionic-table-with-pagination/

Related

Ag-grid gridReady event not working in storybook

I'm facing a issue with AG-grid in Storybook.
I'm trying to do filtration in AG-grid added as storybook template. But gridReady event doesn't get fired
Here is the code for reference
someApp.component.html
<div style="float: right; width: 100%;display: flex; <=== this is dive to have search field. We can add input here.
flex-direction: row;
justify-content: flex-end;">
<mat-search-bar (keyup)="applyFilter($event.target.value)" (onClose)="clearFilter()" [placeholder]="Search"></mat-search-bar>
</div> <===== on keyup it takes the input from search field and get the filter data in AG-Grid
</mat-toolbar>
<div class=" ag-grid-container">
<ag-grid-angular
class="ag-theme-material ag-grid-container"
[columnDefs]="columnDefs"
[rowData]="rowdef"
[suppressColumnMoveAnimation]="true"
[suppressDragLeaveHidesColumns]="true"
[overlayNoRowsTemplate]="overlayNoRowsTemplate"
(gridReady)="onGridReady($event)"
>
</ag-grid-angular>
In the above code, I get the value of search and call applyFilter to set quickfilter in grid
someApp.component.ts
columnDefs = [
{ headerName:'Sports', field: 'sports'},
{ headerName:'No: of Players', field:'player'},
];
gridApi!: GridApi;
Search = "Search";
onGridReady (params) {
console.log('calling grid Api');
this.gridApi = params.api;
console.log('called grid Api: '+this.gridApi);
}
ngOnInit() {
}
public overlayNoRowsTemplate =
'<div *ngIf="rowDef.length === 0" class="no-records">No database found.</div>';
applyFilter(value: string) {
console.log(value);
this.gridApi.setQuickFilter(
value
);
}
clearFilter() {
this.gridApi.setQuickFilter(""
);
}
someApp.stories.ts
import {
GridApi,
GridReadyEvent,
ICellRendererParams
} from 'ag-grid-community';
import { moduleMetadata, Meta } from '#storybook/angular';
import { ActionsComponent } from 'projects/web-component-library/src/lib/components/actions/app-actions.component';
import {someApp} from '../../projects/web-component-library/src/lib/components/inventory/inventory.component';
import { MaterialModule } from '../../projects/web-component-library/src/lib/components/material';
import { BrowserAnimationsModule, NoopAnimationsModule } from '#angular/platform-browser/animations';
import { NgMatSearchBarModule } from 'ng-mat-search-bar';
import { AgGridModule } from 'ag-grid-angular';
import { RouterModule } from '#angular/router';
import { CustomActionComponent } from 'projects/web-component-library/src/lib/components/custom-action/custom-action.component';
const rowdef = [{sports:'Cricket', player:11},
{sports:'Basketball', player:5}
]
export default {
title: 'Data Inventory',
component: someApp,
decorators: [
moduleMetadata({
declarations: [someApp,CustomActionComponent],
imports: [MaterialModule, BrowserAnimationsModule, NoopAnimationsModule,NgMatSearchBarModule,AgGridModule.withComponents([CustomActionComponent]),RouterModule]
}),
],
} as Meta;
export const Default = (args: someApp) => ({
component: someApp,
props: args
});
Default.args = {
rowdef
};
export const NoData = (args: someApp) => ({
component: someApp,
props: args
});
NoData.args = {
rowdef:[]
};
When I try to search something
it gives error as this.gridApi is undefined. whereas when I add this in parent HTML as below and run as 'ng serve', its works fine
App.component.html
<some-app><some-app>
Seems like onGridReady is not fired properly in storybook.
Using
Storybook 6.0.12
Angular 8
npm 6.13.4
node v10.19.0
Log of error in storybook

Routing edit/id in asp.net core application with angular not working

I am learning building application using angular and asp.net core using these videos on this link. Everything works fine except the edit of a component. If I give a URL like below, it goes to the route for error in app-routing.module.ts even though there's no error in the browser console log.
http://localhost:4200/genres/edit/1
The app-routing.model.ts is as below
import { Component, NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { CreateActorComponent } from './actors/create-actor/create-actor.component';
import { EditActorComponent } from './actors/edit-actor/edit-actor.component';
import { IndexActorsComponent } from './actors/index-actors/index-actors.component';
import { CreateGenreComponent } from './genres/create-genre/create-genre.component';
import { EditGenreComponent } from './genres/edit-genre/edit-genre.component';
import { IndexGenresComponent } from './genres/index-genres/index-genres.component';
import { HomeComponent } from './home/home.component';
import { CreateMovieTheaterComponent } from './movie-theaters/create-movie-theater/create-movie-theater.component';
import { EditMovieTheaterComponent } from './movie-theaters/edit-movie-theater/edit-movie-theater.component';
import { IndexMovieTheaterComponent } from './movie-theaters/index-movie-theater/index-movie-theater.component';
import { CreateMovieComponent } from './movies/create-movie/create-movie.component';
import { EditMovieComponent } from './movies/edit-movie/edit-movie.component';
const routes: Routes = [
{path:' ', component:HomeComponent},
{path:'genres', component:IndexGenresComponent},
{path:'genres/create', component:CreateGenreComponent},
{path:'genres/edit:id', component:EditGenreComponent},
{path:'actors', component:IndexActorsComponent},
{path:'actors/create', component:CreateActorComponent},
{path:'actors/edit:id', component:EditActorComponent},
{path:'movietheaters', component:IndexMovieTheaterComponent},
{path:'movietheaters/create', component:CreateMovieTheaterComponent},
{path:'movietheaters/edit:id', component:EditMovieTheaterComponent},
{path:'movies/create', component:CreateMovieComponent},
{path:'movies/edit:id', component:EditMovieComponent},
// {path:'**',component:HomeComponent}
{path:'**',redirectTo:' '}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
edit-genre.component.ts is
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute } from '#angular/router';
import { genreCreationDTO } from '../genres.model';
#Component({
selector: 'app-edit-genre',
templateUrl: './edit-genre.component.html',
styleUrls: ['./edit-genre.component.css']
})
export class EditGenreComponent implements OnInit {
constructor(private activatedRoute:ActivatedRoute) { }
model: genreCreationDTO={name:"Drama"};
ngOnInit(): void {
this.activatedRoute.params.subscribe(params=>{
});
}
//Event emiited value passed from child form-genre-creation to parent create-genre.component
//to be displayed
saveChanges(genreCreationDTO:genreCreationDTO)
{
}
}
edit-genre.component.html is
<h2>Edit Genre</h2>
<app-form-genre [model]="model" (onSaveChanges)="saveChanges($event)"></app-form-genre>
form-genre.component.html is
<form (submit)="saveChanges()" [formGroup]="form">
<mat-form-field appearance="outline">
<mat-label>Name*</mat-label>
<input matInput formControlName="name">
<mat-error *ngIf="form.invalid">{{getErrorMessageFieldName()}}</mat-error>
</mat-form-field>
<div>
<button mat-flat-button color="primary" [disabled]="form.invalid">Save Changes</button>
<a mat-stroked-button routerLink="/genres">Cancel</a>
</div>
form-genre.component.ts is
import { Component, OnInit, Output,EventEmitter, Input } from '#angular/core';
import { FormBuilder, FormGroup, Validators } from '#angular/forms';
import { Router } from '#angular/router';
import { firstLetterUppercase } from 'src/app/validators/firstLetterUppercase';
import { genreCreationDTO } from '../genres.model';
#Component({
selector: 'app-form-genre',
templateUrl: './form-genre.component.html',
styleUrls: ['./form-genre.component.css']
})
export class FormGenreComponent implements OnInit {
constructor(private router: Router, private formBuilder:FormBuilder) { }
#Input()
model!: genreCreationDTO;
//Event Emitter
#Output()
onSaveChanges: EventEmitter<genreCreationDTO>=new EventEmitter<genreCreationDTO>();
form!: FormGroup;
ngOnInit(): void {
this.form= this.formBuilder.group({
name:['',[Validators.required, Validators.minLength(3),firstLetterUppercase()]]
});
if(this.model!==undefined){
this.form.patchValue(this.model);
}
}
getErrorMessageFieldName()
{
const field= this.form.get("name");
if(field?.hasError("required"))
{
return "The name field is required";
}
if(field?.hasError("minLength")){
return "The minimum length is 3"
}
if(field?.hasError('firstLetterUppercase')){
return field.getError('firstLetterUppercase').message;
}
return '';
}
saveChanges()
{
//Emit value from child form-genre.compnent to parent create-genre.component
this.onSaveChanges.emit(this.form.value);
// this.router.navigate(['/genres']);
}
}
I am new to .net core framework & angular and i'm using forms(chapter sharing forms) in the video tutorial by Felipe galivan. Everytime I give an edit/id url for a component, it keeps using this
{path:'**',redirectTo:' '}
in the app-routing.module.ts as if say genres/edit/id has no match. I'm doing exactly as Felipe in the video, mine keeps redirecting me to home page instead of genres/edit. Why is this happening?

API data is not getting at first loading ionic2, angular2

I am struggling from last couple days.I am using ionic2/3 angular 2 and wordpress for data.
I am trying to load categories data at home page at first load but i am not getting. In browser it's coming properly and also when i click on menu button entire data is showing properly. I checked all blogs but didn't get any proper solution.
Please help me if any one had same issues and solved.Thanks in advance.
I am attaching my codes here.
enter code here
Home.ts-
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import * as WC from 'woocommerce-api';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
woocommerce: any;
categories: any[];
// Home=HomePage;
constructor(public navCtrl: NavController) {
this.categories=[];
}
ionViewDidLoad(){
this.getCatData();
}
getCatData(){
this.woocommerce = WC({
url:'http://www.example.com/',
consumerKey: 'ck_7dfe0aec65ahgcdhgcdhcdhf36288d1fa2e4c01',
consumerSecret: 'cs_da53e5b228eb6235bshhcskhc7a68541ad809743'
});
this.woocommerce.getAsync("products/categories").then((data)=>{
console.log(JSON.parse(data.body).product_categories);
this.categories = JSON.parse(data.body).product_categories;
},(err)=>{
console.log(err);
})
}
}
Home.html-
<ion-header>
<ion-navbar color="header">
<ion-buttons left>
<button ion-button menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
</ion-buttons>
<ion-buttons right>
<button ion-button icon-only>
<ion-icon name="search"></ion-icon>
</button>
</ion-buttons>
<ion-title>
KAAIROS EXPORTS
</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<!-- slider -->
<ion-card>
<ion-slides loop="true" autoplay="false" pager>
<ion-slide *ngFor= "let number of [1,2,3,4,5]"><img src="./assets/img/{{number}}.jpg"/></ion-slide>
</ion-slides>
</ion-card>
<!-- end-slider -->
<!-- <ion-grid> Hi this is second line
</ion-grid> -->
<ion-item *ngFor="let category of categories">
<h2> {{ category.name }} </h2>
</ion-item>
</ion-content>
app.component.ts-
import { TabsPage } from './../pages/tabs/tabs';
import { HomePage } from './../pages/home/home';
import { Component, ViewChild } from '#angular/core';
import { Nav, Platform } from 'ionic-angular';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
//import { Menu } from '../pages/menu/menu';
#Component({
templateUrl: 'app.html'
})
export class MyApp {
#ViewChild(Nav) nav: Nav;
// rootPage: any = Menu;
rootPage = TabsPage;
constructor(public platform: Platform, public statusBar: StatusBar, public splashScreen: SplashScreen) {
this.initializeApp();
}
initializeApp() {
this.platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
this.statusBar.styleDefault();
this.splashScreen.hide();
});
}
// go_to_home(){
// this.nav.setRoot(HomePage);
// }
}
app.html-
<ion-menu side="left" [content]="content">
<ion-header>
<ion-toolbar>
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<!-- <ion-list>
<!-- <ion-item (click)="go_to_home()" menuClose>
Home
</ion-item> -->
<!-- <ion-item (click)="go_to_about()" menuClose>
About
</ion-item> -->
<!-- <ion-item (click)="go_to_contact()" menuClose>
Contact Us
<!-- </ion-item> -->
</ion-content>
</ion-menu>
<!-- Disable swipe-to-go-back because it's poor UX to combine STGB with side menus -->
<ion-nav [root]="rootPage" #content swipeBackEnabled="true"></ion-nav>
app.module:-
import { BrowserModule } from '#angular/platform-browser';
import { ErrorHandler, NgModule } from '#angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { TabsPage } from '../pages/tabs/tabs';
import { AboutusPage } from '../pages/aboutus/aboutus';
import { ContactusPage } from '../pages/contactus/contactus';
import { CategoryPage } from '../pages/category/category';
import { ProductsByCategoryPage } from '../pages/products-by-category/products-by-category';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
import { WooCommerceProvider } from '../providers/woocommerce/woocommerce';
import { HttpModule } from '#angular/http';
#NgModule({
declarations: [
MyApp,
HomePage,
TabsPage,
AboutusPage,
ContactusPage,
CategoryPage,
//ProductListPage,
ProductsByCategoryPage
],
imports: [
BrowserModule,
HttpModule,
IonicModule.forRoot(MyApp,{
mode:'ios'
}),
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
HomePage,
TabsPage,
AboutusPage,
ContactusPage,
CategoryPage,
ProductsByCategoryPage
],
providers: [
StatusBar,
SplashScreen,
{provide: ErrorHandler, useClass: IonicErrorHandler},
WooCommerceProvider
]
})
export class AppModule {}
Simply call the ChangeDetectorRef after successfull API call to refresh the changes in UI. PFB the sample code where we have triggered change detector on subscribe call. You can check the working version here
import { Component, ViewChild, ChangeDetectorRef } from '#angular/core';
import { NavController, Content } from 'ionic-angular';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
#ViewChild(Content) content: Content;
Arr = Array; //Array type captured in a variable
num:number = 1000;
toolbar_color: string;
constructor(public navCtrl: NavController, public ref : ChangeDetectorRef) {
this.toolbar_color="secondary";
}
changeColor(){
this.toolbar_color="primary";
this.ref.detectChanges();
}
ionViewDidLoad() {
//this.content.enableJsScroll();
this.content.ionScrollEnd.subscribe(() => {
this.changeColor();
});
}
}
This is because your data is asynchronously loaded. The view has already been rendered by the time your data arrives.
One way to fix this is to add some kind of "refresh" method and call it when you receive the data (e.g., in .getAsync().then(...)).

Onclick image to move another page is not working

I'm new to nativescript. I'm navigation from Alert page to
Naviagation page. I have posted all relevant codes.please check it.
I'm not getting any issue.When performing image onClick I'm able to call this method onNotification().
I'm able to see this console log in command prompt
console.log("SteveCheck", "Test");
But I don't know, Why it is not moving to notification page when
click on the button in alert page.Below I have added all the relevant codes.
app.module.ts:
import { NgModule, NO_ERRORS_SCHEMA } from "#angular/core";
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
import { AlertComponent } from "./AlertFolder/alert.component";
import { NativeScriptRouterModule } from "nativescript-angular/router"
import {AppRoutes, AppComponents } from "./app.routing";
#NgModule({
declarations: [AlertComponent, ...AppComponents],
bootstrap: [AlertComponent],
imports: [
NativeScriptModule,
NativeScriptRouterModule,
NativeScriptRouterModule.forRoot(AppRoutes)
],
schemas: [NO_ERRORS_SCHEMA],
})
export class AppModule {}
app.routing.ts:
import { AlertComponent } from "./AlertFolder/alert.component";
import { NotificationComponent } from "./Noficiation/notification";
export const AppRoutes:any = [
{ path: "", component: AlertComponent },
{ path: "NotificationPage", component: NotificationComponent}
];
export const AppComponents: any = [
AlertComponent,
NotificationComponent
];
alert.component.ts:
#Component({
selector: "sdk-child-component",
moduleId: module.id,
....
})
export class AlertComponent {
.....
.....
public constructor(private router: Router, private routerExtensions: RouterExtensions){
this.alertList = [];
}
onNotification() {
console.log("SteveCheck", "Test");
this.router.navigate(["NotificationPage"]);
}
}
alert.component.html:
<StackLayout class="borders" orientation="horizontal" >
<Label class="notification-label" text="Notification Center" ></Label>
<Image src="res://right_arrow" stretch="none" class="right-arrow" (tap)="onNotification()"></Image>
</StackLayout>
constructor(private routerExtensions: RouterExtensions) {
// ...
}
this.routerExtensions.navigate(["/NotificationPage"]);
I have to use Path folder name Notification. I have that second page NotificationComponent placed inside that Notification folder only.That's why I'm unable to navigate between pages.
By changing this :
this.router.navigate(["NotificationPage"]);
to this:
this.router.navigate(["Notification"]);
fixed my issue
Here is an example , we can include routerLink on the img tag-
<img src="../../../assets/images/Notification.png" [routerLink]="['/NotificationPage']" width="55%" height = "200px" class="img-responsive" style="margin-left: 220px">

How to check whether user has internet connection or not in Angular2?

How I would check internet connection in Angular2 at the time of API hitting, whenever in my app API is hit to server sometimes user is
offline (i mean without internet connection) so how would i check the internet connectivity ? is there some special status code for internet connectivity ?
or something else ?
PS:- i found navigator.onLine in angularJs but seems not working in angular2.
Source - How to check internet connection in AngularJs
update
as sudheer suggested in answer below navigator.onLine in working with angular2 but still not working properly why ?
working example here
(2018) Code updated for rxjs6
It totally works with angular2. Obviously it's different from angularJS because neither $scope nor $apply exist anymore. RxJS makes this easy, though! Tested on Chrome 53:
template:
<p>{{online$ | async}}</p>
component:
import { Observable, fromEvent, merge, of } from 'rxjs';
import { mapTo } from 'rxjs/operators';
#Component({ /* ... */ })
export class MyComponent {
online$: Observable<boolean>;
constructor() {
this.online$ = merge(
of(navigator.onLine),
fromEvent(window, 'online').pipe(mapTo(true)),
fromEvent(window, 'offline').pipe(mapTo(false))
);
}
}
Think about what 'offline' means for your use case!
An unplugged ethernet cable and a 3KB/s EDGE connection likely have the same implications for your app although the latter means you're not technically offline!
From a programmer's point-of-view being connected wirelessly with a very poor signal is actually a lot worse than being truely disconnected because it's a lot harder to detect!
The above code returning a false value means your absolutely offline as in disconnected. It returning true doesn't necessarily indicate that there's a practically usable connection.
At first, j2L4e's answer didn't work for me (testing in Chrome). I tweaked slightly by surrounding my bool in brackets in the ngIf and this ended up working.
<md-icon class="connected" mdTooltip="No Connection" *ngIf="!(isConnected | async)">signal_wifi_off</md-icon>
import { Component, OnInit } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import 'rxjs/Rx';
#Component({
selector: 'toolbar',
templateUrl: './toolbar.component.html',
styleUrls: ['./toolbar.component.css']
})
export class ToolbarComponent implements OnInit {
isConnected: Observable<boolean>;
constructor() {
this.isConnected = Observable.merge(
Observable.of(navigator.onLine),
Observable.fromEvent(window, 'online').map(() => true),
Observable.fromEvent(window, 'offline').map(() => false));
}
ngOnInit() {
}
}
As i have checked navigator is global object like window. You can use in in angular2 and it worked fine for me.
import {Component} from 'angular2/core';
#Component({
selector: 'my-app',
template:`
navigator.onLine
{{onlineFlag}}
`
})
export class AppComponent {
public onlineFlag =navigator.onLine;
}
Using Angular 6+ and Rxjs 6+, you can do it in the following way:
import { Observable, fromEvent, merge, of } from 'rxjs';
import { mapTo } from 'rxjs/operators';
online$: Observable<boolean>;
constructor() {
this.online$ = merge(
of(navigator.onLine),
fromEvent(window, 'online').pipe(mapTo(true)),
fromEvent(window, 'offline').pipe(mapTo(false))
)
}
Here is a demo (toggle network in dev tools)
Safe Approach to listen to network states
Answers given above works well but are not considered safe approach.
1.Browser dependent objects like window should not be referenced directly, always check for platform.
2.Furthermore functionality like Network Connection must be encapsulated into a service.
Below is the ConnectionService which can be subscribed to listen network states. It follows the rxjs 6 style.
Complete Code
import { Injectable, Inject, PLATFORM_ID } from '#angular/core';
import { Observable, fromEvent, merge, empty } from 'rxjs';
import { isPlatformBrowser } from '#angular/common';
import { mapTo } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class ConnectionService {
private connectionMonitor: Observable<boolean>;
constructor(#Inject(PLATFORM_ID) platform) {
if (isPlatformBrowser(platform)) {
const offline$ = fromEvent(window, 'offline').pipe(mapTo(false));
const online$ = fromEvent(window, 'online').pipe(mapTo(true));
this.connectionMonitor = merge(
offline$, online$
);
} else {
this.connectionMonitor = empty();
}
}
monitor(): Observable<boolean> {
return this.connectionMonitor;
}
}
in component, you may listen by subscribing to monitor() or directly into HTML using async pipe.
For Angular 9 - a very simple solution and comfortable using (thanks to this and this solutions):
1) Create new component:
ng g c NoConnection
no-connection.component.ts
import { Component, OnInit } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser'
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'app-no-connection',
templateUrl: './no-connection.component.html',
styleUrls: ['./no-connection.component.css']
})
export class NoConnectionComponent implements OnInit {
isConnectionAvailable: boolean = navigator.onLine;
constructor(private httpClient: HttpClient) {
window.addEventListener('online', () => {
this.isConnectionAvailable = true
});
window.addEventListener('offline', () => {
this.isConnectionAvailable = false
});
}
ngOnInit(): void {
}
}
no-connection.component.html (customise page as you want)
<div>
<p style.color = "{{ isConnectionAvailable ? 'green' : 'red'}}"> {{ isConnectionAvailable ? 'Online' : 'Offline'}} </p>
<!-- https://stackoverflow.com/questions/13350663/greyed-out-waiting-page-in-javascript#answer-13350908 -->
<div id="blackout" class="noselect" style.display = "{{isConnectionAvailable ? 'none' : 'block'}}">
<br><br><br><br><br>
<p>No Internet connection!</p>
<br>
</div>
</div>
no-connection.component.css
#blackout {
width:100%;
height:100%; /* make sure you have set parents to a height of 100% too*/
position: absolute;
left:0; top:0;
z-index:10; /*just to make sure its on top*/
opacity: 0.5;
background-color:#333;
text-align: center;
font-size:25px;
color: white;
}
.noselect {
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Old versions of Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently
supported by Chrome, Opera and Firefox */
}
2) Use it anywhere you want - in my case the best place - is a root component:
app.component.html
<div>
<app-no-connection></app-no-connection>
<app-main></app-main>
</div>
Go with this simple Hack.
Working in angular 5 or later
constructor(){
setInterval(()=>{
if(navigator.onLine){
//here if it is online
}else{
//here if it is offline
}
}, 100)
}
write this in constructor of app.component.ts or your app bootstrap
No need of any external library ..
import { Injectable } from '#angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
#Injectable()
export class InternetInterceptor implements HttpInterceptor {
constructor() { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// check to see if there's internet
if (!window.navigator.onLine) {
// if there is no internet, throw a HttpErrorResponse error
// since an error is thrown, the function will terminate here
return Observable.throw(new HttpErrorResponse({ error: 'Internet is required.' }));
} else {
// else return the normal request
return next.handle(request);
}
}
}
Use this.
Without any external library.
public isOnline: boolean = navigator.onLine;
ngOnInit() {
console.log(this.isOnline);
}

Resources