Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/source/about/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@ Unreleased

**Removed**

- :pull:`840` - remove ``IDOM_FEATURE_INDEX_AS_DEFAULT_KEY`` option
- :pull:`840` - Remove ``IDOM_FEATURE_INDEX_AS_DEFAULT_KEY`` option
- :pull:`835` - ``serve_static_files`` option from backend configuration

**Added**

- :pull:`835` - ability to customize the ``<head>`` element of IDOM's built-in client.
- :pull:`835` - Ability to customize the ``<head>`` element of IDOM's built-in client.
- :pull:`835` - ``vdom_to_html`` utility function.
- :pull:`843` - Ability to subscribe to changes that are made to mutable options.
- :pull:`699` - Support for form element serialization

**Fixed**

Expand Down
30 changes: 30 additions & 0 deletions src/client/packages/idom-client-react/src/event-to-object.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ const elementTransformCategories = {
return {};
}
},
hasElements: (element) => {
const { elements } = element;
const indices = [...Array(elements.length).keys()];
return {
elements: indices.map((index) => serializeDomElement(elements[index])),
};
},
hasName: (element) => {
const { name } = element;
// In some edge cases, "name" may not be a string. For example, in the case of
// `<form><input name="name"></form>`, the "name" attribute of the `<form>` will
// be the `<input>` element.
return typeof name === "string" ? { name } : {};
},
};

function defaultElementTransform(element) {
Expand All @@ -69,6 +83,22 @@ const elementTagCategories = {
],
hasCurrentTime: ["AUDIO", "VIDEO"],
hasFiles: ["INPUT"],
hasElements: ["FORM"],
hasName: [
"BUTTON",
"FORM",
"FIELDSET",
"IFRAME",
"INPUT",
"KEYGEN",
"OBJECT",
"OUTPUT",
"SELECT",
"TEXTAREA",
"MAP",
"META",
"PARAM",
],
};

const elementTransforms = {};
Expand Down
79 changes: 51 additions & 28 deletions src/client/packages/idom-client-react/tests/event-to-object.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,40 @@ import * as assert from "uvu/assert";
import { serializeEvent } from "../src/event-to-object.js";
import "./tooling/setup.js";

function assertEqualSerializedEventData(eventData, expectedSerializedData) {
const mockBoundingRect = {
left: 0,
top: 0,
right: 0,
bottom: 0,
x: 0,
y: 0,
width: 0,
};
const mockBoundingRect = {
left: 0,
top: 0,
right: 0,
bottom: 0,
x: 0,
y: 0,
width: 0,
};

const mockElement = {
tagName: null,
getBoundingClientRect: () => mockBoundingRect,
};
const mockElement = {
tagName: null,
getBoundingClientRect: () => mockBoundingRect,
};

const allTargetData = {
files: [
{
lastModified: 0,
name: "something",
type: "some-type",
size: 0,
},
],
value: "something",
currentTime: 35,
tagName: null, // overwritten in tests
elements: [
{ ...mockElement, tagName: "INPUT", value: "first" },
{ ...mockElement, tagName: "INPUT", value: "second" },
],
};

function assertEqualSerializedEventData(eventData, expectedSerializedData) {
const commonEventData = {
target: mockElement,
currentTarget: mockElement,
Expand All @@ -38,20 +56,6 @@ function assertEqualSerializedEventData(eventData, expectedSerializedData) {
);
}

const allTargetData = {
files: [
{
lastModified: 0,
name: "something",
type: "some-type",
size: 0,
},
],
value: "something",
currentTime: 35,
tagName: null, // overwritten in tests
};

[
{
case: "adds 'files' and 'value' attributes for INPUT if type=file",
Expand All @@ -76,6 +80,24 @@ const allTargetData = {
tagName,
output: { target: { currentTime: allTargetData.currentTime } },
})),
...["FORM"].map((tagName) => ({
case: `adds 'elements' attribute for ${tagName} element`,
tagName,
output: {
target: {
elements: [
{
value: "first",
boundingClientRect: mockBoundingRect,
},
{
value: "second",
boundingClientRect: mockBoundingRect,
},
],
},
},
})),
].forEach((expectation) => {
test(`serializeEvent() ${expectation.case}`, () => {
const eventData = {
Expand Down Expand Up @@ -113,6 +135,7 @@ const allEventData = {
clientX: "clientX",
clientY: "clientY",
ctrlKey: "ctrlKey",
form: "form",
metaKey: "metaKey",
pageX: "pageX",
pageY: "pageY",
Expand Down
20 changes: 20 additions & 0 deletions temp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from idom import component, event, html, run


@component
def Form():
@event(prevent_default=True)
def handle_form(event):
print(event["target"]["elements"])

return html.form(
{"onSubmit": handle_form},
html.input({"name": "firstname"}),
html.p("test"),
html.button({"type": "submit", "value": "Submit"}, "Submit"),
html.input({"lastname": "lastname"}),
html.p("tes2t"),
)


run(Form)