I was recently wondering why one can not change the active segment in ionic v3 by modifying the [(ngModel)] within ionScroll.subscribe(). I have my segment content stacked underneath each other. So I'm using the buttons for "anchor-scrolling" and want to make them show vise versa, when my scroll position is over a specific position. Here is my code:
<ion-segment [(ngModel)]="segData">
<ion-segment-button (click)="this.scrollToCard('card1')" value="seg1">Card1</ion-segment-button>
<ion-segment-button (click)="this.scrollToCard('card2')" value="seg2">Card2</ion-segment-button>
</ion-segment>
<div [ngSwitch]="segData">
<ion-list *ngSwitchCase="'seg1'">
<ion-item>
<ion-card #card1>...</ion-card>
</ion-item>
<ion-item>
<ion-card #card2>...</ion-card>
</ion-item>
</ion-list>
</div>
example.ts
segData: string;
export class ShowCar
{
@ViewChild(Content) content : Content;
...
constructor(...)
{
this.segData = "seg1";
}
...
ionViewDidLoad()
{
//This would work
//setTimeout( () => { this.segData = "seg2"; }
//Inside ionScroll.subscribe() it is not working
//Even if i wrap this into "setTimeout"
this.content.ionScroll.subscribe( scrollData =>
{
if( scrollData.scrollTop > seg1PosFromTop)
this.segData = "seg2";
});
}
...
}
I tried a lot of things and some crazy stuff might be going on. For example, since latest angular allows to work with elements directly from the DOM, I triggered an click-event on the element. The segment then shortly appears to be active and after a millisecond, the previous segment turned active again. Also I was playing around with just changing css classes. However when clicking on the segment-buttons I had to capture that, remove all segment-button segment-active
classes and adding it manually to the chosen one.
Okay, since nobody answered my question, I spent a lot of time trying and researching. Here we go, the solution:
Every scroll movement in an ionic app happens to be outside of angular for performance reasons. So one can not do modification of angular variables or do a content.resize()
inside of any scroll event handler (ionScroll
, ionScrollStart
, ionScrollEnd
).
So you have to wrap every code into: this.zone.run()
import { Component, NgZone } from '@angular/core';
@Component({
template: `
<ion-header>
<ion-navbar>
<ion-title></ion-title>
</ion-navbar>
</ion-header>
<ion-content (ionScroll)="scrollHandler($event)">
<p> Some realllllllly long content </p>
</ion-content>
`})
class E2EPage {
public scrollAmount = 0;
constructor( public zone: NgZone){}
scrollHandler(event) {
console.log(`ScrollEvent: ${event}`)
this.zone.run(()=>{
// since scrollAmount is data-binded,
// the update needs to happen in zone
this.scrollAmount++
})
}
}
https://ionicframework.com/docs/api/components/content/Content/#advanced