Navigation stack needs at least one root page - ionic2

When I call this.navCtrl.popAll();, I get this error:
Error: Uncaught (in promise): navigation stack needs at least one root page
But the root page is set in app.component.ts:
rootPage = LandingPage;
What is still missing?

I have the same issue
Error: Uncaught (in promise): navigation stack needs at least one root page
... when I use registerbackbutton for hardware back button in Android. And then I try to call this.navCtrl.pop() for back to previous page.
My solution:
In app.component.ts
import { App } from 'ionic-angular/components/app/app';
/* define in constructor */
constructor(public platform: Platform, app: App){
this.platform.ready().then(() => {
this.platform.registerBackButtonAction(() => {
app.navPop();
});
})
}

Related

Can't test Material-ui Modal with react test renderer

When trying to write a simple test with jest lib for Modal component like this
import { Modal } from '#material-ui/core';
import React from 'react';
import TestRenderer from 'react-test-renderer';
describe('Material Modal test', () => {
it('It should render', () => {
const testRenderer = TestRenderer.create(
<Modal open={true}>
<div>Test</div>
</Modal>
);
console.log(testRenderer.toJSON());
});
});
I get an error:
console.error node_modules/react-test-renderer/cjs/react-test-renderer.development.js:120
Warning: An invalid container has been provided. This may indicate that another renderer is being used in addition to the test renderer. (For example, ReactDOM.createPortal inside of a ReactTestRenderer tree.) This is not supported.
in div (created by ForwardRef(Modal))
in ForwardRef(Portal) (created by ForwardRef(Modal))
in ForwardRef(Modal) (at spinnerWaitingWindow.spec.tsx:10)
console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29
Error: Uncaught [TypeError: parentInstance.children.indexOf is not a function]
Did anyone have a clue why this happens and how to setup test library?

Ionic Deep linker view does not update on browser back button event

I have a PWA built with ionic deep linker. I have done a demo here https://stackblitz.com/edit/ionic-mee2ut?file=app%2Fcustomer%2Fcustomer.component.html where the browser back button doesn't work as expected.
Steps to reproduce
1.In Dashboard page click on edit button.It will navigate to customer
page(see URL.It is changed to /Customer/CustomerId).
2.In Customer page, you will see the customer info and other customers
list, there click edit from other customers list.This will open another
page.(see URL.It is changed to /Customer/CustomerId).
3.Click on browser back button u can see that the URL is changed but the
view is not updated.
If I repeat steps 1 & 2 then click on nav back button instead of browser button then it works correctly.Both the URL and the view gets updated.
Is there something I am doing wrong because the browser back button does not work as expected or this is issue of ionic framework.
This is how i navigate between views
EditCustomer(Customer: any) {
this.navCtrl.push('Customer', { Id: Customer.Id, Name: Customer.Name });
}
Can somebody please tell me a way how to resolve this issue?
I saw your code in the above url, you are passing id as param but not the name so, that is the reason url is changing but data is not reflected i modified your code in app.module.ts file please replace this code in your app.module.ts file
IonicModule.forRoot(MyApp, {}, {
links: [
{ component: DashboardComponent, name: 'Dashboard', segment: 'Dashboard' },
{ component: CustomerComponent, name: 'Customer', segment: 'Customer/:Id/:Name' }
]
})
Please replace your app.module.ts with the following code
import { Component } from '#angular/core';
import { Platform, IonicApp, App } from 'ionic-angular';
#Component({
templateUrl: 'app.html'
})
export class MyApp {
rootPage:any = 'Dashboard';
constructor(private _app: App, platform: Platform, private _ionicApp: IonicApp,) {
platform.ready().then(() => {
this.setupBackButtonBehavior();
});
}
private setupBackButtonBehavior () {
// If on web version (browser)
if (window.location.protocol !== "file:") {
// Register browser back button action(s)
window.onpopstate = (evt) => {
//Navigate back
if (this._app.getRootNav().canGoBack())
this._app.getRootNav().pop();
};
}
}
}
I was able to use something like this:
let randomID = this.makeId(5); // random string id
this.navCtrl.push('path', {
eventID: eventID,
instituteID: instituteID,
randomID: randomID
}, {
id: `path/${eventID}/${instituteID}/${randomID}`
});
This "id" seems to fix it, but if you can go to the same page, then it requires a "random" value to separate each visit to that page.
#IonicPage({
name: 'path',
segment: 'path/:instituteID/:eventID/:randomID'
})
It looks like, by default, it uses the name of the page as an id for that view. If multiple views have same id => issue when using browser back/forward. That's where the random comes in, to separate multiple instances of the same page.

Ionic 2: Loading screen does not get dismissed

I have an application made with Ionic 2, The work flow is like this
Case A . When user is using app for the first time
User Logs in (loading is shown)
When successfully logged in loading window is hidden and user is forwarded to Dashboard page.
In dashboard page items are loaded via ajax request.
Case B. When user is already logged in before
The first screen is Dashboard and items are loaded via ajax request.
Problem
In case A, when user logs in and forwarded to DashboardPage, the loading screen doesn't gets dismissed. Sometimes it gets dismissed but most of the time it doesnot? Is this an ionic bug or am I doing something wrong??
Here is my DashboardPage
//imports here
export class DashboardPage {
public loadingmsg: any;
public ajaxRequest: any;
constructor(
public navCtrl: NavController,
public navParams: NavParams,
private webservice: WebService,
private loadingCtrl: LoadingController
)
{
this.loadDashboardContents();
}
loadDashboardContents(){
//other codes
this.loadingmsg = this.loadingCtrl.create({
content:"Loading contents, please wait..."
});
this.loadingmsg.present();
this.ajaxRequest = this.webservice.getDashboardContents(params).subscribe(data => {
this.loadingmsg.dismiss().then(()=>{
//other codes to save retrieved data to localstorage.
});
});
}
}
UPDATE
The login method from login page
loginUser(){
this.loading=this.loadingctrl.create({
content:"Logging in, please wait..."
});
this.loading.present();
this.ajaxRequest = this.webservice.loginUser(params).subscribe(data => {
this.loading.dismiss();
if(data.status =="ok"){
this.navctrl.push(DashboardPage).then(()=>{
const index = this.viewCtrl.index;
this.navctrl.remove(index);
});
}else{
//show error alert
}
}, err =>{
this.loading.dismiss();
});
}
My Ionic and cordova version information
Ionic Framework: 3.5.0
Ionic App Scripts: 1.3.9
Angular Core: 4.1.3
Angular Compiler CLI: 4.1.3
Node: 6.10.3
OS Platform: Windows 10
Cordova Version: 6.5.0
I am currently using loading in my project and it works well in all case. To ensure loading will always dismiss you need to add some code:
1. duration, dismissOnPageChange
let loading = this.loadingCtrl.create({
content: "",
duration: 5000, //ms
dismissOnPageChange: true
})
2. dissmis when ajax call success or error:
.subscribe(success=>{
//some code
loading.dismiss();
},error=>{
//some code
loading.dismiss();
})
It may be due to the this reference inside your subscribe method. I would try declaring loadingmsg locally and removing this.
loadDashboardContents(){
//other codes
let loadingmsg = this.loadingCtrl.create({
content:"Loading contents, please wait..."
});
loadingmsg.present();
this.ajaxRequest = this.webservice.getDashboardContents(params).subscribe(data => {
loadingmsg.dismiss().then(()=>{
//other codes to save retrieved data to localstorage.
});
});
}

Reload model/update template on createRecord save

I see this question is being ask all over again still don't find solution that works for such a trivial task.
This url displays a list of navigations tabs for workspaces.
http://localhost:4200/users/1/workspaces
Each of tab resolves to
http://localhost:4200/users/1/workspaces/:wid
Also on the I have a button that suppose to create a new workspace as well as new tab.
Here how controller for looks:
export default Ember.Controller.extend({
actions: {
newWorkspace: function () {
this.get('currentModel').reload();
var self = this;
var onFail = function() {
// deal with the failure here
};
var onSuccess = function(workspace) {
self.transitionToRoute('dashboard.workspaces.workspace', workspace.id);
};
this.store.createRecord('workspace', {
title: 'Rails is Omakase'
}).save().then(onSuccess, onFail);
}
}
});
When I click on button I see in ember inspector new record indeed created as well as url redirected to id that represents newly created workspace.
My question is how to force model/template to reload. I have already killed 5h trying model.reload() etc. Everything seem not supported no longer. Please please help.
UPDATE
When adding onSuccess
model.pushObject(post);
throws Uncaught TypeError: internalModel.getRecord is not a function
I believe you should call this.store.find('workspace', workspace.id) for Ember Data 1.12.x or earlier. For 1.13 and 2.0 there are more complicated hooks that determine whether or not the browser should query the server again or use a cached value; in that case, call this.store.findRecord('workspace', workspace.id, { reload: true }).
I do not know if this help. I had a similar problem. My action was performed in the route. Refresh function took care of everything.

Ember Data creates local record on GET that returns 404

When I request a single resource that returns a 404 (or 403 for that matter) Ember Data is creating a local record.
For example, I load my app from scratch at /items/123. The adapter does a request for GET /items/123 which results in a 404 but now I have an item record in my local store with id=123. All attributes are undefined expect where the model defines default values.
Also, all model flags are false except isValid which is true.
Is this excepted behaviour? It seems strange that the local record gets created even though the server is saying that it doesn't exist (or that the user is not allowed to see it).
Details
I'm running Ember 1.8.1 and Ember Data 1.0.0-beta.11.
Here's what I have for Routes—pretty basic stuff:
// itemsRoute, TOP LEVEL
model: function() {
return this.store.find('item');
}
// itemRoute, CHILD LEVEL
model: function(params) {
return this.store.find('item', params.item_id); // <-- this returns 404
},
actions: {
error: function(err) {
this.replaceWith('items'); // jump out to main list view
return true; // ensure error bubbles up
}
}
The rejection in the model hook is working because the error action is triggered and I'm redirected out the top level /items view. But I still end up with a local record for an item that doesn't exist.
After thinking about this a little more... try altering your error handler in itemRoute from...
actions: {
error: function(err) {
this.replaceWith('items'); // jump out to main list view
return true; // ensure error bubbles up
}
}
to...
actions: {
error: function(err) {
this.transitionTo('items'); // jump out to main list view
return false; // Stop event bubbling - we've handled it.
//You could also console.log parts or all of your error
//You can return true too if you want to keep the event bubbling.
}
}
I don't have a concrete reason for why this would be yet. Waiting to hear back from you if it worked.
This is most definitely a bug. It seems this was fixed a while back but as was reintroduced by a change on March 14.
I've submitted a bug report https://github.com/emberjs/data/issues/3085