ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
50.92k stars 13.52k forks source link

feat: scroll to top of view when pressing tab button #22558

Open DwieDima opened 3 years ago

DwieDima commented 3 years ago

Feature Request

Ionic version:

[x] 5.x

Describe the Feature Request

Many applications scroll to top, when content inside tab page is scrolled and active tab button is pressed again (e.g. YouTube). It would be great, if ionic could provide this feature out of the box.

RPReplay_Final1606233680

Describe Preferred Solution

Ionic already has a global config option statusTap: boolean, which enables scrollTop() when status bar is pressed. Extend global configs by tabTap: boolean, to provide this functionality also to tab button.

Describe Alternatives

currently you have to code this by your own.

ionitron-bot[bot] commented 3 years ago

This issue has been labeled as help wanted. This label is added to issues that we believe would be good for contributors.

If you'd like to work on this issue, please comment here letting us know that you would like to submit a pull request for it. This helps us to keep track of the pull request and make sure there isn't duplicated effort.

For a guide on how to create a pull request and test this project locally to see your changes, see our contributing documentation.

Thank you!

DwieDima commented 2 years ago

Currently i'm using some custom implementation on ionic angular. If you paste this snippet inside tabs.page.ts scrolling to top of view by pressing tab button will work.

  @ViewChild(IonTabs, { static: true }) private ionTabs: IonTabs;
  ...
  public ionViewDidEnter(): void {
    const tabs = document.querySelectorAll('ion-tab-button');
    tabs.forEach(tab => {
      tab.addEventListener('click', () => {
        const selectedTab = this.ionTabs.outlet.getActiveStackId();
        const tabPage = this.ionTabs.outlet.getRootView(selectedTab);
        const ionContent = tabPage.element.querySelector('ion-content');
        ionContent?.scrollToTop(450).catch(() => {});
      });
    });
  }

This won't work for custom scroll-content (virtual-scroll).

@liamdebeasi can this approach be refactored to IonicConfig or isn't it generally valid for all frameworks?

Update

Heres some alternative reactive angular approach:

  @ViewChild(IonTabs, { static: true }) private ionTabs: IonTabs;
  private _destroy$: Subject<void> = new Subject<void>();

  public constructor(private router: Router) {}

  public ionViewDidEnter(): void {
    let isFirstNavigation = true;
    const tabs = document.querySelectorAll('ion-tab-button');
    of(true)
      .pipe(
        switchMap(() => (isFirstNavigation ? of(true) : this.router.events)), 
        filter(event => event instanceof NavigationEnd || isFirstNavigation),
        switchMap(() => fromEvent(tabs, 'click')),
        map(() => {
          const stackId = this.ionTabs.outlet.getActiveStackId();
          const tab = this.ionTabs.outlet.getRootView(stackId);
          return tab.element.querySelector('ion-content');
        }),
        filter(ionContent => !!ionContent),
        tap(ionContent => from(ionContent.scrollToTop(450))),
        tap(() => (isFirstNavigation = false)),
        takeUntil(this._destroy$),
      )
      .subscribe();
  }

  public ngOnDestroy(): void {
    this._destroy$.next();
    this._destroy$.complete();
  }
sean-perkins commented 1 year ago

Hello everyone 👋 I looked into the development work here to support this feature and realized that "help wanted" is not appropriate. There are added complexities in each framework to verify the user is at the root of the activated tab stack, before attempting to scroll the content. As such, I've removed the "help wanted" label as the framework team should ultimately handle this feature work.

Thanks!