Ionic 4 background blinks and tap delay - ionic-framework

This is my first application using ionic4 and there is something weird happening. When I tap on any link, there is delay and the entire background blinks before it loads the page. Here is a video showing this weird behave: https://youtu.be/NqoOMQYyr4k
For reference, here is the code for the pages:
On the global.scss i have this property to setup the background
ion-content {
--background: #000 url('./assets/images/main-bg.png') no-repeat center center / cover;
}
news.page.ts
import { News } from './news.model';
import { Component, OnInit } from '#angular/core';
import { NewsService } from '../services/news.service';
import { Router } from '#angular/router';
import { NavController } from '#ionic/angular';
#Component({
selector: 'app-news',
templateUrl: './news.page.html',
styleUrls: ['./news.page.scss'],
})
export class NewsPage implements OnInit {
news: any;
constructor(private newsService: NewsService, private router: Router, private navController: NavController) { }
ngOnInit() {
this.news = this.newsService.getAllEvents();
}
go(id: string) {
this.navController.navigateForward('news/' + id);
}
}
news.page.html
<ion-header>
<ion-toolbar color="grey">
<ion-buttons slot="start">
<ion-menu-button></ion-menu-button>
</ion-buttons>
<ion-title style="color: #524A4A!important">News</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-grid padding class="margin-logo-header">
<ion-row>
<div>
<h2>Noticias HD Friends</h2>
</div>
</ion-row>
</ion-grid>
<ion-card color="grey" *ngFor="let news of news | async">
<ion-nav-pop (click)="go(news.id)" >
<ion-img src="{{news.picture}}"></ion-img>
<ion-card-header>
<ion-card-title>{{ news.title }}</ion-card-title>
</ion-card-header>
<ion-card-content>
<p>{{ news.subtitle }}</p>
</ion-card-content>
</ion-nav-pop>
</ion-card>
</ion-content>
news.service.ts
import { Injectable } from '#angular/core';
import { AngularFireDatabase, AngularFireList } from '#angular/fire/database';
import { News } from '../news/news.model';
#Injectable({
providedIn: 'root'
})
export class NewsService {
NODE = 'news/';
news: AngularFireList<News[]>;
constructor(private db: AngularFireDatabase) { }
getAllEvents() {
const localNews = this.db.list(this.NODE);
return localNews.valueChanges();
}
getNews(id: string) {
return this.db.object(this.NODE + id);
}
}
Is this a bug because it's a beta or is this something I messed up?
Thanks guys
UPDATE 1
This seems to be a bug on ionic framework. As soon as I get something I'll post here for future reference.

Related

Display a photo retrived from firebase on ionic 4 App

I have an ionic4 app that I retrieve some photo from firebase storage and show it on html page in my app, now I just could showed the photo in a console and I couldn't showed it on a page.
Can someone help me that how can I display a photo on html page please.
My code is below
home.page.ts
import { Component } from '#angular/core';
import { AngularFireStorage, AngularFireStorageReference } from 'angularfire2/storage';
#Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
storageRef: AngularFireStorageReference;
constructor(private afStorage: AngularFireStorage) { }
display() {
this.storageRef = this.afStorage.ref('rasool/download2.jpg');
this.storageRef.getDownloadURL().subscribe(url => console.log(url));
}
}
home.page.html
<ion-header>
<ion-toolbar>
<ion-title>
Ionic Blank
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
<p>its work sir</p>
<ion-button (click)="display()">click me</ion-button>
</ion-content>
// home.page.ts
import { Component } from '#angular/core';
import { AngularFireStorage, AngularFireStorageReference } from 'angularfire2/storage';
#Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
storageRef: AngularFireStorageReference;
public imageUrl = '';
constructor(private afStorage: AngularFireStorage) { }
display() {
this.storageRef = this.afStorage.ref('rasool/download2.jpg');
this.storageRef.getDownloadURL().subscribe(url => this.imageUrl = url);
}
}
// home.page.html
<ion-header>
<ion-toolbar>
<ion-title>
Ionic Blank
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
<p>its work sir</p>
<img src="{{imageUrl}}" />
<ion-button (click)="display()">click me</ion-button>
</ion-content>`enter code here`

Ionic Http request re-occurring multiple times

I'm learning Ionic and stuck on an issue. My app is stuck in a loop in which it is repeatedly fetching information from a remote server and causing the browser and crash.
I setup a service, code below, to retrieve the data:
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
/*
Generated class for the CategoriesServiceProvider provider.
See https://angular.io/guide/dependency-injection for more info on providers
and Angular DI.
*/
#Injectable()
export class CategoriesServiceProvider {
apiURL = 'https://reqres.in/api/users';
constructor(public http: HttpClient) {
console.log('Hello CategoriesServiceProvider Provider');
}
getUsers(){
return new Promise(resolve => {
this.http.get(this.apiURL).subscribe(data => {
resolve(data);
// console.log(data);
}, err => {
console.error(err);
});
});
}
}
Below is the code in my categories.ts file which uses the service above:
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { CategoriesServiceProvider } from '../../providers/categories-service/categories-service';
/**
* Generated class for the CategoriesPage page.
*
* See https://ionicframework.com/docs/components/#navigation for more info on
* Ionic pages and navigation.
*/
#IonicPage()
#Component({
selector: 'page-categories',
templateUrl: 'categories.html',
providers: [CategoriesServiceProvider]
})
export class CategoriesPage {
constructor(public navCtrl: NavController, public navParams: NavParams, private categories: CategoriesServiceProvider) {
}
users: any;
getUsers(){
this.categories.getUsers().then(data => {
this.users = data;
console.log(this.users);
});
}
ionViewDidLoad() {
console.log('ionViewDidLoad CategoriesPage');
this.getUsers();
}
}
... followed by categories.html:
<ion-header>
<ion-navbar>
<ion-title>categories</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-list>
<ion-item *ngFor="let user of getUsers()">
TESTING - {{user.gender}}
</ion-item>
</ion-list>
</ion-content>
I don't know why the http request is repeating instead of fetching once and then going away.
here you are looping on the function to get your data:
<ion-content padding>
<ion-list>
<ion-item *ngFor="let user of getUsers()">
TESTING - {{user.gender}}
</ion-item>
</ion-list>
</ion-content>
Replace it with the retrieved data instead!
Something like :
<ion-content padding>
<ion-list>
<ion-item *ngFor="let user of this.users">
TESTING - {{user.gender}}
</ion-item>
</ion-list>
</ion-content>

Ionic4 ngSubmit is not firing on submit

Using Ionic4 for the first time and struggling with ngSubmit not triggering the respective method in the login page. Although its always successfully hitting the LoginPage constructor and AuthService constructor. All the respective modules have been imported and there are no console errors too. What am i doing wrong ?
login.page.html:
<ion-header>
<ion-toolbar>
<ion-title>
Login
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<form (ngSubmit)="login()" [formGroup]="loginForm">
<ion-grid>
<ion-row>
<ion-col>
<ion-item>
<ion-input type="text" placeholder="Email" formControlName="email" style="width:50%;"></ion-input>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col col-3>
<ion-item>
<ion-input type="password" placeholder="Password" formControlName="password" style="width:50%;"></ion-input>
</ion-item>
</ion-col>
</ion-row>
</ion-grid>
<div padding-horizontal>
<div class="form-error">{{loginError}}</div>
</div>
<ion-grid>
<ion-row>
<ion-col>
<ion-button type="submit" [disabled]="!loginForm.valid" color="primary">Log in</ion-button>
Forgot password?
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-button icon-left block clear (click)="loginWithGoogle()" color="secondary">
<ion-icon name="logo-google"></ion-icon>
Log in with Google
</ion-button>
<ion-button icon-left block clear (click)="signup()" color="primary">
<ion-icon name="person-add"></ion-icon>
Sign up
</ion-button>
</ion-col>
</ion-row>
</ion-grid>
</form>
</ion-content>
login.page.ts:
import { Component, OnInit } from '#angular/core';
import { AuthService } from '../common/services/auth.service';
import { FormGroup, FormBuilder, Validators } from '#angular/forms';
import { Router } from '#angular/router';
#Component({
selector: 'app-login',
templateUrl: './login.page.html',
styleUrls: ['./login.page.scss'],
})
export class LoginPage implements OnInit {
loginForm: FormGroup;
loginError: string;
constructor(private auth:AuthService,
private router:Router,
private fb: FormBuilder)
{
this.loginForm = this.fb.group({
email: ['', Validators.compose([Validators.required, Validators.email])],
password: ['', Validators.compose([Validators.required, Validators.minLength(6)])]
});
}
ngOnInit() {}
login() {
alert('login');
let data = this.loginForm.value;
if (!data.email) {
return;
}
let credentials = {
email: data.email,
password: data.password
};
this.auth.signInWithEmail(credentials)
.then(
() => this.router.navigate(['/home']),
error => this.loginError = error.message
);
}
}
login.module.ts:
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { FormsModule,ReactiveFormsModule } from '#angular/forms';
import { Routes, RouterModule } from '#angular/router';
import { IonicModule } from '#ionic/angular';
import { LoginPage } from './login.page';
const routes: Routes = [
{
path: '',
component: LoginPage
}
];
#NgModule({
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
IonicModule,
RouterModule.forChild(routes),
],
entryComponents: [LoginPage],
declarations: [LoginPage]
})
export class LoginPageModule {}
auth.service.ts:
import { Injectable } from '#angular/core';
import { AngularFireAuth } from 'angularfire2/auth';
import * as firebase from 'firebase/app';
import AuthProvider = firebase.auth.AuthProvider;
#Injectable({
providedIn: 'root'
})
export class AuthService {
private user: firebase.User;
constructor(public afAuth: AngularFireAuth) {
afAuth.authState.subscribe(user => {
this.user = user;
});
}
signInWithEmail(credentials) {
console.log('Sign in with email');
return this.afAuth.auth.signInWithEmailAndPassword(credentials.email,
credentials.password);
}
}
ngSubmit is reloading the complete page and hence its hitting only login constructor but not the respective method. Removed (ngSubmit) on <form>, type="submit" on <ion-button>, added (click)="login()" event to <ion-button>. It started working.

Ionic 2 Maximum call stack size exceeded Error

Trying to figure out this problem. I am getting a maxmimum call stack size error and the link below is the js output.
I have added print statements and worked out the main app file is calling page1 as it should but then page1 is calling the main app file and this continues.
I am new to ionic 2 and would really appreciate a solution, thanks.
Javascript Output
page1.ts
import { Component } from '#angular/core';
import { Data } from '../../providers/data';
import { NewListPage } from '../new-list/new-list';
import { NavController } from 'ionic-angular';
#Component({
selector: 'page-page1',
templateUrl: 'page1.html',
})
export class Page1 {
public list: any[] = [];
constructor(public navCtrl: NavController, private _data: Data) {
console.log('Page1BEFORE');
let that = this;
this._data.list.subscribe((data) => {that.list.push(data);}, (err) => {console.error(err);});
}
newList() {
console.log('NEWLIST1');
this.navCtrl.push(NewListPage);
}
}
page1.html
<ion-app>
<ion-header>
<ion-navbar>
<button ion-button menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
<ion-title>Page One</ion-title>
<ion-buttons end>
<ion-icon ios="ios-contact" md="md-contact"></ion-icon>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content class="grid-basic-page">
<ion-col width-100><progress class="progressBar" max="100" value="80"></progress></ion-col>
<ion-row>
<ion-col width-50><div>col</div></ion-col>
<ion-col width-50><div>col</div></ion-col>
</ion-row>
<ion-row>
<ion-col width-50><div>col</div></ion-col>
<ion-col width-50><div>col</div></ion-col>
</ion-row>
<ion-row>
<ion-col width-50><div>col</div></ion-col>
<ion-col width-50><div>col</div></ion-col>
</ion-row>
<ion-list *ngIf="list">
<ion-item *ngFor="let item of list">
<ion-label>{{item.title}}</ion-label>
</ion-item>
</ion-list>
<p *ngIf="!list"> No Lists </p>
<button fab fab-bottom fab-right (click)="newList()"> New </button>
</ion-content>
</ion-app>
app.component.ts
import { Component, ViewChild } from '#angular/core';
import { Nav, Platform } from 'ionic-angular';
import { StatusBar, Splashscreen } from 'ionic-native';
import { Page1 } from '../pages/page1/page1';
import { Page2 } from '../pages/page2/page2';
import { Data } from '../providers/data';
#Component({
templateUrl: 'app.html',
providers: [Data],
})
export class MyApp {
#ViewChild(Nav) nav: Nav;
rootPage: any = Page1;
pages: Array<{title: string, component: any}>;
constructor(public platform: Platform) {
console.log('PreAPP');
this.initializeApp();
console.log('PostApp');
// used for an example of ngFor and navigation
this.pages = [
{ title: 'Page One', component: Page1 },
{ title: 'Page Two', component: Page2 }
];
console.log('pages');
}
initializeApp() {
console.log('APP');
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.
StatusBar.styleDefault();
Splashscreen.hide();
});
}
openPage(page) {
console.log('OpenPAGE');
// Reset the content nav to have just this page
// we wouldn't want the back button to show in this scenario
this.nav.setRoot(page.component);
}
}
app.html
<ion-menu [content]="content">
<ion-header>
<ion-toolbar>
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<button menuClose ion-item *ngFor="let p of pages" (click)="openPage(p)">
{{ p.title }}
</button>
</ion-list>
</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="false"></ion-nav>
Removing the <ion-app> element from page1.html fixed the issue
In my case I had not declared and added routes constant in imports array of the module. Once declared and imported error gone.
I am using IONIC 4

How to extract and reuse nav bar template and logic in Ionic 2 app?

Having had some experience with Angular 1.x (but not Ionic 1.x), I am now trying to develop a small mobile app using Ionic 2, which is based on Angular 2.
I am familiar with URL-based routing principles such as those used in ui-router. The concept in Ionic 2 is different and is based on pushing/popping pages on top of a root page.
So far I have managed to create 2 pages (Search and Person) with a nav bar on top, and to navigate from one to the other, and back. The navbar has a button to return to the root (Search) page (because later it will be possible to navigate from a person to other pages, further away from the root page).
However I could not figure out how to extract the navbar and navbar controller in a separate file. So the markup and the button handler (goToSearch) are repeated in every page.
How can I extract the navbar template and logic so as not to repeat it ?
Bonus question (and strongly related) : Can someone explain the difference between the ion-nav in app.html and the ion-navbar in the pages ?
app.ts :
import 'es6-shim';
import {App, Platform} from 'ionic-angular';
import {StatusBar} from 'ionic-native';
import {TabsPage} from './pages/tabs/tabs';
import {Search} from './pages/search/search'
#App({
templateUrl: 'build/pages/app.html',
config: {} // http://ionicframework.com/docs/v2/api/config/Config/
})
export class MyApp {
rootPage: any = Search;
constructor(platform: Platform) {
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.
StatusBar.styleDefault();
});
}
}
app.html :
<ion-nav [root]="rootPage">
<ion-buttons end>
<button>
<ion-icon name="search"></ion-icon>
</button>
</ion-buttons>
</ion-nav>
search.ts :
import {Page} from 'ionic-angular';
import {Nav} from 'ionic-angular';
import {Person} from '../person/person'
#Page({
templateUrl: 'build/pages/search/search.html',
})
export class Search {
nav:Nav;
constructor(nav:Nav) {
this.nav = nav;
}
goToPerson() {
this.nav.push(Person);
}
}
search.html:
<ion-navbar *navbar>
<ion-title>Search</ion-title>
<ion-buttons end>
<button>
<ion-icon name="search"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
<ion-content padding class="page1">
<h2>Welcome to SEARCH</h2>
<button (click)="goToPerson()">Go to person</button>
</ion-content>
person.ts :
import {Page} from 'ionic-angular';
import {Nav} from 'ionic-angular';
import {Search} from '../search/search'
#Page({
templateUrl: 'build/pages/person/person.html',
})
export class Person {
nav:Nav;
constructor(nav:Nav) {
this.nav = nav;
}
goToSearch() {
this.nav.push(Search);
}
}
person.html :
<ion-navbar *navbar>
<ion-title>Person</ion-title>
<ion-buttons end>
<button (click)="goToSearch()">
<ion-icon name="search"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
<ion-content padding class="page1">
<h2>Welcome to PERSON</h2>
<button (click)="goToSearch()">Go to search</button>
</ion-content>
you could create a component to hold your header config, components are reusable and can be very dynamic, just dont forget to import it on your module
default-header.html
<ion-navbar *navbar>
<ion-title>{{pageTitle}}</ion-title>
<ion-buttons end>
<button (click)="goToSearch()">
<ion-icon name="{{icon}}"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
default-header.ts
import { Component, Input, Inject, ViewChild } from "#angular/core";
import { Content } from "ionic-angular";
import { NavController } from "ionic-angular/navigation/nav-controller";
import {Person} from '../person/person'
#Component({
selector: "default-header",
templateUrl: "default-header.html"
})
export class DefaultHeaderComponent {
#Input() pageTitle: any;
#Input() icon= true;
#ViewChild(Content) content: Content;
constructor(
public navCtrl: NavController,
) {
console.log("Hello DefaultHeaderComponent Component");
}
ionViewDidLoad() {
const self = this;
}
gotNotificationsPage() {
this.global.setRoot("NotificationsPage");
}
}
and call it in the place of your navbar like this in any page
<default-header [title]="'Person'" [icon]="'search'"></default-header>