Reputation: 135
I'm building an hybrid app using Ionic3+Angular, and I'm stuck on this:
I have a form separated in segments (A and B), like this:
<form [formGroup]="testForm">
<ion-segment formControlName="segmentTest" [(ngModel)]="segmentTest">
<ion-segment-button value="A">
Segment A
</ion-segment-button>
<ion-segment-button value="B">
Segment B
</ion-segment-button>
</ion-segment>
<div [ngSwitch]="segmentTest">
<ion-list *ngSwitchCase="'A'">
<ion-item>
<ion-label floating>Input A</ion-label>
<ion-input type="number"></ion-input>
</ion-item>
</ion-list>
<ion-list *ngSwitchCase="'B'">
<ion-item>
<ion-label floating>Input B</ion-label>
<ion-input type="number"></ion-input>
</ion-item>
</ion-list>
</div>
</form>
The problem is: when I insert some data in the Input A (Segment A) and then I change to Segment B, when I return to Segment A its input's data is lost/blank.
What should I do to fix it? Is there another component I could use to get the same results as Segment?
Upvotes: 2
Views: 1991
Reputation: 31833
The problem is that structural directives like *ngSwitch
and *ngFor
add and remove the components under their purview. When a component is removed, any data they hold in their bindings is going to be removed as well. When the element is added back to the Dom because the switch case matches again, the component is instantiated again, the old component having long been discarded.
Therefore, to toggle these sections, you need to conditionally show and hide the elements instead of using structural directives.
Here is an example:
<ion-list [hidden]="segmentTest !== 'B'">
<ion-item>
<ion-label floating>Input A</ion-label>
<ion-input type="number"></ion-input>
</ion-item>
</ion-list>
<ion-list [hidden]="segmentTest !== 'A'">
<ion-item>
<ion-label floating>Input B</ion-label>
<ion-input type="number"></ion-input>
</ion-item>
</ion-list>
This will work but I don't like it because we need to negate all the conditions, which might be more complicated and it's just not as clear to read. So let's create are own it directive.
import {Directive, ElementRef, Input} from '@angular/core';
@Directive({selector: '[showWhen]'}) export default class {
constructor(elementRef: ElementRef) {
this.ref = elementRef;
}
@Input() set showWhen(value) {
this.ref.nativeElement.hidden = !value;
}
get showWhen() {
return !this.ref.nativeElement.hidden;
}
// intentional framework stupid weak typing defeated.
ref: {nativeElement: Element};
}
Then we could write
<ion-list [showWhen]="segmentTest === 'A'">
<ion-item>
<ion-label floating>Input A</ion-label>
<ion-input type="number"></ion-input>
</ion-item>
</ion-list>
Upvotes: 1