Search code examples
ionic-frameworkscrollionic3modalviewcontrollergetboundingclientrect

Ionic Modal doesn't recognize element as "in view" until scroll on iOS


I have a reuseable consent form component that pops up in an ionic modal from various parts of an app that populate it with different text depending on the particular consent or agreement the client is accepting/declining (terms of service/user agreement/compliance stuff/etc.).

At the end of the text/subtext I have a div as a scroll checkpoint:

<div #scrollCheckpoint id="scrollCheck"></div>

the button to accept the agreement/consent has a [disabled]="!canAccept" property binding to make sure the user has read over the text contained in the agreement.

In my .ts file I viewchild the element:

@ViewChild('scrollCheckpoint') scrollCheckpoint: ElementRef;

and have two methods to set/unset the canAccept variable:

private onScrolled() {
    if (!this.canAccept){
        this.canAccept = this.isElementInViewport(this.scrollCheckpoint.nativeElement);
        this.cd.detectChanges();
    }       
}

and

private isElementInViewport(el: HTMLElement) {
    var bounding = el.getBoundingClientRect();
    return (
        bounding.top >= 0 &&
        bounding.left >= 0 &&
        bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
        bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
    );
};

I should also mention that I have an ionViewDidLoad method that does an initial check upon load even:

ionViewDidLoad(){
    this.canAccept = this.isElementInViewport(this.scrollCheckpoint.nativeElement);
}

This works perfectly on Android or Web and the button does not show as enabled until the user has scrolled through the text.

The problem is on iOS the user is forced to scroll (even just a few pixels) in order for the button to activate even if all of the text (as well as the scroll div) is already in view. I obviously want it to show the button as active if the text is all contained in the window already.

I know this is super petty, but just trying to get the best user experience here. Has anyone else run into this issue or know a workaround/solution?


Solution

  • I know it is probably lame to answer your own question, but maybe this might help someone else. I found that there must be a delay with iOS devices in correctly calculating the getBoundingClientRect() values so if I put the check inside of ionViewDidEnter() instead of ionViewDidLoad() it accounted enough for the delay so that I had correct initial values when checking if the button should be enabled/disabled.