소스 검색

Add ability to set disabled element values

Add options for getFormValues, setFormValues, and clearFormValues to allow managing of values for disabled elements.
master
부모
커밋
0843513772
3개의 변경된 파일66개의 추가작업 그리고 12개의 파일을 삭제
  1. +0
    -4
      README.md
  2. +32
    -0
      cypress/integration/core.test.ts
  3. +34
    -8
      src/index.ts

+ 0
- 4
README.md 파일 보기

@@ -172,8 +172,4 @@ add values to the form (such as specifying which action to take for the rest of
[usability table for `SubmitEvent.submitter`](https://caniuse.com/mdn-api_submitevent_submitter) to check if your target
browser is supported.

Setting form values of disabled elements is not supported by design, as `formxtra` is made for submittable form
elements. If a disabled element's value needs to be changed somehow, the form instance is already available, and the
element to be looked up is accessible via `HTMLFormElement.elements`.

The sources are under the [MIT license](https://code.modal.sh/TheoryOfNekomata/formxtra/raw/branch/master/LICENSE).

+ 32
- 0
cypress/integration/core.test.ts 파일 보기

@@ -336,6 +336,7 @@ describe('misc', () => {
<body>
<form>
<input type="text" name="foobar" />
<input type="text" name="disabled" disabled />
<button type="submit">Submit</button>
</form>
</body>
@@ -409,6 +410,23 @@ describe('misc', () => {
},
})
});

it('should allow setting values for disabled elements', () => {
utils.test({
querySubmitter: (cy: any) => cy.get('[type="submit"]'),
onSubmitted: (form: HTMLFormElement, submitter: any, search: any) => {
let isThrown = false;
try {
setFormValues(form, { foobar: 'baz', disabled: 'new value' }, { includeDisabled: true });
} catch (e) {
isThrown = true;
}

expect(isThrown).toBe(false);
expect(getFormValues(form, { includeDisabled: true })).toEqual({ foobar: 'baz', disabled: 'new value', });
},
})
});
});


@@ -430,6 +448,7 @@ describe('misc', () => {
<input type="radio" name="foo" value="value1" checked />
<input type="radio" name="foo" value="value2" />
<input type="radio" name="foo" value="value3" />
<input type="text" name="disabled" value="disabled" disabled />
<button type="submit">Submit</button>
</form>
</body>
@@ -455,6 +474,19 @@ describe('misc', () => {
},
});
});

it('should clear all values given disabled option', () => {
utils.test({
querySubmitter: (cy: any) => cy.get('[type="submit"]'),
onSubmitted: (form: HTMLFormElement, submitter: any, search: any) => {
clearFormValues(form, ['foobar', 'bar', 'foo', 'disabled'], { includeDisabled: true });
expect(getFormValues(form, { includeDisabled: true })).toEqual({
foobar: ['', ''], baz: 'value3', bar: ['', ''],
disabled: '',
});
},
});
});
});

describe('duplicates', () => {


+ 34
- 8
src/index.ts 파일 보기

@@ -1021,23 +1021,34 @@ const NAME_ATTRIBUTE_VALUE_ISINDEX = 'isindex' as const;
/**
* Determines if an element's value is included when its form is submitted.
* @param el - The element.
* @param includeDisabled - Should we include disabled field elements?
* @returns Value determining if the element's value is included when its form is submitted.
*/
export const isElementValueIncludedInFormSubmit = (el: HTMLElement) => {
export const isElementValueIncludedInFormSubmit = (el: HTMLElement, includeDisabled = false) => {
const namedEl = el as unknown as Record<string, unknown>;
return (
typeof namedEl[ATTRIBUTE_NAME] === 'string'
&& namedEl[ATTRIBUTE_NAME].length > 0
&& namedEl[ATTRIBUTE_NAME] !== NAME_ATTRIBUTE_VALUE_ISINDEX
&& !(ATTRIBUTE_DISABLED in namedEl && Boolean(namedEl[ATTRIBUTE_DISABLED]))
&& (includeDisabled || !(ATTRIBUTE_DISABLED in namedEl && Boolean(namedEl[ATTRIBUTE_DISABLED])))
&& isFieldElement(namedEl as unknown as HTMLElement)
);
};

/**
* Options for all form value functions.
*/
type FormValuesOptions = {
/**
* Should we include disabled field elements?
*/
includeDisabled?: true,
}

/**
* Options for getting form values.
*/
type GetFormValuesOptions = GetFieldValueOptions & {
type GetFormValuesOptions = FormValuesOptions & GetFieldValueOptions & {
/**
* The element that triggered the submission of the form.
*/
@@ -1081,9 +1092,10 @@ const assertIsFormElement = (maybeForm: unknown, context: string) => {
/**
* Filters the form elements that can be processed.
* @param form - The form element.
* @param includeDisabled - Should we include disabled field elements?
* @returns Array of key-value pairs for the field names and field elements.
*/
const filterFieldElements = (form: HTMLFormElement) => {
const filterFieldElements = (form: HTMLFormElement, includeDisabled = false) => {
const formElements = form.elements as unknown as Record<string | number, HTMLElement>;
const allFormFieldElements = Object.entries<HTMLElement>(formElements);
return allFormFieldElements.filter(([k, el]) => (
@@ -1091,7 +1103,7 @@ const filterFieldElements = (form: HTMLFormElement) => {
!Number.isNaN(Number(k))

// Only the enabled/read-only elements can be enumerated.
&& isElementValueIncludedInFormSubmit(el)
&& isElementValueIncludedInFormSubmit(el, includeDisabled)
)) as [string, HTMLElementWithName][];
};

@@ -1104,7 +1116,7 @@ const filterFieldElements = (form: HTMLFormElement) => {
export const getFormValues = (form: HTMLFormElement, options = {} as GetFormValuesOptions) => {
assertIsFormElement(form, 'getFormValues');

const fieldElements = filterFieldElements(form);
const fieldElements = filterFieldElements(form, Boolean(options.includeDisabled));
const fieldValues = fieldElements.reduce(
(theFormValues, [, el]) => {
const fieldValue = getValue(el, options);
@@ -1236,15 +1248,22 @@ const getElementsOfSameName = (fieldElementEntries: [string, HTMLElementWithName
)
);

/**
* Options for setting form values.
*/
type SetFormValuesOptions = FormValuesOptions;

/**
* Sets the values of all the fields within the form through accessing the DOM nodes. Partial values
* may be passed to set values only to certain form fields.
* @param form - The form.
* @param values - The form values.
* @param options - The options.
*/
export const setFormValues = (
form: HTMLFormElement,
values: unknown,
options = {} as SetFormValuesOptions,
) => {
assertIsFormElement(form, 'getFormValues');
const valuesType = typeof values;
@@ -1258,12 +1277,17 @@ export const setFormValues = (
}

const objectValues = normalizeValues(values);
const fieldElements = filterFieldElements(form);
const fieldElements = filterFieldElements(form, Boolean(options.includeDisabled));
const filteredFieldElements = fieldElements.filter(([, el]) => el.name in objectValues);
const elementsWithSameName = getElementsOfSameName(filteredFieldElements);
doSetFormValues(filteredFieldElements, elementsWithSameName, objectValues);
};

/**
* Options for clearing form values.
*/
type ClearFormValuesOptions = FormValuesOptions;

/**
* Clears the values of all the fields within the form through accessing the DOM nodes. Partial
* values may be passed to set values only to certain form fields.
@@ -1272,14 +1296,16 @@ export const setFormValues = (
*
* @param form - The form.
* @param fieldNames - The field names to clear their corresponding element(s).
* @param options - The options.
*/
export const clearFormValues = (
form: HTMLFormElement,
fieldNames: string | string[],
options = {} as ClearFormValuesOptions,
) => {
assertIsFormElement(form, 'clearFormValues');
const fieldNamesNormalized = Array.isArray(fieldNames) ? fieldNames : [fieldNames];
const fieldElements = filterFieldElements(form);
const fieldElements = filterFieldElements(form, Boolean(options.includeDisabled));
const filteredFieldElements = fieldElements.filter(
([, el]) => fieldNamesNormalized.includes(el.name),
);


불러오는 중...
취소
저장