4
votes

I have a workflow where users can edit a song's information. When a user is on a song page, they can click the edit button to bring up the editing page. For example if a user is viewing a submission and would like to edit, they would go from the release page to the submit page using navigateByURL(tabs/(submit:submit/:artist/:submission):

/tabs/(home:release/isrk2mpkiq) to ->

/tabs/(submit:submit/2zmrsXMHxagFz6vI2cD7r6/isrk2mpkiq)

(note how these are on two different tabs/outlets: Home and Submit)

Edit mode is determined by subscribing to the route params and if an :artist (2zmrsXMHxagFz6vI2cD7r6) and :submission (isrk2mpkiq) are present in the url then we know to display the edit prompt (with all of the details filled in to the inputs) instead of the empty submission prompt, using the following within the ngOnInit() on the submit page:

this.route.params.subscribe(
  (params: Params) => {
    if (params['artist'] && params['submission']) {
      this.submissionEdit(params['artist'], params['submission'])
    } 
  }
)

Once the user completes the edit, the updates are saved and the user is routed back to the submission page (thus moving away from the submit tab) with:

navigateByUrl('tabs/(home:release/${this.submission.submissionUID})')

Everything works perfectly until the user clicks the edit button on the song page again

When they do, they are routed back to that submit page url, but since the route had not changed on the submit tab, the route params subscription didn't update and could not run the this.submissionEdit() method inside the subscription thus not populating the submission form with existing data.

So my question is, after the user submits an edit, how do I reset the specific submit tab/stack back to tabs/(submit:submit) so that when the user clicks edit again, the url does change and that param subscription can update?

I am using Ionic 4 Angular. Let me know what other info you may need, thanks!

2
Hey Jordan! Were you able to solve this?ciekawy
few thoughts here: 1. this seems to be by design from ionic with no option to configure. 2. when you click on already selected tab having more than one view on the stack it is being reset to the root. The workaround could be to listen to ionTabsWillChange , inject the @ViewChild('appTabs') and do this.appTabs.select(event.tab). The only thing is that this will cause the stacked view to be shown first and animated away.ciekawy
another option is to just use a route outside of the tab to not store it onto the tab's navigation stackciekawy

2 Answers

2
votes

I think I have a temporary solution that does not seem to have any side-effects (yet).

On every tab in tabs.page.html:

<ion-tab-button tab="tab1" (click)="openTab('tab1', $event)">
    <ion-label>Tab</ion-label>
</ion-tab-button>

On tabs.page.ts:

async openTab(tab: string, evt: MouseEvent) {
    const tabSelected = this.tabs.getSelected();
    evt.stopImmediatePropagation();
    evt.preventDefault();
    return tabSelected !== tab
      ? await this.navCtrl.navigateRoot(this.tabs.outlet.tabsPrefix + '/' + tab)
      : this.tabs.select(tab);
}
0
votes

Inspired by @Leonardo solution I've modified it a bit. Haven't checked though yet with Angular 8 - I believe with the use of outlet.canGoBack() / outlet.pop() there is a chance it will work also for 8:

<ion-tabs #tabs>
    <ion-tab-button tab="tab1" (click)="handleTabClick($event)">
        <ion-label>Tab</ion-label>
    </ion-tab-button>
</ion-tabs> 
// usual @Component() goes here
class TabsPage {
    @ViewChild('tabs') tabs: IonTabs;

    resetStackTabs = ['inbox', 'tasks'];
    handleTabClick = (event: MouseEvent) => {
        const { tab } = event.composedPath().find((element: any) =>
            element.tagName === 'ION-TAB-BUTTON') as EventTarget & { tab: string };
        // without checking resetStackTabs this will work for any tab
        if (this.resetStackTabs.includes(tab) &&
            this.tabs.outlet.canGoBack(1, tab)) {
            event.stopImmediatePropagation();

            // here we may need pop depth more than one if we handle deeper nav for a tab
            return this.tabs.outlet.pop(1, tab);
        }
    }
}