diff --git a/core/src/components/checkbox/checkbox.tsx b/core/src/components/checkbox/checkbox.tsx
index 8a25b9200d5..569f31ab6ea 100644
--- a/core/src/components/checkbox/checkbox.tsx
+++ b/core/src/components/checkbox/checkbox.tsx
@@ -151,44 +151,53 @@ export class Checkbox implements ComponentInterface {
connectedCallback() {
const { el } = this;
- // Watch for class changes to update validation state.
if (Build.isBrowser && typeof MutationObserver !== 'undefined') {
- this.validationObserver = new MutationObserver(() => {
- const newIsInvalid = checkInvalidState(el);
- if (this.isInvalid !== newIsInvalid) {
- this.isInvalid = newIsInvalid;
- /**
- * Screen readers tend to announce changes
- * to `aria-describedby` when the attribute
- * is changed during a blur event for a
- * native form control.
- * However, the announcement can be spotty
- * when using a non-native form control
- * and `forceUpdate()`.
- * This is due to `forceUpdate()` internally
- * rescheduling the DOM update to a lower
- * priority queue regardless if it's called
- * inside a Promise or not, thus causing
- * the screen reader to potentially miss the
- * change.
- * By using a State variable inside a Promise,
- * it guarantees a re-render immediately at
- * a higher priority.
- */
- Promise.resolve().then(() => {
- this.hintTextId = this.getHintTextId();
- });
+ this.validationObserver = new MutationObserver((mutations) => {
+ // Watch for label content changes
+ if (mutations.some((mutation) => mutation.type === 'characterData')) {
+ this.hasLabelContent = this.el.textContent !== '';
+ }
+ // Watch for class changes to update validation state.
+ if (mutations.some((mutation) => mutation.type === 'attributes')) {
+ const newIsInvalid = checkInvalidState(el);
+ if (this.isInvalid !== newIsInvalid) {
+ this.isInvalid = newIsInvalid;
+ /**
+ * Screen readers tend to announce changes
+ * to `aria-describedby` when the attribute
+ * is changed during a blur event for a
+ * native form control.
+ * However, the announcement can be spotty
+ * when using a non-native form control
+ * and `forceUpdate()`.
+ * This is due to `forceUpdate()` internally
+ * rescheduling the DOM update to a lower
+ * priority queue regardless if it's called
+ * inside a Promise or not, thus causing
+ * the screen reader to potentially miss the
+ * change.
+ * By using a State variable inside a Promise,
+ * it guarantees a re-render immediately at
+ * a higher priority.
+ */
+ Promise.resolve().then(() => {
+ this.hintTextId = this.getHintTextId();
+ });
+ }
}
});
this.validationObserver.observe(el, {
attributes: true,
attributeFilter: ['class'],
+ characterData: true,
+ subtree: true,
});
}
// Always set initial state
this.isInvalid = checkInvalidState(el);
+ this.hasLabelContent = this.el.textContent !== '';
}
componentWillLoad() {
@@ -267,10 +276,6 @@ 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;
@@ -387,7 +392,7 @@ export class Checkbox implements ComponentInterface {
id={this.inputLabelId}
onClick={this.onDivLabelClick}
>
-