Skip to content

Commit 1d7c716

Browse files
feat: add error messages
1 parent 0a25787 commit 1d7c716

File tree

7 files changed

+159
-90
lines changed

7 files changed

+159
-90
lines changed

Diff for: package-lock.json

+102-55
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: src/element-internals.ts

+34-18
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
11
import {
2-
refMap,
3-
validityMap,
42
internalsMap,
5-
validationMessageMap,
6-
shadowHostsMap,
7-
formElementsMap,
3+
refMap,
84
refValueMap,
9-
hiddenInputMap,
5+
shadowHostsMap,
106
shadowRootMap,
11-
validationAnchorMap
7+
validationAnchorMap,
8+
validityMap,
9+
validationMessageMap
1210
} from './maps';
11+
import {
12+
createHiddenInput,
13+
findParentForm,
14+
getHostRoot,
15+
initForm,
16+
initLabels,
17+
initRef,
18+
removeHiddenInputs,
19+
throwIfNotFormAssociated
20+
} from './utils';
1321
import { initAom } from './aom';
14-
import { getHostRoot, initRef, initLabels, initForm, findParentForm, createHiddenInput, removeHiddenInputs } from './utils';
1522
import { ValidityState, reconcileValidty, setValid } from './ValidityState';
1623
import { observerCallback, observerConfig } from './mutation-observers';
1724
import { IElementInternals, ICustomElement, LabelsList } from './types';
@@ -66,21 +73,24 @@ export class ElementInternals implements IElementInternals {
6673
refMap.set(this, ref);
6774
validityMap.set(this, validity);
6875
internalsMap.set(ref, this);
69-
const { labels, form } = this;
7076
initAom(ref, this);
77+
initRef(ref, this);
7178
Object.seal(this);
7279

73-
initRef(ref, this);
74-
initLabels(ref, labels);
75-
initForm(ref, form, this);
80+
if (ref.constructor['formAssociated']) {
81+
const { labels, form } = this;
82+
initLabels(ref, labels);
83+
initForm(ref, form, this);
84+
}
7685
}
7786

7887
/**
7988
* Will return true if the element is in a valid state
8089
*/
8190
checkValidity(): boolean {
82-
const validity = validityMap.get(this);
8391
const ref = refMap.get(this);
92+
throwIfNotFormAssociated(ref, `Failed to execute 'checkValidity' on 'ElementInternals': The target element is not a form-associated custom element.`);
93+
const validity = validityMap.get(this);
8494
if (!validity.valid) {
8595
const validityEvent = new Event('invalid', {
8696
bubbles: false,
@@ -95,6 +105,7 @@ export class ElementInternals implements IElementInternals {
95105
/** The form element the custom element is associated with */
96106
get form(): HTMLFormElement {
97107
const ref = refMap.get(this);
108+
throwIfNotFormAssociated(ref, `Failed to read the 'form' property from 'ElementInternals': The target element is not a form-associated custom element.`);
98109
let form;
99110
if (ref.constructor['formAssociated'] === true) {
100111
form = findParentForm(ref);
@@ -105,6 +116,7 @@ export class ElementInternals implements IElementInternals {
105116
/** A list of all relative form labels for this element */
106117
get labels(): LabelsList {
107118
const ref = refMap.get(this);
119+
throwIfNotFormAssociated(ref, `Failed to read the 'labels' property from 'ElementInternals': The target element is not a form-associated custom element.`);
108120
const id = ref.getAttribute('id');
109121
const hostRoot = getHostRoot(ref);
110122
if (hostRoot && id) {
@@ -115,9 +127,10 @@ export class ElementInternals implements IElementInternals {
115127

116128
/** Will report the elements validity state */
117129
reportValidity(): boolean {
130+
const ref = refMap.get(this);
131+
throwIfNotFormAssociated(ref, `Failed to execute 'reportValidity' on 'ElementInternals': The target element is not a form-associated custom element.`);
118132
const valid = this.checkValidity();
119133
const anchor = validationAnchorMap.get(this);
120-
const ref = refMap.get(this);
121134
if (anchor && !ref.constructor['formAssociated']) {
122135
throw new DOMException(`Failed to execute 'setValidity' on 'ElementInternals': The target element is not a form-associated custom element.`);
123136
}
@@ -131,9 +144,7 @@ export class ElementInternals implements IElementInternals {
131144
/** Sets the element's value within the form */
132145
setFormValue(value: string | FormData): void {
133146
const ref = refMap.get(this);
134-
if (!this.form || !ref.constructor['formAssociated']) {
135-
return undefined;
136-
}
147+
throwIfNotFormAssociated(ref, `Failed to execute 'setFormValue' on 'ElementInternals': The target element is not a form-associated custom element.`);
137148
removeHiddenInputs(this);
138149
if (value != null && !(value instanceof FormData)) {
139150
if (ref.getAttribute('name')) {
@@ -161,6 +172,7 @@ export class ElementInternals implements IElementInternals {
161172
*/
162173
setValidity(validityChanges: Partial<globalThis.ValidityState>, validationMessage?: string, anchor?: HTMLElement) {
163174
const ref = refMap.get(this);
175+
throwIfNotFormAssociated(ref, `Failed to execute 'setValidity' on 'ElementInternals': The target element is not a form-associated custom element.`);
164176
if (!validityChanges) {
165177
throw new TypeError('Failed to execute \'setValidity\' on \'ElementInternals\': 1 argument required, but only 0 present.');
166178
}
@@ -191,19 +203,23 @@ export class ElementInternals implements IElementInternals {
191203

192204
/** The element's validation message set during a call to ElementInternals.setValidity */
193205
get validationMessage(): string {
206+
const ref = refMap.get(this);
207+
throwIfNotFormAssociated(ref, `Failed to read the 'validationMessage' property from 'ElementInternals': The target element is not a form-associated custom element.`);
194208
return validationMessageMap.get(this);
195209
}
196210

197211
/** The current validity state of the object */
198212
get validity(): globalThis.ValidityState {
213+
const ref = refMap.get(this);
214+
throwIfNotFormAssociated(ref, `Failed to read the 'validity' property from 'ElementInternals': The target element is not a form-associated custom element.`);
199215
const validity = validityMap.get(this);
200216
return validity;
201217
}
202218

203219
/** If true the element will participate in a form's constraint validation. */
204220
get willValidate(): boolean {
205221
const ref = refMap.get(this);
206-
222+
throwIfNotFormAssociated(ref, `Failed to read the 'willValidate' property from 'ElementInternals': The target element is not a form-associated custom element.`);
207223
if (ref.disabled || ref.hasAttribute('disabled')) {
208224
return false;
209225
}

Diff for: src/mutation-observers.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export function observerCallback(mutationList) {
1111

1212
added.forEach(node => {
1313
/** Allows for dynamic addition of elements to forms */
14-
if (internalsMap.has(node)) {
14+
if (internalsMap.has(node) && node.constructor['formAssociated']) {
1515
const internals = internalsMap.get(node);
1616
const { form } = internals;
1717

0 commit comments

Comments
 (0)