ionic-framework: bug: v7, cannot pass dynamic label to form controls

Prerequisites

Ionic Framework Version

v7.x

Current Behavior

Upgraded to IONIC 7 RC a couple of day ago. I got all of the warnings about the ion label being deprected and needing to replace with label=“something” labelPlacement=“stacked” etc…

I have a reusable component in which i am passing the label via attribute like so: <app-frequency-select controlName="medfrequency" label="When will this be taken?" [required]="true"></app-frequency-select>

Inside the component you see i’m trying to pass an input to customize the value of the select. HTML:

<ion-item>
  <ion-select
    required
    [label]="label"
    labelPlacement="stacked"
    #frequencySelect
    [formControlName]="controlName"
    placeholder="Please Select"
  >
    <ion-select-option [value]="f.frequencyid" *ngFor="let f of frequencies">{{ f.frequency }}</ion-select-option>
  </ion-select>
</ion-item>

component.ts:

@Component({
  selector: 'app-frequency-select',
  standalone: true,
  templateUrl: './frequency-select.component.html',
  styleUrls: ['./frequency-select.component.scss'],
  imports: [CommonModule, IonicModule, FormsModule, ReactiveFormsModule, RequiredDirective, SelectLabelFixDirective],
  viewProviders: [
    {
      provide: ControlContainer,
      useFactory: (container: ControlContainer) => container,
      deps: [[new SkipSelf(), ControlContainer]]
    }
  ]
})
export class FrequencySelectComponent {
  @ViewChild('frequencySelect') fs: IonSelect;
  @Input() label: string;
  @Input() required: boolean = false;
  @Input() controlName: string;
  frequencies: any[] = [];
  disabled: boolean;

  constructor(private _referenceService: ReferenceService) {}

  async ngOnInit() {
    await this.buildReferences();
    console.log('The label for FS:', this.label); //this is coming through just fine..
  }
  async buildReferences() {
    const t = setTimeout(async () => {
      this.frequencies = await lastValueFrom(this._referenceService.getFrequencies());
      clearTimeout(t);
    }, 1000);
  }
}

As you can see in my comment the label comes through just fine but when i try to render it into [label]=“label” it does not work. No label gets rendered.

I am forced for the time being to put static text like label=“something” which works.

Expected Behavior

I should be able to pass a string to the label in my reusable component and the [label] attribute render the text that I have sent as an @Input() label;

Steps to Reproduce

Create and input and try passing dynamic text to the label with brackets like so <ion-input [label]="somevariableforlabel"></ion-input>

in the component file:

public somevariableforlabel = 'My label';

Code Reproduction URL

No response

Ionic Info

Ionic:

Ionic CLI : 7.0.0 (/Users/abcd/.nvm/versions/node/v16.18.0/lib/node_modules/@ionic/cli) Ionic Framework : not installed @angular-devkit/build-angular : 15.2.4 @angular-devkit/schematics : 15.2.4 @angular/cli : 15.2.4 @ionic/angular-toolkit : 6.1.0

Capacitor:

Capacitor CLI : 4.6.1 @capacitor/android : 4.6.1 @capacitor/core : 4.6.1 @capacitor/ios : 4.6.1

Utility:

cordova-res : 0.15.4 native-run (update available: 1.7.2) : 1.7.1

System:

NodeJS : v16.18.0 (/Users/abcd/.nvm/versions/node/v16.18.0/bin/node) npm : 9.6.2 OS : macOS Unknown

Additional Information

Let me know if you need anymore information. Thank you.

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 15
  • Comments: 15 (4 by maintainers)

Commits related to this issue

Most upvoted comments

Thank you!

Here is the latest/most up-to-date dev-build:

7.0.2-dev.11681157690.1060bc7f

I still need to get a team review, but the end result changes here is that we are trying to default to the modern syntax instead of the legacy syntax.

Developers can still get the legacy UI by either doing:

<ion-item>
  <ion-label>Label</ion-label>
  <ion-input></ion-input>
</ion-item>

or by assigning the legacy="true" property on the control directly:

<ion-item>
  <ion-input legacy="true"></ion-input>
</ion-item>

Implementations that are similar to:

<ion-item>
  <ion-input></ion-input>
</ion-item>

will be force updated to the modern syntax. It is the only discovered way that I can maintain the modern syntax in a scenario where a label is initially unset, but later has a value (translations, shared components, etc.)

The fix for this issue is queued to be merged and will be available in this week’s release v7.0.3. Thank you everyone for reporting the issue + helping validate the fix 🎉

I would add that I have noticed this behavior with any Ionic component that I’ve tried to set a dynamic label on, and not just <ion-input>. All of our labels are run through an i18n package, so dynamic labels are non-negotiable for us.

I can confirm it fixes the problem for me 🚀

I made a reproduction repository which demonstrates the bug when using transloco to translate input labels inside a modal: https://github.com/Julien-Marcou/ionic-issue-27085

The first time the modal opens:

Screenshot 2023-04-10 at 18-32-58 Ionic App

And the second time the modal opens:

Screenshot 2023-04-10 at 18-33-08 Ionic App

@ceotrammell your ionic info says you have 7.0.2 installed. Make sure to install 7.0.3 correctly than it should work!

Also noticed that the shadow-root changes on navigation/re-hydration. Our label just prints fine but when navigating its gone. And we do not use the [legacy]="true" attr.

SCR-20230404-kfxn SCR-20230404-kfyy