How to add object to react-final-form field name dynamically? - javascript

This react-final-form component will return the following result
<Field
name="answers[0].name"
component="input"
type="radio"
value="0"
/>
{ answers: [ { name: 'value' } ] }
How to add another property? that will end like This
{ answers: [ { name: 'user input value will here', other: 'my custom data' } ] }
According to final-form you can name your field component in 4 ways

You can add an initialValues prop to the form which will pre-populate the result.
<Form
onSubmit={onSubmit}
initialValues={{
answers: [ { other: 'your custom data' } ]
}}
>
<Field
name="answers[0].name"
component="input"
type="text"
/>
</Form>

Related

Display dynamically nested object as a table in Javascript

I'm trying to use nested object to display fields in a table. (using Material UI and formik)
My rows table are ordered by year so I have:
<Formik initialValues={{
2018: {
other: 1,
year: 2018,
number: 1,
name: "Jim",
surname: "Jon",
},
2019: {
other: 1,
year:2019,
number: 1,
name: "Tun",
surname: "Ton",
}}
onSubmit={()=>{}}>
To use nested Object I could do:
<Form>
<Field name="2018.name" />
<Field name="2019.name" />
<button type="submit">Submit</button>
</Form>
But if my response return something different from mine It don't works.
How can I fix it?
I'd tried like this:
export const REPORT_IVASS_FORM_INIT_VALUES = Object.freeze({
"year": '',
"name": '',
"surname": '',
"number": '',
"other": '',
})
and after:
response.map(el =>
<Field
name={response.2018[el.key]
type="text"
}
/>
)
but firstly response.2018[el.key], after response.2019[el.key] and so on.
But obviously it don't work.
You don't have to use key inside it , you can use it like this
{
response.map((el,index) => {
return <div key={index}>
<Field
name={response.name[el.index]
} type="text" />
</div>
})
}
looking at your initial value, it looks as if you receive an object, ordered by year where the year is unique. You should use a map function to return JSX for each year, and use a unique key for the key prop.
You can use Object.values to iterate and map over your initial data or api data, if its the same (an object) as your initial data
<Form>
{Object.values(initialValues).map((value) =>
<Field
key={value.year}
name={value.name}
type="text"
/>
)}
<button type="submit">Submit</button>
</Form>

Get list of Fields of an Ant Design Form

I have an ant design form on React.
How can I get the whole list of fields of a form? (all of them are wrapped by Form.Item)?
When I submit a form, is there any way to find out which fields are changed(touched) and their value?
import React from 'react'
function TempForm({ form }) {
const submit = e => {
e.preventDefault()
form.validateFields((error, values) => {
if (error) {
console.log('error while validating')
} else if (values) {
console.log('name: ', values.name, 'email: ', values.email)
}
})
}
return (
<Form onSubmit={submit}>
<div>
<Form.Item label="Customer">
{form.getFieldDecorator('name', {
initialValue: 'John',
rules: [{ required: true, message: 'Please select a customer!' }],
})(<Input type="text" placeholder="name" />)}
</Form.Item>
<Form.Item label="Customer Email">
{form.getFieldDecorator('email', {
rules: [{ required: true, message: 'Please select a Clinic' }],
})(<Input type="email" placeholder="customer email" />)}
</Form.Item>
</div>
</Form>
)
}
export default Form.create()(TempForm)
Here we are having a antd-form(import all necessary components) and a on-submit function. You can easily access all you fields as shown. Here values will be a js-object containing key-value pair or you can use form.getFieldValue('name') to access form values.

VueJS Input field value not binding

I have a problem with my generic input fields.
In other words I've made a generic input field which should cover regular input fields, checkboxes and radiobuttons. But when I try to pass a string value as a value of the radio input field, the prop is empty.
<TextInput
v-model="name"
description="Name & LastName"
name="Name & Surname"
rules="required"
/>
<TextInput
v-model="age"
type="number"
description="Age"
name="Age"
rules="required|digits:2"
/>
<div id="gender-fields">
<legend>Please specify your gender:</legend>
<TextInput
v-model="gender"
type="radio"
description="Male"
name="Gender"
rules="required"
/>
<TextInput
v-model="gender"
type="radio"
description="Female"
name="Gender"
rules="required"
/>
<TextInput
v-model="gender"
type="radio"
description="Unspecified"
name="Gender"
rules="required"
/>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
This is how I'm declaring my input fields in my form.
Here's the definiton of the Input Field.
<template>
<ValidationProvider
tag="div"
:rules="rules"
:name="name"
:vid="vid"
v-slot="{ errors }"
:mode="mode"
>
<label>
{{ description }}
<input :type="type" v-model="currentValue" :value="value" />
</label>
<span>{{ errors[0] }}</span>
</ValidationProvider>
</template>
<script>
import { ValidationProvider } from "vee-validate";
export default {
name: "TextInput",
components: {
ValidationProvider
},
props: {
description: {
type: String,
default: ""
},
value: {
required: true
},
rules: {
type: [String, Object],
default: ""
},
name: {
type: String,
default: ""
},
vid: {
type: String,
default: undefined
},
type: {
type: String,
default: "text"
},
mode: {
type: String,
default: "aggressive"
}
},
data: () => ({
currentValue: ""
}),
watch: {
currentValue(val) {
// allows us to use v-model on our input.
this.$emit("input", val);
}
}
};
</script>
<style></style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
THe only input fields I have a problem with are those radio buttons. Is there something I'm missing?
The easiest way to fix this is to skip putting :value="value" on the input and change your watch like this:
watch: {
//watch for value to change and assign it to our currentValue
value: {
handler(val) {
this.currentValue = val;
},
//this makes it run the handler function on mount in addition to whenever the value changes
immediate:true
},
currentValue(val) {
// allows us to use v-model on our input.
this.$emit("input", val);
}
}

How to dynamically show or hide form fields depending on the state of a BooleanInput field in react-admin?

I need to build a complex edit form with react-admin. The form has a variety of yes/no sliders made with the BooleanInput component of react-admin.
If the user sets the slider to "yes", further form fields should appear dynamically, which refer thematically to the slider. How do I query the status of the BooleanInput component or would this task be solved in react in a different way?
<BooleanInput source="yesno" label="show or hide fields" />
<AutocompleteArrayInput source="probably_hidden1" label="show or hide me" choices={[
{ id: 'one', name: '1' },
{ id: 'two', name: '2' },
{ id: 'three', name: '3' }
]} />
<TextInput multiline source="text" label="show or hide me too" />
I found out: It can be done using FormDataConsumer like this:
<BooleanInput source="yesno" label="show or hide fields" />
<FormDataConsumer>
{({ formData, ...rest }) => formData.yesno && <div>
<AutocompleteArrayInput source="yesno" label="show or hide fields" choices={[
{ id: 'one', name: '1' },
{ id: 'two', name: '2' },
{ id: 'three', name: '3' }
]} {...rest} />
<TextInput multiline source="text" label=""show or hide me too" {...rest} />
</div>
}
</FormDataConsumer>
See:
https://marmelab.com/react-admin/Inputs.html#hiding-inputs-based-on-other-inputs
You could write dynamically code inside JSX
> { isShow ? <TextInput ... /> : null }

Map value react.js

I am having a problem where I am trying use value in map. Is it possible to use value from state when mapping? How should I do it correctly?
const inputName=[
{id:1, label: 'Login',type:'text',name:'login',placeholder:'Enter login'},
{id:2, label: 'Password',type:'text',name:'password',placeholder:'Enter password'},
{id:3, label: 'Password',type:'password',name:'password2',placeholder:'Enter password again'},
{id:4, label: 'Name',type:'text',name:'firstName',placeholder:'Enter name'},
{id:5, label: 'Surname',type:'text',name:'lastName',placeholder:'Enter surname'},
{id:6, label: 'Position',type:'select',name:'role',option1:'Worker',option2:'Manager'},
]
/*My state*/
state = {
login: "",
password: "",
password2: "",
firstName: "",
lastName: "",
enable: true,
role: {
name: ""
}
};
/* My map */
/* How use value from state in my input mapping? */
const inputs = inputName.map(input => (
<FormGroup key={input.id}>
<Label>{input.label}</Label>
<Input
type={input.type}
name={input.name}
// value={} idk how get every value from state here
onChange={this.handleChange}
placeholder={input.placeholder}
>
<option>{input.option1}</option>
<option>{input.option2}</option>
</Input>
</FormGroup>
));
If I understand the question correctly, you could use your name property to access the state value by using the "bracket notation":
const inputs = inputName.map(input => (
<FormGroup key={input.id}>
<Label>{input.label}</Label>
<Input
type={input.type}
name={input.name}
value={this.state[input.name]} // access the value from the state
onChange={this.handleChange}
placeholder={input.placeholder}
>
<option>{input.option1}</option>
<option>{input.option2}</option>
</Input>
</FormGroup>
));
This only works if the key of your state property is equal to the name
You just have to find the value corresponding to the label property:
const inputs = inputName.map(input => (
<FormGroup key={input.id}>
<Label>{input.label}</Label>
<Input
type={input.type}
name={input.name}
value={this.state[input.label.toLowerCase()]} //this.state['login']
onChange={this.handleChange}
placeholder={input.placeholder}
>
<option>{input.option1}</option>
<option>{input.option2}</option>
</Input>
</FormGroup>
));

Categories