Compare commits

..

6 Commits
8.8.x ... main

Author SHA1 Message Date
OS-jacobbell
f04fa23e0d test(angular): validate checkbox and toggle in lazy template-form (#31005)
## What is the current behavior?
Checkbox and toggle components are not validated to be ticked/on in
`packages/angular/test/base/src/app/lazy/template-form`. This prevents
the error text from being displayed. While they have the `required`
attribute, this only applies to accessibility for
[checkbox](https://ionicframework.com/docs/api/checkbox#required) and
[toggle](https://ionicframework.com/docs/api/toggle#required).

## What is the new behavior?
- Use an Angular validator directive for checkbox and toggle.
- Make template-form an Angular module so the validator directive can be
imported.

## Does this introduce a breaking change?

- [ ] Yes
- [X] No
2026-03-12 19:29:07 +00:00
OS-jacobbell
ce83407e1d fix(checkbox): re-evaluate label visibility when label is updated (#30980)
## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->
Checkbox's render function applies the `label-text-wrapper-hidden` css
class when there is no label text to prevent extra margin from being
added. The render function is not re-evaluated if the label is updated.
This causes a problem in Angular where dynamic variables get applied
after the page is loaded, and a checkbox using a variable as a label
gets stuck with its label hidden until something else triggers a
re-render, e.g. ticking the box.
## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
- The checkbox will be re-rendered, and css classes will be updated,
when the label text is changed.
- Updated tests to check that the label is visible after changing from
blank to having content.
## Does this introduce a breaking change?

- [ ] Yes
- [X] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->
2026-03-12 18:51:20 +00:00
renovate[bot]
784fdc6543 chore(deps): update download + upload artifacts (major) (#30974)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[actions/download-artifact](https://redirect.github.com/actions/download-artifact)
| action | major | `v7` → `v8` |
|
[actions/upload-artifact](https://redirect.github.com/actions/upload-artifact)
| action | major | `v6` → `v7` |

---

### Release Notes

<details>
<summary>actions/download-artifact (actions/download-artifact)</summary>

###
[`v8`](https://redirect.github.com/actions/download-artifact/compare/v7...v8)

[Compare
Source](https://redirect.github.com/actions/download-artifact/compare/v7...v8)

</details>

<details>
<summary>actions/upload-artifact (actions/upload-artifact)</summary>

###
[`v7`](https://redirect.github.com/actions/upload-artifact/compare/v6...v7)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v6...v7)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4zNi4yIiwidXBkYXRlZEluVmVyIjoiNDMuMzYuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-09 16:20:18 +00:00
renovate[bot]
7dcefa2203 chore(deps): update actions/setup-node action to v6.3.0 (#30987)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/setup-node](https://redirect.github.com/actions/setup-node) |
action | minor | `v6.2.0` → `v6.3.0` |

---

### Release Notes

<details>
<summary>actions/setup-node (actions/setup-node)</summary>

###
[`v6.3.0`](https://redirect.github.com/actions/setup-node/releases/tag/v6.3.0)

[Compare
Source](https://redirect.github.com/actions/setup-node/compare/v6.2.0...v6.3.0)

##### What's Changed

##### Enhancements:

- Support parsing `devEngines` field by
[@&#8203;susnux](https://redirect.github.com/susnux) in
[#&#8203;1283](https://redirect.github.com/actions/setup-node/pull/1283)

> When using node-version-file: package.json, setup-node now
prefers devEngines.runtime over engines.node.

##### Dependency updates:

- Fix npm audit issues by
[@&#8203;gowridurgad](https://redirect.github.com/gowridurgad) in
[#&#8203;1491](https://redirect.github.com/actions/setup-node/pull/1491)
- Replace uuid with crypto.randomUUID() by
[@&#8203;trivikr](https://redirect.github.com/trivikr) in
[#&#8203;1378](https://redirect.github.com/actions/setup-node/pull/1378)
- Upgrade minimatch from 3.1.2 to 3.1.5 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[#&#8203;1498](https://redirect.github.com/actions/setup-node/pull/1498)

##### Bug fixes:

- Remove hardcoded bearer for mirror-url
[@&#8203;marco-ippolito](https://redirect.github.com/marco-ippolito) in
[#&#8203;1467](https://redirect.github.com/actions/setup-node/pull/1467)
- Scope test lockfiles by package manager and update cache tests by
[@&#8203;gowridurgad](https://redirect.github.com/gowridurgad) in
[#&#8203;1495](https://redirect.github.com/actions/setup-node/pull/1495)

##### New Contributors

- [@&#8203;susnux](https://redirect.github.com/susnux) made their first
contribution in
[#&#8203;1283](https://redirect.github.com/actions/setup-node/pull/1283)

**Full Changelog**:
<https://github.com/actions/setup-node/compare/v6...v6.3.0>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My40OC4xIiwidXBkYXRlZEluVmVyIjoiNDMuNDguMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-09 16:11:57 +00:00
renovate[bot]
623bf0e2f2 chore(deps): update dependency @capacitor/core to v8.2.0 (#30997)
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [@capacitor/core](https://capacitorjs.com)
([source](https://redirect.github.com/ionic-team/capacitor)) | [`8.1.0`
→
`8.2.0`](https://renovatebot.com/diffs/npm/@capacitor%2fcore/8.1.0/8.2.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@capacitor%2fcore/8.2.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@capacitor%2fcore/8.1.0/8.2.0?slim=true)
|

---

### Release Notes

<details>
<summary>ionic-team/capacitor (@&#8203;capacitor/core)</summary>

###
[`v8.2.0`](https://redirect.github.com/ionic-team/capacitor/blob/HEAD/CHANGELOG.md#820-2026-03-06)

[Compare
Source](https://redirect.github.com/ionic-team/capacitor/compare/8.1.0...09770f7d2dc8d566bb377f9968355090f20918b6)

##### Bug Fixes

- **android:** Add missing null checks in BridgeActivity
([#&#8203;8185](https://redirect.github.com/ionic-team/capacitor/issues/8185))
([bd29b99](bd29b9913a))
- **android:** Concurrent Range Requests for assets
([#&#8203;8357](https://redirect.github.com/ionic-team/capacitor/issues/8357))
([5e82c89](5e82c89f1b))
- **android:** handle lowercase range header
([#&#8203;8368](https://redirect.github.com/ionic-team/capacitor/issues/8368))
([ae0e2dd](ae0e2ddccb))
- **android:** invalid http range seeking
([#&#8203;8369](https://redirect.github.com/ionic-team/capacitor/issues/8369))
([3109d22](3109d22547))
- **cli:** Allow to run update on non macOS
([#&#8203;8344](https://redirect.github.com/ionic-team/capacitor/issues/8344))
([a441280](a441280d7c))
- **cli:** Don't overwrite config.server section with `--live-reload`
([#&#8203;7528](https://redirect.github.com/ionic-team/capacitor/issues/7528))
([782b9d9](782b9d9c26))
- **cli:** use 8.0.0 as default Capacitor SPM dependency version
([#&#8203;8341](https://redirect.github.com/ionic-team/capacitor/issues/8341))
([a55dc5e](a55dc5ee4d))
- **docs:** fix typo in CapApp-SPM README
([#&#8203;8348](https://redirect.github.com/ionic-team/capacitor/issues/8348))
([7d001ac](7d001ac4c5))
- **ios:** remove tmpWindow usages on presentVC/dismissVC
([#&#8203;8338](https://redirect.github.com/ionic-team/capacitor/issues/8338))
([fc9647f](fc9647f26f))

##### Features

- **cli:** Add --https option for --live-reload
([#&#8203;8194](https://redirect.github.com/ionic-team/capacitor/issues/8194))
([5db81e6](5db81e68c6))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My41Ni4wIiwidXBkYXRlZEluVmVyIjoiNDMuNTYuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-09 15:58:55 +00:00
Brandy Smith
5862405e9e merge release-8.8.1 (#30998)
v8.8.1
2026-03-06 13:04:17 -05:00
31 changed files with 132 additions and 38 deletions

View File

@@ -22,7 +22,7 @@ runs:
using: 'composite'
steps:
- name: 🟢 Configure Node for Publish
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: ${{ inputs.node-version }}
registry-url: 'https://registry.npmjs.org'

View File

@@ -3,7 +3,7 @@ description: 'Build Ionic Angular Server'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive

View File

@@ -9,7 +9,7 @@ runs:
using: 'composite'
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 24.x

View File

@@ -9,7 +9,7 @@ runs:
using: 'composite'
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 24.x
- name: 🕸️ Install Dependencies

View File

@@ -3,7 +3,7 @@ description: 'Build Ionic React Router'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive

View File

@@ -3,7 +3,7 @@ description: 'Build Ionic React'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive

View File

@@ -3,7 +3,7 @@ description: 'Builds Ionic Vue Router'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive

View File

@@ -3,7 +3,7 @@ description: 'Build Ionic Vue'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive

View File

@@ -10,7 +10,7 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v8
with:
name: ${{ inputs.name }}
path: ${{ inputs.path }}

View File

@@ -6,7 +6,7 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive

View File

@@ -3,7 +3,7 @@ description: 'Test Core Clean Build'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 24.x

View File

@@ -3,7 +3,7 @@ description: 'Test Core Lint'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 24.x
- name: 🕸️ Install Dependencies

View File

@@ -13,7 +13,7 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
@@ -66,7 +66,7 @@ runs:
working-directory: ./core
- name: 📦 Archive Updated Screenshots
if: inputs.update == 'true' && steps.test-and-update.outputs.hasUpdatedScreenshots == 'true'
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: updated-screenshots-${{ inputs.shard }}-${{ inputs.totalShards }}
path: UpdatedScreenshots-${{ inputs.shard }}-${{ inputs.totalShards }}.zip

View File

@@ -6,7 +6,7 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 24.x
- name: 🕸️ Install Dependencies

View File

@@ -6,7 +6,7 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive

View File

@@ -6,7 +6,7 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive

View File

@@ -6,7 +6,7 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive

View File

@@ -7,10 +7,10 @@ on:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: 24.x
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v8
with:
path: ./artifacts
- name: 🔎 Extract Archives

View File

@@ -13,7 +13,7 @@ runs:
- name: 🗄️ Create Archive
run: zip -q -r ${{ inputs.output }} ${{ inputs.paths }}
shell: bash
- uses: actions/upload-artifact@v6
- uses: actions/upload-artifact@v7
with:
name: ${{ inputs.name }}
path: ${{ inputs.output }}

View File

@@ -627,9 +627,9 @@
"license": "MIT"
},
"node_modules/@capacitor/core": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-8.1.0.tgz",
"integrity": "sha512-UfMBMWc1v7J+14AhH03QmeNwV3HZx3qnOWhpwnHfzALEwAwlV/itQOQqcasMQYhOHWL0tiymc5ByaLTn7KKQxw==",
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-8.2.0.tgz",
"integrity": "sha512-oKaoNeNtH2iIZMDFVrb1atoyRECDGHcfLMunJ5KWN8DtvpVBeeA4c41e20NTuhMxw1cSYbpq2PV2hb+/9CJxlQ==",
"dev": true,
"license": "MIT",
"dependencies": {

View File

@@ -127,6 +127,8 @@ export class Checkbox implements ComponentInterface {
*/
@State() isInvalid = false;
@State() private hasLabelContent = false;
@State() private hintTextId?: string;
/**
@@ -265,6 +267,10 @@ export class Checkbox implements ComponentInterface {
ev.stopPropagation();
};
private onSlotChange = () => {
this.hasLabelContent = this.el.textContent !== '';
};
private getHintTextId(): string | undefined {
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
@@ -326,7 +332,6 @@ export class Checkbox implements ComponentInterface {
} = this;
const mode = getIonMode(this);
const path = getSVGPath(mode, indeterminate);
const hasLabelContent = el.textContent !== '';
renderHiddenInput(true, el, name, checked ? value : '', disabled);
@@ -338,7 +343,7 @@ export class Checkbox implements ComponentInterface {
aria-checked={indeterminate ? 'mixed' : `${checked}`}
aria-describedby={this.hintTextId}
aria-invalid={this.isInvalid ? 'true' : undefined}
aria-labelledby={hasLabelContent ? this.inputLabelId : null}
aria-labelledby={this.hasLabelContent ? this.inputLabelId : null}
aria-label={inheritedAttributes['aria-label'] || null}
aria-disabled={disabled ? 'true' : null}
aria-required={required ? 'true' : undefined}
@@ -376,13 +381,13 @@ export class Checkbox implements ComponentInterface {
<div
class={{
'label-text-wrapper': true,
'label-text-wrapper-hidden': !hasLabelContent,
'label-text-wrapper-hidden': !this.hasLabelContent,
}}
part="label"
id={this.inputLabelId}
onClick={this.onDivLabelClick}
>
<slot></slot>
<slot onSlotchange={this.onSlotChange}></slot>
{this.renderHintText()}
</div>
<div class="native-wrapper">

View File

@@ -8,13 +8,19 @@ test.describe('Value Accessors', () => {
test('should update the form value', async ({ page }) => {
await expect(page.locator('#formValue')).toHaveText(JSON.stringify({ checkbox: false }, null, 2));
await expect(page.locator('ion-checkbox')).toHaveClass(/ion-pristine/);
await expect(page.getByRole('checkbox', { name: 'Static Checkbox Label' })).toHaveClass(/ion-pristine/);
await page.locator('ion-checkbox').click();
await page.getByRole('checkbox', { name: 'Static Checkbox Label' }).click();
await expect(page.locator('#formValue')).toHaveText(JSON.stringify({ checkbox: true }, null, 2));
await expect(page.locator('ion-checkbox')).toHaveClass(/ion-dirty/);
await expect(page.locator('ion-checkbox')).toHaveClass(/ion-valid/);
await expect(page.getByRole('checkbox', { name: 'Static Checkbox Label' })).toHaveClass(/ion-dirty/);
await expect(page.getByRole('checkbox', { name: 'Static Checkbox Label' })).toHaveClass(/ion-valid/);
await expect(page.getByRole('checkbox', { name: 'Static Checkbox Label' })).toBeVisible();
});
test('should display dynamically set label', async ({ page }) => {
await expect(page.getByRole('checkbox', { name: 'Dynamic Checkbox Label' })).toBeVisible();
});
});

View File

@@ -28,7 +28,6 @@ import { AlertComponent } from '../alert/alert.component';
import { AccordionComponent } from '../accordion/accordion.component';
import { AccordionModalComponent } from '../accordion/accordion-modal/accordion-modal.component';
import { TabsBasicComponent } from '../tabs-basic/tabs-basic.component';
import { TemplateFormComponent } from '../template-form/template-form.component';
@NgModule({
declarations: [
@@ -54,8 +53,7 @@ import { TemplateFormComponent } from '../template-form/template-form.component'
AlertComponent,
AccordionComponent,
AccordionModalComponent,
TabsBasicComponent,
TemplateFormComponent
TabsBasicComponent
],
imports: [
CommonModule,

View File

@@ -19,7 +19,6 @@ import { NavigationPage3Component } from '../navigation-page3/navigation-page3.c
import { AlertComponent } from '../alert/alert.component';
import { AccordionComponent } from '../accordion/accordion.component';
import { TabsBasicComponent } from '../tabs-basic/tabs-basic.component';
import { TemplateFormComponent } from '../template-form/template-form.component';
export const routes: Routes = [
{
@@ -34,7 +33,7 @@ export const routes: Routes = [
{ path: 'textarea', loadChildren: () => import('../textarea/textarea.module').then(m => m.TextareaModule) },
{ path: 'searchbar', loadChildren: () => import('../searchbar/searchbar.module').then(m => m.SearchbarModule) },
{ path: 'form', component: FormComponent },
{ path: 'template-form', component: TemplateFormComponent },
{ path: 'template-form', loadChildren: () => import('../template-form/template-form.module').then(m => m.TemplateFormModule) },
{ path: 'modals', component: ModalComponent },
{ path: 'modal-inline', loadChildren: () => import('../modal-inline').then(m => m.ModalInlineModule) },
{ path: 'modal-sheet-inline', loadChildren: () => import('../modal-sheet-inline').then(m => m.ModalSheetInlineModule) },

View File

@@ -0,0 +1,16 @@
import { NgModule } from "@angular/core";
import { RouterModule } from "@angular/router";
import { TemplateFormComponent } from "./template-form.component";
@NgModule({
imports: [
RouterModule.forChild([
{
path: '',
component: TemplateFormComponent
}
])
],
exports: [RouterModule]
})
export class TemplateFormRoutingModule { }

View File

@@ -109,6 +109,7 @@
[(ngModel)]="checkboxValue"
name="checkboxField"
required
requireTrue
#checkboxField="ngModel"
id="template-checkbox-test"
helper-text="You must agree to continue"
@@ -133,6 +134,7 @@
[(ngModel)]="toggleValue"
name="toggleField"
required
requireTrue
#toggleField="ngModel"
id="template-toggle-test"
helper-text="You must turn on to continue"

View File

@@ -0,0 +1,23 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { IonicModule } from "@ionic/angular";
import { TemplateFormRoutingModule } from "./template-form-routing.module";
import { TemplateFormComponent } from "./template-form.component";
import { ValidatorsModule } from "../validators/validators.module";
@NgModule({
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
IonicModule,
TemplateFormRoutingModule,
ValidatorsModule
],
declarations: [
TemplateFormComponent
]
})
export class TemplateFormModule { }

View File

@@ -0,0 +1,19 @@
import { Directive, forwardRef } from '@angular/core';
import { NG_VALIDATORS, Validator, AbstractControl, ValidationErrors, Validators } from '@angular/forms';
@Directive({
selector: '[requireTrue]',
providers: [
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => RequireTrueValidatorDirective),
multi: true,
},
],
standalone: false,
})
export class RequireTrueValidatorDirective implements Validator {
validate(control: AbstractControl): ValidationErrors | null {
return Validators.requiredTrue(control);
}
}

View File

@@ -0,0 +1,20 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { RequireTrueValidatorDirective } from "./require-true.directive";
@NgModule({
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule
],
declarations: [
RequireTrueValidatorDirective
],
exports: [
RequireTrueValidatorDirective
]
})
export class ValidatorsModule { }

View File

@@ -6,6 +6,7 @@
</p>
<app-value-accessor-test [formGroup]="form">
<ion-checkbox formControlName="checkbox">Checkbox</ion-checkbox>
<ion-checkbox formControlName="checkbox">Static Checkbox Label</ion-checkbox>
</app-value-accessor-test>
<ion-checkbox>{{dynamicLabel}}</ion-checkbox>
</div>

View File

@@ -15,6 +15,11 @@ import { ValueAccessorTestComponent } from "../value-accessor-test/value-accesso
]
})
export class CheckboxComponent {
dynamicLabel = '';
ngAfterViewInit(): void {
this.dynamicLabel = 'Dynamic Checkbox Label';
}
form = this.fb.group({
checkbox: [false, Validators.required],