form support more inputs (#1554)
This commit is contained in:
parent
2c61077796
commit
cd47815a4d
@ -383,12 +383,26 @@ export const preventDefault = (event) => {
|
|||||||
* @returns The value.
|
* @returns The value.
|
||||||
*/
|
*/
|
||||||
export const getRefValue = (ref) => {
|
export const getRefValue = (ref) => {
|
||||||
if (!ref || !ref.current){
|
if (!ref || !ref.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ref.current.type == "checkbox") {
|
if (ref.current.type == "checkbox") {
|
||||||
return ref.current.checked;
|
return ref.current.checked;
|
||||||
} else {
|
} else {
|
||||||
return ref.current.value;
|
//querySelector(":checked") is needed to get value from radio_group
|
||||||
|
return ref.current.value || (ref.current.querySelector(':checked') && ref.current.querySelector(':checked').value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the values from a ref array.
|
||||||
|
* @param refs The refs to get the values from.
|
||||||
|
* @returns The values array.
|
||||||
|
*/
|
||||||
|
export const getRefValues = (refs) => {
|
||||||
|
if (!refs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// getAttribute is used by RangeSlider because it doesn't assign value
|
||||||
|
return refs.map((ref) => ref.current.value || ref.current.getAttribute("aria-valuenow"));
|
||||||
|
}
|
||||||
|
@ -28,6 +28,7 @@ DEFAULT_IMPORTS: imports.ImportDict = {
|
|||||||
ImportVar(tag="preventDefault"),
|
ImportVar(tag="preventDefault"),
|
||||||
ImportVar(tag="refs"),
|
ImportVar(tag="refs"),
|
||||||
ImportVar(tag="getRefValue"),
|
ImportVar(tag="getRefValue"),
|
||||||
|
ImportVar(tag="getRefValues"),
|
||||||
ImportVar(tag="getAllLocalStorageItems"),
|
ImportVar(tag="getAllLocalStorageItems"),
|
||||||
},
|
},
|
||||||
"": {ImportVar(tag="focus-visible/dist/focus-visible")},
|
"": {ImportVar(tag="focus-visible/dist/focus-visible")},
|
||||||
|
@ -22,12 +22,18 @@ class Form(ChakraComponent):
|
|||||||
A dict mapping the event trigger to the var that is passed to the handler.
|
A dict mapping the event trigger to the var that is passed to the handler.
|
||||||
"""
|
"""
|
||||||
# Send all the input refs to the handler.
|
# Send all the input refs to the handler.
|
||||||
return {
|
form_refs = {}
|
||||||
"on_submit": {
|
for ref in self.get_refs():
|
||||||
ref[4:]: Var.create(f"getRefValue({ref})", is_local=False)
|
# when ref start with refs_ it's an array of refs, so we need different method
|
||||||
for ref in self.get_refs()
|
# to collect data
|
||||||
}
|
if ref.startswith("refs_"):
|
||||||
}
|
form_refs[ref[5:-3]] = Var.create(
|
||||||
|
f"getRefValues({ref[:-3]})", is_local=False
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
form_refs[ref[4:]] = Var.create(f"getRefValue({ref})", is_local=False)
|
||||||
|
|
||||||
|
return {"on_submit": form_refs}
|
||||||
|
|
||||||
|
|
||||||
class FormControl(ChakraComponent):
|
class FormControl(ChakraComponent):
|
||||||
|
@ -88,8 +88,9 @@ class NumberInput(ChakraComponent):
|
|||||||
The component.
|
The component.
|
||||||
"""
|
"""
|
||||||
if len(children) == 0:
|
if len(children) == 0:
|
||||||
|
_id = props.pop("id", None)
|
||||||
children = [
|
children = [
|
||||||
NumberInputField.create(),
|
NumberInputField.create(id=_id) if _id else NumberInputField.create(),
|
||||||
NumberInputStepper.create(
|
NumberInputStepper.create(
|
||||||
NumberIncrementStepper.create(),
|
NumberIncrementStepper.create(),
|
||||||
NumberDecrementStepper.create(),
|
NumberDecrementStepper.create(),
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
"""A pin input component."""
|
"""A pin input component."""
|
||||||
|
|
||||||
from typing import Dict
|
from typing import Dict, Optional
|
||||||
|
|
||||||
from reflex.components.component import Component
|
from reflex.components.component import Component
|
||||||
|
from reflex.components.layout import Foreach
|
||||||
from reflex.components.libs.chakra import ChakraComponent
|
from reflex.components.libs.chakra import ChakraComponent
|
||||||
from reflex.event import EVENT_ARG
|
from reflex.event import EVENT_ARG
|
||||||
|
from reflex.utils import format
|
||||||
from reflex.vars import Var
|
from reflex.vars import Var
|
||||||
|
|
||||||
|
|
||||||
@ -66,6 +68,26 @@ class PinInput(ChakraComponent):
|
|||||||
"on_complete": EVENT_ARG,
|
"on_complete": EVENT_ARG,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def get_ref(self):
|
||||||
|
"""Return a reference because we actually attached the ref to the PinInputFields.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None.
|
||||||
|
"""
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _get_hooks(self) -> Optional[str]:
|
||||||
|
"""Override the base get_hooks to handle array refs.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The overrided hooks.
|
||||||
|
"""
|
||||||
|
if self.id:
|
||||||
|
ref = format.format_array_ref(self.id, None)
|
||||||
|
if ref:
|
||||||
|
return f"const {ref} = Array.from({{length:{self.length}}}, () => useRef(null));"
|
||||||
|
return super()._get_hooks()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, *children, **props) -> Component:
|
def create(cls, *children, **props) -> Component:
|
||||||
"""Create a pin input component.
|
"""Create a pin input component.
|
||||||
@ -81,7 +103,21 @@ class PinInput(ChakraComponent):
|
|||||||
The pin input component.
|
The pin input component.
|
||||||
"""
|
"""
|
||||||
if not children and "length" in props:
|
if not children and "length" in props:
|
||||||
children = [PinInputField()] * props["length"]
|
_id = props.get("id", None)
|
||||||
|
length = props["length"]
|
||||||
|
if _id:
|
||||||
|
children = [
|
||||||
|
Foreach.create(
|
||||||
|
list(range(length)), # type: ignore
|
||||||
|
lambda ref, i: PinInputField.create(
|
||||||
|
key=i,
|
||||||
|
id=_id,
|
||||||
|
index=i,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
children = [PinInputField()] * length
|
||||||
return super().create(*children, **props)
|
return super().create(*children, **props)
|
||||||
|
|
||||||
|
|
||||||
@ -89,3 +125,19 @@ class PinInputField(ChakraComponent):
|
|||||||
"""The text field that user types in - must be a direct child of PinInput."""
|
"""The text field that user types in - must be a direct child of PinInput."""
|
||||||
|
|
||||||
tag = "PinInputField"
|
tag = "PinInputField"
|
||||||
|
|
||||||
|
# the position of the PinInputField inside the PinInput.
|
||||||
|
# Default to None because it is assigned by PinInput when created.
|
||||||
|
index: Optional[Var[int]] = None
|
||||||
|
|
||||||
|
def _get_hooks(self) -> Optional[str]:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_ref(self):
|
||||||
|
"""Get the array ref for the pin input.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The array ref.
|
||||||
|
"""
|
||||||
|
if self.id:
|
||||||
|
return format.format_array_ref(self.id, self.index)
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
"""A range slider component."""
|
"""A range slider component."""
|
||||||
|
|
||||||
from typing import Dict, List
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
from reflex.components.component import Component
|
from reflex.components.component import Component
|
||||||
from reflex.components.libs.chakra import ChakraComponent
|
from reflex.components.libs.chakra import ChakraComponent
|
||||||
from reflex.event import EVENT_ARG
|
from reflex.event import EVENT_ARG
|
||||||
|
from reflex.utils import format
|
||||||
from reflex.vars import Var
|
from reflex.vars import Var
|
||||||
|
|
||||||
|
|
||||||
@ -55,6 +56,26 @@ class RangeSlider(ChakraComponent):
|
|||||||
"on_change_start": EVENT_ARG,
|
"on_change_start": EVENT_ARG,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def get_ref(self):
|
||||||
|
"""Get the ref of the component.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The ref of the component.
|
||||||
|
"""
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _get_hooks(self) -> Optional[str]:
|
||||||
|
"""Override the base get_hooks to handle array refs.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The overrided hooks.
|
||||||
|
"""
|
||||||
|
if self.id:
|
||||||
|
ref = format.format_array_ref(self.id, None)
|
||||||
|
if ref:
|
||||||
|
return f"const {ref} = Array.from({{length:2}}, () => useRef(null));"
|
||||||
|
return super()._get_hooks()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, *children, **props) -> Component:
|
def create(cls, *children, **props) -> Component:
|
||||||
"""Create a RangeSlider component.
|
"""Create a RangeSlider component.
|
||||||
@ -69,13 +90,23 @@ class RangeSlider(ChakraComponent):
|
|||||||
The RangeSlider component.
|
The RangeSlider component.
|
||||||
"""
|
"""
|
||||||
if len(children) == 0:
|
if len(children) == 0:
|
||||||
children = [
|
_id = props.get("id", None)
|
||||||
RangeSliderTrack.create(
|
if _id:
|
||||||
RangeSliderFilledTrack.create(),
|
children = [
|
||||||
),
|
RangeSliderTrack.create(
|
||||||
RangeSliderThumb.create(index=0),
|
RangeSliderFilledTrack.create(),
|
||||||
RangeSliderThumb.create(index=1),
|
),
|
||||||
]
|
RangeSliderThumb.create(index=0, id=_id),
|
||||||
|
RangeSliderThumb.create(index=1, id=_id),
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
children = [
|
||||||
|
RangeSliderTrack.create(
|
||||||
|
RangeSliderFilledTrack.create(),
|
||||||
|
),
|
||||||
|
RangeSliderThumb.create(index=0),
|
||||||
|
RangeSliderThumb.create(index=1),
|
||||||
|
]
|
||||||
return super().create(*children, **props)
|
return super().create(*children, **props)
|
||||||
|
|
||||||
|
|
||||||
@ -98,3 +129,16 @@ class RangeSliderThumb(ChakraComponent):
|
|||||||
|
|
||||||
# The position of the thumb.
|
# The position of the thumb.
|
||||||
index: Var[int]
|
index: Var[int]
|
||||||
|
|
||||||
|
def _get_hooks(self) -> Optional[str]:
|
||||||
|
# hook is None because RangeSlider is handling it.
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_ref(self):
|
||||||
|
"""Get an array ref for the range slider thumb.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The array ref.
|
||||||
|
"""
|
||||||
|
if self.id:
|
||||||
|
return format.format_array_ref(self.id, self.index)
|
||||||
|
@ -434,6 +434,24 @@ def format_ref(ref: str) -> str:
|
|||||||
return f"ref_{clean_ref}"
|
return f"ref_{clean_ref}"
|
||||||
|
|
||||||
|
|
||||||
|
def format_array_ref(refs: str, idx) -> str:
|
||||||
|
"""Format a ref accessed by array.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
refs : The ref array to access.
|
||||||
|
idx : The index of the ref in the array.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The formatted ref.
|
||||||
|
"""
|
||||||
|
clean_ref = re.sub(r"[^\w]+", "_", refs)
|
||||||
|
if idx:
|
||||||
|
idx.is_local = True
|
||||||
|
return f"refs_{clean_ref}[{idx}]"
|
||||||
|
else:
|
||||||
|
return f"refs_{clean_ref}"
|
||||||
|
|
||||||
|
|
||||||
def format_dict(prop: ComponentStyle) -> str:
|
def format_dict(prop: ComponentStyle) -> str:
|
||||||
"""Format a dict with vars potentially as values.
|
"""Format a dict with vars potentially as values.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user