Remove a view from the back history - Ionic2 - ionic2

Anyone knows how to remove a view from the back history (or navigation stack) in ionic2?
In Ionic 1 I solved this with
this.$ionicHistory.nextViewOptions({
disableAnimate: true,
disableBack: true
});
Would be really useful, for example, to fully remove the login page of my application from the history once a successfully login was performed.
Just not showing the back button isn't enough in such case, since Android terminals got their own physical back button on the devices.
I tried, after my login function returned a successful promise and before pushing the next page in the stack:
this.navController.pop();
or
this.navController.remove(this.viewCtrl.index);
but unfortunately both weren't successful :(

obrejacatalin on the https://forum.ionicframework.com/t/solved-disable-back-in-ionic2/57457 found the solution
this.nav.push(TabsPage).then(() => {
const index = this.nav.getActive().index;
this.nav.remove(0, index);
});
so I guess it's important to push the next page first, wait for the promise answer and then remove the current view

To remove one backview you need to use startIndex and count of pages to remove from stack.
this.navCtrl.push(NextPage)
.then(() => {
const startIndex = this.navCtrl.getActive().index - 1;
this.navCtrl.remove(startIndex, 1);
});
See this document for more options like removeView(viewController):
https://ionicframework.com/docs/v2/api/navigation/NavController/#remove

I got the same issue with Ionic 3.
So, only two steps to reset history:
// ...
constructor(public navCtrl: NavController) { }
// ...
this.navCtrl.setRoot(NewPageWithoutPrev);
this.navCtrl.popToRoot();
// ...
Links:
https://ionicframework.com/docs/api/navigation/NavController/#setRoot
https://ionicframework.com/docs/api/navigation/NavController/#popToRoot

Related

cypress .next at end of list yields '' but I need to break instead

I am writing Cypress tests for an application that has a dynamic group/list of items. Each item has a details link that when clicked creates a popup with said details. I need to close that popup and move to the next item in the group.
I first tried to use the .each() command on the group and then would .click({multiple:true}) the details but the popup would cover the the next click. Adding {foce:true} does allow all of the popups to display but I don't think that is in the spirit of how the application should function.
My latest attempt has been to create a custom command using .next() to iterate through the group. This works but when .next() reaches the end of the group it yields "" and so the test ultimately fails.
The actual error I get is:
Expected to find element: ``, but never found it. Queried from element: <div.groups.ng-star-inserted>
the .spec.ts
describe('Can select incentives and view details', () => {
it('Views incentive details', () => {
cy.optionPop('section#Incentives div.groups:first')
})
})
the index.ts
Cypress.Commands.add('optionPop', (clickable) => {
cy.get(clickable).find('[ng-reflect-track="Estimator, open_selection_dial"]').click()
cy.get('mat-dialog-container i.close').click()
cy.get(clickable).next().as('clicked').then(($clicked) => {
//fails at .next ^ because '' is yielded at end of list
cy.wrap($clicked).should('not.eq','')
})
cy.optionPop('#clicked')
})
You basically have the right idea, but it might work better in a plain JS function rather than a custom command.
function openPopups(clickables) {
if (clickables.length === 0) return // exit when array is empty
const clickable = clickables.pop() // extract one and reduce array
cy.wrap(clickable)
.find('[ng-reflect-track="Estimator, open_selection_dial"]').click()
cy.get('mat-dialog-container i.close')
.should('be.visible') // in case popup is slow
.click()
// wait for this popup to go, then proceed to next
cy.get('mat-dialog-container')
.should('not.be.visible')
.then(() => {
openPopups(clickables) // clickables now has one less item
})
}
cy.get('section#Incentives div.groups') // get all the popups
.then($popups => {
const popupsArray = Array.from($popups) // convert jQuery result to array
openPopups(popupsArray)
})
Some extra notes:
Using Array.from($popups) because we don't know how many in the list, and want to use array.pop() to grab each item and at the same time reduce the array (it's length will control the loop exit).
clickables is a list of raw elements, so cy.wrap(clickable) makes the individual element usable with Cypress commands like .find()
.should('be.visible') - when dealing with popup, the DOM is often altered by the click event that opens it, which can be slow relative to the speed the test runs at. Adding .should('be.visible') is a guard to make sure the test is not flaky on some runs (e.g if using CI)
.should('not.be.visible').then(() => ... - since you have some problems with multiple overlapping popups this will ensure each popup has gone before testing the next one.

How to get current page from Navigation in ionic 2

I am new to Ionic2, and I am trying to build dynamic tabs based on current menu selection. I am just wondering how can I get current page using navigation controller.
...
export class TabsPage {
constructor(navParams: NavParams,navCtrl:NavController) {
//here I want to get current page
}
}
...
From api documentation I feel getActiveChildNav() or getActive() will give me the current page, but I have no knowledge on ViewController/Nav.
Any help will be appreciated. Thanks in advance.
Full example:
import { NavController } from 'ionic-angular';
export class Page {
constructor(public navCtrl:NavController) {
}
(...)
getActivePage(): string {
return this.navCtrl.getActive().name;
}
}
Method to get current page name:
this.navCtrl.getActive().name
More details here
OMG! This Really Helped mate, Tons of Thanks! #Deivide
I have been stuck for 1 Month, Your answer saved me. :)
Thanks!
if(navCtrl.getActive().component === DashboardPage){
this.showAlert();
}
else
{
this.navCtrl.pop();
}
My team had to build a separate custom shared menu bar, that would be shared and displayed with most pages. From inside of this menu component.ts calling this.navCtrl.getActive().name returns the previous page name. We were able to get the current page name in this case using:
ngAfterViewInit() {
let currentPage = this.app.getActiveNav().getViews()[0].name;
console.log('current page is: ', currentPage);
}
this.navCtrl.getActive().name != TheComponent.name
or
this.navCtrl.getActive().component !== TheComponent
is also possible
navCtrl.getActive() seems to be buggy in certain circumstances, because it returns the wrong ViewController if .setRoot was just used or if .pop was just used, whereas navCtrl.getActive() seems to return the correct ViewController if .push was used.
Use the viewController emitted by the viewDidEnter Observable instead of using navCtrl.getActive() to get the correct active ViewController, like so:
navCtrl.viewDidEnter.subscribe(item=> {
const viewController = item as ViewController;
const n = viewController.name;
console.log('active page: ' + n);
});
I have tested this inside the viewDidEnter subscription, don't know about other lifecycle events ..
Old post. But this is how I get current page name both in dev and prod
this.appCtrl.getActiveNav().getActive().id
Instead of
...
...
//In debug mode alert value is 'HomePage'
//In production/ signed apk alert value is 'n'
alert(activeView.component.name);
if (activeView.component.name === 'HomePage') {
...
...
Use this
...
...
//In debug mode alert value is 'HomePage'
//In production/ signed apk alert value is 'HomePage'
alert(activeView.id);
if (activeView.id === 'HomePage') {
...
...
Source Link
You can use getActive to get active ViewController. The ViewController has component and its the instance of current view. The issue is the comparsion method. I've came up to solution with settings some field like id:string for all my Page components and then compare them. Unfortunately simple checking function name so getActive().component.name will break after minification.

How to observe a computed property in EmberJS? Creating a FB like notification feature

I am building notification feature for my app just like Facebook's notification. I have almost made it work but just unable to observe a computed property.
Here is the scenario:
There are many deals and when a deal is updated(like it's name/ price is changed), the notification is sent through RabbitMQ. The object payload that we send, it has an attribute "status" which could be 'read' or 'unread'.
controller:
notificationsCount: function() {
var notifications = this.get('notifications');
var unreadCount = 0;
for (var i = 0; i < notifications.length; i++) {
if (notifications[i].status == 'unread') {
unreadCount++;
}
}
return unreadCount;
}.property('notifications.[]'),
Here, initially 'notifications' is an empty array. All the notifications coming from RMQ as object payloads goes inside this. This 'unreadCount' is what I want to show kinda like a small badge over the notification icon.
When I click the notification icon, all the notifications' status should change to 'read' from 'unread'.
controller:
action:{
readNotifications: function () {
var notifications = this.get('notifications');
for (var i = 0; i < notifications.length; i++) {
notifications[i].status = 'read';
}
},
}
Through debugging, I found everything is working fine till this point. But what I want is, once the user clicks the notification icon and all the notifications are marked as read, the notificationCount should be set as zero as there are no more any notifications that is unread.
Theoretically, I have to either observe notificationsCount or execute notificationsCount once inside readNotifications action. But I couldn't find a way to do it. If there is any other way, feel free to share.
Thanks in advance.
The short of it is that you should define your notificationsCount computed property to listen to notifications.#each.status instead of notifications.[]. .[] triggers when the array contents change (elements are added or removed), while an .#each.prop triggers when the prop property on any array element changes.
Refer to the relevant Ember.js docs for details on this.
Additionally, you can make your code more concise using NativeArray methods (because, since you are already using the .property() shorthand, you do have prototype extension enabled). Your entire notificationsCount could be written as
notificationsCount: function() {
return this.get('notifications').filterBy('status', 'unread').length;
}.property('notifications.#each.status'),
and your action as
readNotifications: function () {
this.get('notifications').setEach('status', 'read');
},

sencha touch list doesn't work after building app

I'm sure I'm missing something but I can't understand why a list that perfectly works in debug mode doesn't show in production.
Some details:
- the list is inside an Ext.navigation.View
- the list must show a filtered store by the itemtap event from another list
- the store reads from a remote json
- the build is for a web-app
this is the code I use to update the list:
listUpdate: function() {
console.log("sections_list update " + this.section);
section = this.section;
this.setStore(Ext.getStore('sections_remote'));
this.getStore().setFilters([function(item) {
return item.get('section')==section
}]);
this.getStore().load({
callback: function(records, operation, success) {
console.log("sections_list loaded "+records.length);
this.refresh();
},
scope: this
});
}
after loading, the records.length is always the total length and not the number of the filtered records but in debug version the list shows only the filtered records while in production shows nothing.
any ideas?
thanks in advance,
Daniele
I've just put all the semicolons and now it works.
Thank-you

Using jsPlumb in an Ember.js Application

I am trying to learn how to use jsPlumb in my Ember.js application so I put a minimal jsFiddle together to demonstrate how they could work together.
In this example so far I just insert the nodes and add them to jsPlumb. I have not added any links between them yet. At this stage the nodes should be draggable but they are not.
Error I get in the browser console:
TypeError: myOffset is null
Which points to this part of the code in jsPlumb:
for (var i = 0; i < inputs.length; i++) {
var _el = _getElementObject(inputs[i]), id = _getId(_el);
p.source = _el;
_updateOffset({ elId : id });
var e = _newEndpoint(p);
_addToList(endpointsByElement, id, e);
var myOffset = offsets[id], myWH = sizes[id];
var anchorLoc = e.anchor.compute( { xy : [ myOffset.left, myOffset.top ], wh : myWH, element : e });
e.paint({ anchorLoc : anchorLoc });
results.push(e);
}
You can see that a simple example without integration with Ember.js works as expected. I know that this version of jsPlumb I have uses jquery-ui to clone elements and support drag and drop. A post here shows there is an issue with jquery-ui draggable functionality in Ember. However, I am not sure if I am hitting the same problem. If that is the same issue I am having, I would appreciate some help in how to implement the solution suggested there in my application. I am new to both Ember and jsPlumb, so I would appreciate clear guidance about what is going on here and what path to take.
How can I make this example work?
Luckily my suspicion was wrong and the issue was not with metamorph. jsPlumb and Ember work just fine together, without any hacks. I put a little example in this jsFiddle that demonstrates how they could work together.
Credit goes to Simon Porritt who helped me at jsPlumb user group to identify the problem. What I was missing was a simple call to jsPlumb.draggable element. However, the above error persisted after this fix.
The particular error message above was result of Ember calling didInsertElement an extra time with an element which did not make it to the DOM. I have reported this issue. One workaround is to check the element makes it into the DOM before calling jsPlumb. As you can see in the jsFiddle I have added this code in the didInsertElement hook to get rid of the error.
elementId = this.get 'elementId'
element = $("#"+elementId)
if element.size() > 0
console.log "added element", element
jsPlumb.addEndpoint element, endpoint
jsPlumb.draggable element
else
console.log "bad element"
Hope this helps someone.