Is there a way to refresh only a page i.e. only one screen in ionic2.
I tried :
window.location.reload();
and
location.reload();
but it rebuilds the app .. is there a way to refresh only that page (particular screen).
Also tried:
<ion-input *ngIf="no_internet === 1" (click)="refresh($event)"></ion-input>
in TypeScript:
refresh(refresher) {
console.log('Begin async operation', refresher);
setTimeout(() => {
console.log('Async operation has ended');
refresher.complete();
}, 2000);
}
Try this code :
this.navCtrl.setRoot(this.navCtrl.getActive().component);
You could also use the ionic refresher, to create a pull to refresh action on the page
http://ionicframework.com/docs/v2/api/components/refresher/Refresher/
I would do that : (based on #Ahmad Aghazadeh answer)
this.navCtrl.push(this.navCtrl.getActive().component).then(() => {
let index = this.viewCtrl.index;
this.navCtrl.remove(index);
})
=> Push this page once more (loading it again)
=> Remove the page we were on (using index)
Example of using ion-refresher in an async function in ionic 3:
in your .html file:
<ion-content no-padding >
<ion-refresher (ionRefresh)="doRefresh($event)">
<ion-refresher-content></ion-refresher-content>
</ion-refresher>
and in your .ts file:
constructor(...) {
...
samplefuncion(null){
asyncFunction().then(()=>{
...//after success call
...
if (event)
event.complete();
},(error)=>{
....
if (event)
event.complete();
})
}
doRefresh(event) {
samplefuncion(event);
}
If you are willing to follow a common convention, I have found a very easy way to reload the current view (including all of its parameters). I tested this using Ionic3, but it should still apply in Ionic 2
Move all of your initialization code for every page into ionViewDidLoad(), which is run ONCE on the first time the view is loaded
import { Component } from '#angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { Api } from '../../providers/api';
import { Movie } from '../../interfaces/movie';
#Component({
selector: 'page-movie-info',
templateUrl: 'movie-info.html'
})
export class MovieInfoPage {
constructor(
public navCtrl: NavController,
public navParams: NavParams,
public api: Api
) {
}
/**
* Run all page initialization in this method so that this page
* can be refreshed simply by re-calling this function
*/
ionViewDidLoad() {
//access any parameters provided to the page through navParams.
var movieId = this.navParams.data.movieId;
this.api.movies.getById(movieId).then((movie) => {
this.movie = movie;
});
}
public movie: Movie;
}
From anywhere else in the app, you can reload the current view with this code
//get the currently active page component
var component = this.navController.getActive().instance;
//re-run the view load function if the page has one declared
if (component.ionViewDidLoad) {
component.ionViewDidLoad();
}
Html:
<ion-refresher (ionRefresh)="doRefresh($event)">
<ion-refresher-content></ion-refresher-content>
</ion-refresher>
</ion-content>
TypeScript :
#Component({...})
export class NewsFeedPage {
doRefresh(refresher) {
console.log('Begin async operation', refresher);
setTimeout(() => {
console.log('Async operation has ended');
refresher.complete();
}, 2000);
}
}
source : Ionic doc
Try this, just pop one page and then push that page again.
this.navCtrl.pop();
this.navCtrl.push(NewPage);
Hope this will help.
Try this: $window.location.reload(); $route.reload() use to reload route.
if you are using $stateProvider : $state.go($state.current, {}, {reload: true});
or
var currentPageTemplate = $route.current.templateUrl;
$templateCache.remove(currentPageTemplate);
$route.reload();
Related
Hi i'm building a chat app with angular for a school project i'm using firebase for my backend and i have an issue with my ngfor.
For exemple if i reload the page i will see nothing unless i hover my routerlink on my navbar. However sometime it will work after some time on the page without any action
When i recieve message i need to be on the page to see them ...
When i reload my page in first time my array is empty this may be what makes the ngfor bug
array on reload.
I'm using ngOnInit() to subscribe :
messages: Message[];
messageSubscription: Subscription;
constructor(private messageService: MessageService, private router: Router) {
}
ngOnInit(): void {
this.messageSubscription = this.messageService.messageSubject.subscribe(
(messages: Message[]) => {
console.log(messages)
this.messages = messages;
}
);
this.messageService.getMessage();
this.messageService.emitMessage();
}
ngOnDestroy(): void {
this.messageSubscription.unsubscribe();
}
This is my html template :
<div *ngFor="let message of messages" class="message-box">
<img [src]="message.photoURL" class="profile-picture">
<div class="content-box">
<div class="information">
<p class="username">{{message.displayName}}</p>
<p class="date">{{message.createdAt | date: 'short'}}</p>
</div>
<p class="text">{{message.text}}</p>
</div>
</div>
Here you can find my service with my getMessage() function and emitMessage():
messages:Message[] = [];
messageSubject = new Subject<Message[]>();
constructor() { }
emitMessage(){
this.messageSubject.next(this.messages);
}
saveMessage(newMessage: Message){
firebase.database().ref('/message').push(newMessage);
}
getMessage(){
firebase.database().ref('/message')
.on('value', (data) => {
this.messages = data.val() ? Object.values(data.val()): [];
this.emitMessage();
});
}
And this is the repo of my project: https://github.com/Zuxaw/AngularChatApp
If anyone has a solution I'm interested
Problem is, your firebase library is not Angular specific.
This means you some times need to make sure its code, mostly its event callbacks, run within an Angular zone (google to read about it) to make sure a change detection 'tick' is invoked when data changes.
message.service.ts
import { Injectable, NgZone } from '#angular/core';
// ...
constructor(private zone: NgZone) { }
// ..
getMessage(){
firebase.database().ref('/message')
.on('value', (data) => {
this.zone.run(() => {
this.messages = data.val() ? Object.values(data.val()): [];
this.emitMessage();
});
});
}
I think you might need to use the child_added event instead of value in your getMessage method.
Check if you're receiving data on time in your getMessage method, if not it's most probably, because of the event.
But one thing that I don't understand is why you're calling emitMessage inside getMessage and also calling it inside your component after getMessage, try to evade that.
I have a problem in Ionic 2 and maybe one of you could help me out.
Basically, I have a provider that i'm building which includes the function BLE. I include this provider in one my page. And from this page I can call the function without problem. But what I want, is to access the public variable that is the provider. This variable is a status connection (true or false) and I want to access it from my page to know if I'm connected with BLE or not.
here's my code
BleProvider.ts
#Injectable()
export class BleProvider {
public isConnected:boolean;
constructor(public http: Http) {
console.log('Hello BleProvider Provider');
}
connectToDevice(device){
this.isConnected = true;
}
}
My page Login.ts
import { BleProvider } from '../../providers/ble/ble'
#IonicPage()
#Component({
selector: 'page-login',
templateUrl: 'login.html',
})
#NgModule({
providers: [BleProvider],
})
export class LoginPage {
constructor(public ble: BleProvider){
ble.connectToDevice();
}
function testIsConnected(){
console.log("isConnected value: " + this.ble.isConnected);
}
}
The console.log will return "isConnected value: undefined. And if i set isConnected in the constructor of the provider (e.g. this.isConnected = false) even that the function connectToDevice will set isConnected at true, when i call it from my page it will return the value false.
Can someone explain to me what happens and how to solve this?
Adding to my comment above. I think this would work for you.
constructor(public ble: BleProvider){
}
ngOnInit(){
this.ble.connectToDevice()
}
I hope that helps.
I'm having some difficulties with Ionic 2 and setting up global variables. The structure of my app is as follows:
Main app
|
|--- Page1 (Info)
|--- Page2 (Map)
|--- Page3 (List)
|
|--- ItemTabsPage
|
|---tab1
|---tab2
|---tab3
My intention is to show a list in Page3, and once one item is selected, to show additional information in tabs.
I send the information from Page 3 to the page with the tabs using:
itemTapped(event, item) {
this.nav.push(ItemTabsPage, {
item: item
});
}
The problem is that I can't do the same to send the info to the child tabs. I would like to show different information depending on which item is selected. I have tried defining an injectable globalVars.js to store the value in a variable:
import {Injectable} from 'angular2/core';
#Injectable()
export class GlobalVars {
constructor(myGlobalVar) {
this.myGlobalVar = "";
}
setMyGlobalVar(value) {
this.myGlobalVar = value;
}
getMyGlobalVar() {
return this.myGlobalVar;
}
}
and then updating the code of itemTapped in the list as follows:
itemTapped(event, item) {
this.nav.push(ItemTabsPage, {
item: item
});
this.globalVars.setMyGlobalVar(item);
}
However, I always get the same error:
Uncaught EXCEPTION: Error during evaluation of "click"
ORIGINAL EXCEPTION: TypeError: Cannot read property 'setMyGlobalVar' of undefined
The code for page3 is:
import {Page, NavController, NavParams} from 'ionic-angular';
import {ItemService} from '../services/ItemService';
import {ItemTabsPage} from '../item/item-tabs/item-tabs';
import {GlobalVars, setMyGlobalVar} from '../../providers/globalVars';
import {Http} from 'angular2/http';
import 'rxjs/add/operator/map';
#Page({
templateUrl: 'build/pages/item-list/item-list.html',
providers: [ItemService]
})
export class ItemListPage {
static get parameters() {
return [[NavController], [NavParams], [Http]];
}
constructor(nav, navParams, http, globalVars) {
this.nav = nav;
// If we navigated to this page, we will have an item available as a nav param
this.selectedItem = navParams.get('item');
this.http = http;
//this.items = null;
this.globalVars = globalVars;
this.http.get('https://website-serving-the-info.com/items.json').map(res => res.json()).subscribe(data => {
this.items = data.items;
},
err => {
console.log("Oops!");
});
}
itemTapped(event, item) {
this.nav.push(ItemTabsPage, {
item: item
});
this.globalVars.setMyGlobalVar(item);
}
}
Anyone have any suggestion? My Ionic installation is:
Cordova CLI: 6.1.1
Gulp version: CLI version 3.9.1
Gulp local: Local version 3.9.1
Ionic Framework Version: 2.0.0-beta.4
Ionic CLI Version: 2.0.0-beta.25
Ionic App Lib Version: 2.0.0-beta.15
OS: Distributor ID: LinuxMint Description: Linux Mint 17.3 Rosa
Node Version: v5.11.0
The easiest way I use is to create a file app/global.ts
export var global = {
myvar : 'myvar 01',
myfunction : function(msg) {
alert(msg);
}
};
Then import and use freely in other classes:
import {global} from "../../global";
constructor() {
global.myfunction('test');
}
and if you want to use this global to component HTML page as below
export class HomePage {
Global: any = Global;
now it is available in HTML as below
<div [style.display]="Global.splash ? 'flex': 'none'" >
You're on the right track. And some of the other answers will work, but the Ionic team is recommending you not use globals via a globals file. Instead, they recommend the use of Providers (as you're attempting to do).
You're provider is missing the actual variable declaration.
#Injectable()
export class GlobalVars {
myGlobalVar: string = '' // this is the line you're missing
constructor(myGlobalVar) {
this.myGlobalVar = "";
}
}
You should also note that you are not exporting the function setMyGlobalVar(). You are exporting the class GlobalVars which contains the function setMyGlobalVar().
I believe if you make those changes it should work.
edit
I'd also be careful of this line this.globalVars = globalVars; in your Page3. This will cause a rewrite of your globalVars each time Page3 is created.
I have exactly the same scenario, and would like to share my approach.
my understanding is that, in ionic2, the injection is implemented as instance. which means each time you enter a page, a new instance of the injection is created.
so direct access to a static value does not fit here; you have to somehow bridge the gap.
my approach goes as this:
you still defined a static value in your service provider, yet you define instance "getter", and "setter" for that value.
in your page implementation, you inject the service as a parameter of the constructor.
in the constructor, you have to "new" an instance of the service; and call the "getter", and "setter". see my code snippets below:
export class TransSender {
static _count:number = 0;
static _pushed:number = 0;
...
public static setter(count:number, pushed:number,...) {
TransSender._count = count;
TransSender._pushed = pushed;
}
public get count(){
return TransSender._count;
}
public get pushed(){
return TransSender._pushed;
}
...
}
I actually provide a static collective setter for the service to get value from backend in a static way.
my page implementation runs likes this
import {TransSender} ...;
#Component({
templateUrl: 'build/pages/basics/basics.html',
providers: [TransSender]
})
export class Page {
...
constructor(tSender: TransSender,...) {
...
tSender = new TransSender();
TransSender.setter(1,2,3,4,5,6,7,8);
console.log(tSender.count);
}
}
in your display (html), your will refer to tSender rather than TransSender
this might look a bit stupid. yet I can not find any other solution.
with the release of ionic2 Beta9, bootstrap was re-introduced into the frame. so I am exploring new possibilities
cheers
In your class ItemListPage, try this static parameters method before your constructor:
static get parameters() {
return [[NavController], [NavParams], [Http], [GlobalVars]];
}
I am thinking that you are setting your globalVars variable in the constructor to 'undefined' and therefore you cannot call a function on something that is undefined.
You seem to inject the GlobalVars provider incorrectly in ItemLisyPage.
I'm developing a web site using Angular 2.
Is there any way to disable or trigger Browser back button using Angular 2?
Thanks
Not sure if this is already sorted, but posting the answer nonetheless, for future references.
To tackle this, you basically need to add a listener in your app-component and setup a canDeactivate guard on your angular-router.
// in app.component.ts
import { LocationStrategy } from '#angular/common';
#Component({
selector: 'app-root'
})
export class AppComponent {
constructor(
private location: LocationStrategy
) {
// check if back or forward button is pressed.
this.location.onPopState(() => {
// set isBackButtonClicked to true.
this.someNavigationService.setBackClicked(true);
return false;
});
}
}
// in navigation guard
#Injectable()
export class NavigationGuard implements CanDeactivate<any> {
constructor(private someNavigationService: SomeNavigationService) {}
canDeactivate(component: any) {
// will prevent user from going back
if (this.someNavigationService.getBackClicked()) {
this.someNavigationService.setBackClicked(false);
// push current state again to prevent further attempts.
history.pushState(null, null, location.href);
return false;
}
return true;
}
}
import { LocationStrategy } from '#angular/common';
constructor( private location: LocationStrategy){
// preventing back button in browser implemented by "Samba Siva"
history.pushState(null, null, window.location.href);
this.location.onPopState(() => {
history.pushState(null, null, window.location.href);
});
}
its working fine to me 100% in angular2/4/5
This Very simple, use the following code, This example code is from plain javascript i have converted this into angular and using in my 2-3 projects
// Inject LocationStrategy Service into your component
constructor(
private locationStrategy: LocationStrategy
) { }
// Define a function to handle back button and use anywhere
preventBackButton() {
history.pushState(null, null, location.href);
this.locationStrategy.onPopState(() => {
history.pushState(null, null, location.href);
})
}
You can define preventBackButton in any service as well and call it from there
Snippet that I use and works across all major browsers!
ngOnInit() {
history.pushState(null, null, location.href);
this.subscription = fromEvent(window, 'popstate').subscribe(_ => {
history.pushState(null, null, location.href);
this.openModal(`You can't make changes or go back at this time.`, 'Okay');
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
I've tried all the solutions mentioned above but none of them worked perfectly for me. Finally I've found this npm module that worked immediately and perfectly, after two days of failed attempts.
Github: https://github.com/Zatikyan/angular-disable-browser-back-button#readme
A bit late perhaps but maybe somebody can use it.
This is a solution I use for a page with tabs (Bootstrap 4 style) where each tab is a component.
#Injectable()
export class CanNavigateService {
private static _isPermissionGranted = true
public navigationAttempt = new Subject<boolean>()
//-------------------------------------------------------------//
/**Will the next navigation attempt be permitted? */
updatePermission(isPermissionGranted: boolean) {
CanNavigateService._isPermissionGranted = isPermissionGranted
}//updatePermission
//-------------------------------------------------------------//
/**Broadcast the last attempt and whether it was permitted */
updateNavigationAttempt(wasPermissionGranted: boolean) {
this.navigationAttempt.next(wasPermissionGranted)
}//updatePermission
//-------------------------------------------------------------//
/**Can we navigate? */
public isPermissionGranted(): boolean {
return CanNavigateService._isPermissionGranted
}//isPermissionGranted
}//Cls
NavigationGuard like #Jithin Nair above but also broadcasts when an attempt to navigate was made and whether it was permitted. Subscribers of CanNavigateService can use it to decide what to do instead of back navigation.
#Injectable()
export class NavigationGuard implements CanDeactivate<any> {
constructor(private canNavigateService: CanNavigateService) { }
//--------------------------------------------------------------------//
// will prevent user from going back if permission has not been granted
canDeactivate(component: any) {
let permitted = this.canNavigateService.isPermissionGranted()
this.canNavigateService.updateNavigationAttempt(permitted)
if (!permitted) {
// push current state again to prevent further attempts.
history.pushState(null, null, location.href)
return false
}
return true
}//canDeactivate
}//Cls
Usage:
constructor(private _navigateService: CanNavigateService) {
super()
_navigateService.navigationAttempt.subscribe(wasPermitted => {
//If navigation was prevented then just go to first tab
if (!wasPermitted)
this.onTabSelected( this._firstTab)
})
}//ctor
//----------------------------------------------------------------------------//
onTabSelected(tab) {
this._selectedTab = tab
//If it's not the first tab you can't back navigate
this._navigateService.updatePermission(this._selectedTab == this._firstTab)
}//onTabSelected
try to use this
window.onpopstate = function (e) { window.history.forward(1); }
Try this
<script type = "text/javascript" >
history.pushState(null, null, 'pagename');
window.addEventListener('popstate', function(event) {
history.pushState(null, null, 'pagename');
});
</script>
where change 'pagename' to your page name and put this into head section of page.
If you want to prevent a route to be reached you can add the #CanActivate() decorator to your routing component
#Component({selector: 'control-panel-cmp', template: `<div>Settings: ...</div>`})
#CanActivate(checkIfWeHavePermission)
class ControlPanelCmp {
}
See also
- Angular 2: Inject a dependency into #CanActivate? for access to global services.
- Angular2 Router - Anyone know how to use canActivate in app.ts so that I can redirect to home page if not logged in
Why not use just this. Should avoid browser insert automatically things in the history. Just insert in some main.ts (or elsewhere executed at startup)
history.pushState = () => {};
Object.freeze(history);
This issue occurs on IE browser. Use below mentioned code it will resolve your issue.
#HostListener('document:keydown', ['$event'])
onKeyDown(evt: KeyboardEvent) {
if (
evt.keyCode === 8 || evt.which === 8
) {
let doPrevent = true;
const types =['text','password','file','search','email','number','date','color','datetime','datetime-local','month','range','search','tel','time','url','week'];
const target = (<HTMLInputElement>evt.target);
const disabled = target.disabled || (<HTMLInputElement>event.target).readOnly;
if (!disabled) {
if (target.isContentEditable) {
doPrevent = false;
} else if (target.nodeName === 'INPUT') {
let type = target.type;
if (type) {
type = type.toLowerCase();
}
if (types.indexOf(type) > -1) {
doPrevent = false;
}
} else if (target.nodeName === 'TEXTAREA') {
doPrevent = false;
}
}
if (doPrevent) {
evt.preventDefault();
return false;
}
}
}
If you are looking to disable browser back button in angular(7/8/9/10)... Try this link and install package using npm.
1) npm install --save angular-disable-browser-back-button
2) import { NgModule } from '#angular/core';
import { BackButtonDisableModule } from 'angular-disable-browser-back-button';
#NgModule({
...
imports: [
...
BackButtonDisableModule.forRoot()
],
...
})
export class AppModule {}
3) BackButtonDisableModule.forRoot({
preserveScrollPosition: true
})
Please use this link given below.. reference taken from.
[https://www.npmjs.com/package/angular-disable-browser-back-button][1]
This isn't Angular2 related problem. You can send the user back in history. See Manipulating the browser history, history.go() method particular:
window.history.go(-1);
However, I don't think there's a way to cancel or disable default browser action on pressing back button in the browser window because that could be very easily abused.
As an alternative you can show a dialog window when user tries to leave the page: javascript before leaving the page
Add following code in TS file of the component, where you don't want to go back.
#HostListener('window:hashchange', ['$event'])
hashChangeHandler(e) {
window.location.hash = "dontgoback";
}
step 1: Import Locatoion from angular commmon
import {Location} from "#angular/common";
step 2: Initialise in constructor
private location: Location
step 3: Add function in ngOnInit of the respective coponent,
this.location.subscribe(currentLocation => {
if (currentLocation.url === '*/basic-info*') {
window.onpopstate = function (event) {
history.go(1);
}
}
});
Note: Here /basic-info will be replaced by your path.
If first time it is not working, try adding outside subscribe,
let currentUrl = window.location.href;
let tmpVar = currentUrl.includes('/basic-info');
if (currentUrl.includes('/basic-info')) {
window.onpopstate = function (event) {
history.go(1);
}
}
I tried passing parameters in push method of ionic2. like this
this.nav.push(SecondPage, {
thing1: data1,
thing2: data2
});
but is there any way to pass parameter in pop().
This is how I achieved it in ionic-3 and find it easier.
Page from where we pop()
this.navCtrl.getPrevious().data.thing1 =data1;
this.navCtrl.getPrevious().data.thing2 =data2;
this.navCtrl.pop();
Page after pop():
public ionViewWillEnter() {
this.thing1 = this.navParams.get('thing1')|| null;
this.thing2 = this.navParams.get('thing2')|| null;
}
I suggest you use Events. All you have to do is to subscribe to an event on the parent page and then publish the event on the child passing the data you want:
// taken from the docs
import { Events } from 'ionic-angular';
constructor(public events: Events) {}
// first page (publish an event when a user is created)
function createUser(user) {
console.log('User created!')
events.publish('user:created', user);
}
// second page (listen for the user created event)
events.subscribe('user:created', (userEventData) => {
// userEventData is an array of parameters, so grab our first and only arg
console.log('Welcome', userEventData[0]);
});
Currently, I believe that there is no way of accomplishing this.
There is a Github issue for it though, that has got some great discussion on it by the Ionic core team. It sounds like they have added it to the Ionic 2 roadmap, too! The Github issue also has some proposed work-arounds, such as adding the ParentPage to the NavParams going to the ChildPage, but it is all quite a bit hacky.
UPDATE: IT WAS SUPPOSED TO WORK, BUT IT DOES NOT
Seems like there is |See Doc Reference|
pop(opts) takes one parameter of type object
so
to go one step back
this.nav.pop({
thing1: data1,
thing2: data2
});
and to go to a specific view in the history stack
this.nav.popTo(SecondPage, {
thing1: data1,
thing2: data2
});
and to go to root of the stack
this.nav.popToRoot({
thing1: data1,
thing2: data2
});
To retrieve the params (I guess this should work. untested!)
export class SecondPage{
constructor(params: NavParams){
this.params = params;
console.log(this.params.get('thing1'));
}
}
Use popTo() instead of pop()
popTo() has params? parameter where you can pass in your paramaters like so:
this.nav.popTo(SecondPage, {
thing1: data1,
thing2: data2
});
pass in a callback when transitioning by aaronksaunders in this forum
https://forum.ionicframework.com/t/solved-ionic2-navcontroller-pop-with-params/58104/4
Going to try it out.
For sent data with pop you can use getPrevious() method.
When leaving from current page get previous page and send data
ionViewWillLeave() {
this.navCtrl.getPrevious().data.formData = {credentials: {...}};
}
In next page get data from navParams
ionViewWillEnter() {
if (this.navParams.get('formData')) {
// do something
}
}
If you are using ionic-angular application, you can use ionic-angular Events
page1.ts
import { Events,NavController } from 'ionic-angular';
export class page1 {
constructor(private events: Events,
private nvCtrl: NavController
) {}
goToPage2() {
this.navCtrl.pop();
this.event.publish('your-event');
}
}
page2.ts
import { Events} from 'ionic-angular';
export class page1 {
constructor(private events: Events,
private nvCtrl: NavController
) {}
ionViewDidLoad() {
this.events.subscribe('your-event');
}
}