export function URLInput() {
const [value, setValue] = useState("");
return (
<Row>
<Col span={24}>
<FloatLabel label="URL" name="url" labelValue={value}>
<Form.Item
hasFeedback
name="url"
rules={[
{
required: true,
min: 5,
type: "url",
whitespace: true,
},
]}
>
<Input
name="url"
onChange={(event) => setValue(event.target.value)}
/>
</Form.Item>
</FloatLabel>
</Col>
</Row>
);
}
I currently have this Form.Item setup.
If there is already a value in url set in the form's initialValues, the Form.Item will magically populate the input field with the value.
However, I want to be able to access this value too so that I can initialize value in
const [value, setValue] = useState("I want to initialize the value here without introducing a props");
How do I do this?
Edit:
The <URLInput> component is actually used inside of a <Form> like this:
<Form
form={form}
onFinish={handleFormSubmit}
initialValues={{ content: content}}
>
<URLInput/>
</Form>
Pass form to URLInput as a prop, then inside URLInput you can access the initialValue url by invoking the following form.getFieldValue('url').
Please see working CodeSandbox example below:
https://codesandbox.io/s/antdform-accessing-formvalues-in-child-formitem-component-uwdb7
Happy coding!
Related
I now have an antd form component that wraps the input component inside the component. Now the input component can be manually controlled, and the verification function must be added. However, after the name attribute is deleted, it can be controlled manually, but it cannot be verified. If the name attribute is not deleted , it cannot be manually controlled
demo01
Can't be controlled
const [count,setCount] = useState('')
<Form>
<Form.Item label='test' name="test" rules={[{required:true}]}>
<Input
value={count}
onChange={(e)=>{
const {value} = e.target
// Can't be controlled
setCount(value)
}}
/>
</Form.Item>
</Form>
demo2
Can't check
const [count,setCount] = useState('')
<Form>
<Form.Item
label='test'
// name="test"
rules={[{required:true}]}> // 不能校验
<Input
value={count}
onChange={(e)=>{
const {value} = e.target
// 能受控
setCount(value)
}}
/>
</Form.Item>
</Form>
How can I make it both a verification and a controlled component, thank you
I'm building a simple html form using "react-hook-form" library: https://react-hook-form.com/
I've incorporated "react-bootstrap-typeahead" into the html form but haven't been able to register this component with 'useForm' hook. Hence, "react-bootstrap-typeahead" input data is ignored during onSubmit.
"react-bootstrap-typeahead" doesn't provide a "name" prop which makes it difficult to register the component.
I've read the 'useForm' documentation on the different options for registering this type of components but still don't understand how to achieve this: https://react-hook-form.com/get-started#Registerfields
Does anybody have faced such challenge before?
It would be great to see a working example to get a better idea on how to implement "react-bootstrap-typeahead" + "react-hook-form" in my application. Thanks!
Here's my sample code:
import useForm from 'react-hook-form';
import { Typeahead } from 'react-bootstrap-typeahead';
import 'react-bootstrap-typeahead/css/Typeahead.css';
const myForm = (props) => {
const { register, handleSubmit, errors } = useForm();
const onSubmit = data => {
// api post request with form data
})
};
const mydata = [ "one", "two", "three" ];
return (
<>
<form onSubmit={handleSubmit(onSubmit)} >
<div className="form-group">
{/* Here I'm registering text input using ref: */}
<input type="text" className="form-control" name="name" ref={register({ required: true })} />
</div>
<div className="form-group mb-0">
{/* How can I register the below component with useForm? */}
<Typeahead
id="multiple-typeahead"
clearButton
multiple
options={mydata}
/>
</div>
<button type="submit">Save</button>
</form>
</>
);
}
This is how i was able to register the component:
import useForm from 'react-hook-form';
import { useForm, Controller } from "react-hook-form";
import 'react-bootstrap-typeahead/css/Typeahead.css';
const myForm = (props) => {
const { register, handleSubmit, errors, control } = useForm();
const onSubmit = data => {
// api post request with form data
})
};
const mydata = [ "one", "two", "three" ];
return (
<>
<form onSubmit={handleSubmit(onSubmit)} >
<div className="form-group">
<input type="text" className="form-control" name="name" ref={register({ required: true })} />
</div>
<div className="form-group mb-0">
<Controller
as={Typeahead}
control={control}
name="typeahead_component"
rules={{ required: true }}
id="multiple-typeahead"
clearButton
multiple
options={mydata}
defaultValue=""
/>
</div>
<button type="submit">Save</button>
</form>
</>
);
}
I need to get all values in onSubmit method, not only dirty fields.
import React from 'react'
import { Form, Field } from 'react-final-form'
const App: React.FC = () => (
<Form onSubmit={values => console.log(values)}>
{({ form: { submit } }) => (
<>
<Field name="street" component="input" placeholder="street" />
<Field name="city" component="input" placeholder="city" />
<Field name="state" component="input" placeholder="state" />
<button onClick={submit}>Submit</button>
</>
)}
</Form>
)
export default App
Actual result:
{street: "A", city: "B"}
Expected result:
{street: "A", city: "B", state: null}
🏁 Final Form treats '' and undefined as more or less equivalent.
You'll need to provide an initialValues={{ street: null, city: null, state: null }} to get your expected result. However, if the user touches field, changes the value, and then changes it back to empty, the street key will be deleted from the form values (see above link). You could get around that by providing a parse={v => v} to cancel the normal ''-to-undefined conversion.
Hope that helps?
I am trying to create a Wizard form using react-final-form by referring to this code https://codesandbox.io/s/km2n35kq3v. For my use case I need some mutator functions to be used inside my form fields. This example illustrates how to do that - https://codesandbox.io/s/kx8qv67nk5?from-embed.
I am not sure how to access mutator functions in my form steps when I am using a wizard form instead of a single page form.
I tried to combine both the examples by modifying the <Form> component rendered by Wizard.js to pass in the mutators. However I cannot access these mutators in the Wizard form pages.
In Wizard.js
return (
<Form
mutators={{
// potentially other mutators could be merged here
...arrayMutators,
}}
render={({
handleSubmit,
submitting,
values,
pristine,
invalid,
form: {
mutators: {push, pop, remove},
},
}) => {
return (
<form onSubmit={handleSubmit}>
Another file index.js
<Wizard
initialValues={{ employed: true, stooge: "larry" }}
onSubmit={onSubmit}
>
<Wizard.Page>
<FieldArray name="customers">
{({ fields }) =>
fields.map((name, index) => (
<div key={name}>
<label>Cust. #{index + 1}</label>
<Field
name={`${name}.firstName`}
component="input"
placeholder="First Name"
/>
<span
onClick={() => fields.remove(index)}
style={{ cursor: "pointer" }}
>
❌
</span>
</div>
))
}
</FieldArray>
</Wizard.Page>
</Wizard>
It errors out - remove is undefined in index.js
Look at this working example: https://codesandbox.io/s/znzlqvzvnx
changes I have made:
Wizard.js
static Page = ({ children, mutators }) => {
if(typeof children === 'function'){
return children(mutators);
}
return children;
};
...
<form onSubmit={handleSubmit}>
{
// activePage
<activePage.type {...activePage.props} mutators={mutators} />
}
...
index.js (only first <Wizard.page>)
<Wizard.Page>
{
({ upper }) => (
<React.Fragment>
<div>
<label>First Name</label>
<Field
name="firstName"
component="input"
...
</div>
</React.Fragment>
)
}
</Wizard.Page>
I've created a JSFiddle to help demonstrate my question: http://jsfiddle.net/jeffreyrswenson/CrYWn/5/
Here's what I'd like to see:
Messages should not appear when page loads.
Messages should appear when submit button is pushed.
Messages should appear after input value is changed and user leaves element. (Tabs or clicks to next field)
Messages should appear after user leave an input without changing.(For example a field is required and the user tabs through the field, but doesn't enter a value. I'd like the validation message to appear when this happens.)
The first four work as I'd expect. Is the last item possible and if so, what do I need to change to enable that behavior?
HTML:
<label>First name:
<input data-bind='value: firstName' />
</label>
<br/>
<label>Last name:
<input data-bind='value: lastName' />
</label>
<br/>
<button type="button" data-bind='click: submit'>Submit</button>
<br/>
<span data-bind='text: errors().length'></span> errors
ViewModel:
var viewModel = function () {
ko.validation.configure({
decorateElement: true,
registerExtenders: true,
messagesOnModified: true,
insertMessages: true,
parseInputAttributes: true,
messageTemplate: null
});
this.firstName = ko.observable().extend({
required: true
});
this.lastName = ko.observable().extend({
required: true,
pattern: {
message: 'Hey this doesnt match my pattern',
params: '^[A-Z0-9]+$'
}
});
this.submit = function () {
if (this.errors().length == 0) {
alert('Thank you.');
} else {
this.errors.showAllMessages();
}
};
this.errors = ko.validation.group(this);
};
You just need to use the standard valueUpdate option of the value binding where you can specify additional events to trigger your property change and with that the validation.
So you just need to add the valueUpdate: "blur" setting on your bindings:
<label>First name:
<input data-bind='value: firstName, valueUpdate: "blur"' />
</label>
<br/>
<label>Last name:
<input data-bind='value: lastName, valueUpdate: "blur"' />
</label>
Demo JSFiddle.
In my case, I needed the value to update after key down because I was making some fields visible if the input had a value. I wanted the underlying value to update but didn't want the validation to show until the user tabbed to the next input.
A bit of CSS and a couple of bindings is what worked for me:
CSS:
div.validationWrapper.standard-focus.has-focus .validationMessage
{
display: none;
}
HTML:
<div class="validationWrapper standard-focus" data-bind="css: { 'has-focus': MyObservableHasFocus() }">
<input class="standard-focus" type="text" data-bind="hasFocus: MyObservableHasFocus, value: MyObservable, valueUpdate: 'afterkeydown'" />
</div>
Knockout:
self.MyObservable = ko.observable('').extend({/* Your validation here */});
self.MyObservableHasFocus = ko.observable(false);
The result is an observable that updates it's value after key up and shows the validation message after it loses focus.