fix(many): dynamic label support for modern form controls (#27156)

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Developers that are using Ionic v7 are experiencing an issue where
implementations that are intended to use the modern control syntax will
render with the legacy syntax and a warning will be displayed.

The issue is most easily reproduced by not assigning a label to the
control and then asynchronously assigning a label after a duration.

Angular example:
```html
<ion-item>
  <ion-input [label]="label"></ion-input>
</ion-item>
```

```ts
@Component({ ... })
export class MyComponent {
  @Input() label?: string; // initially unset

  ngOnInit() {
    setTimeout(() => this.label = 'Hello world', 500);
  }
}
```

<!-- Issues are required for both bug fixes and features. -->
Issue URL: resolves #27085


## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Form controls that do not have a decorative label or
`aria-label`/`aria-labelledby` assigned, will default render as modern
controls.
- Legacy form implementations that render an `<ion-label>` within the
item, will continue to render with the legacy template and a warning
will be displayed in the console.
- Modern form syntax supports dynamically set labels

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->

Legacy implementations that do not have a decorative label and do not
specify `aria-label` on the control, will be upgraded to the modern
syntax.

For example:
```html
<ion-item>
  <ion-input></ion-input>
</ion-item>
```

Developers that do not want to update to the modern syntax yet should
add the `legacy="true"` attribute to their form control.

## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

Dev-build: `7.0.2-dev.11681157690.1060bc7f`

When migrating the range tests to modern syntax, I observed a visual
clipping issue. This is being addressed in:
https://github.com/ionic-team/ionic-framework/pull/27188. This PR simply
adds the legacy flag so that screenshots are the same as `main`.
This commit is contained in:
Sean Perkins
2023-04-17 16:30:19 -04:00
committed by GitHub
parent 6ffbdbb3b2
commit 30b548b167
7 changed files with 38 additions and 11 deletions

View File

@@ -36,4 +36,27 @@ test.describe('input: item', () => {
const list = page.locator('ion-list');
expect(await list.screenshot()).toMatchSnapshot(`input-inset-list-no-fill-${page.getSnapshotSettings()}.png`);
});
test('input renders as modern when label is set asynchronously', async ({ page }, testInfo) => {
testInfo.annotations.push({
type: 'issue',
description: 'https://github.com/ionic-team/ionic-framework/issues/27085',
});
await page.setContent(
`<ion-item>
<ion-input></ion-input>
</ion-item>
`
);
const input = page.locator('ion-input');
// Initial template should be modern
await expect(input).not.toHaveClass(/legacy-input/);
// Update the input label
await input.evaluate((el: HTMLIonInputElement) => (el.label = 'New label'));
await page.waitForChanges();
// Template should still be modern
await expect(input).not.toHaveClass(/legacy-input/);
});
});