Array concat make an object on every input - javascript

I am trying to take input from user and push that input into array of object . It working fine but I face one problem . When I type for exmaple ( Nine ) so it created 4 object inside array . I want only single object and store user value.
It created an array like
[
{name : 'text', value : 'N'}
{name : 'text', value : 'Ni'}
{name : 'text', value : 'Nin'}
{name : 'text', value : 'Nine'}
]
Could someone please help me how to resolve this issue. Thanks
Code
<input
type="text"
className="inputStyle"
placeholder={item.fieldName}
onChange={(e) =>
this.generateExtraFieldData(
e.target.value,
item.fieldName
)
}
/>
generateExtraFieldData = (data, type) => {
const { optionalFields } = this.state;
var joined = optionalFields.concat({ name: "text", value: data });
this.setState({
optionalFields: joined,
});
};

You don't need to join or concat the fields yourself, you can simply use:
this.setState({
optionalFields: {name:'text', value: data},
});

Ideally, you can consider that when the user stop typing, he won't insert a new character, so basically you can store only the most recent value and replace it every time:
<input
type="text"
className="inputStyle"
placeholder={item.fieldName}
onChange={(e) =>
this.generateExtraFieldData(
e.target.value,
item.fieldName
)}
/>
generateExtraFieldData = (data, type) => {
this.setState({
optionalFields: { name: "text", value: data },
});
};

I believe you should listen to onBlur event but rather waiting for the user to stop typing. That's because if a user types nin and then stops, he would try again to fix the typo by appending e to nin which will result again in two different objects with the following
[ { name: "text", value: 'nin' }]
[ { name: "text", value: 'nine' }]
While if you listen to onBlur event, you can just empty the input and ask user to add a new optional field. That way giving the user time to think and look in case of any typo
<input
type="text"
className="inputStyle"
placeholder="test"
onBlur={(e) =>
this.generateExtraFieldData(
e.target, // pass the e.target so we can empty the input after adding to array
'name'
)
}
/>
generateExtraFieldData = (target, type) => {
const { optionalFields } = this.state;
var joined = optionalFields.concat({ name: "text", value: target.value });
this.setState({
optionalFields: joined,
});
target.value = '';
};
Here's the working Plunker

Related

Set JSON field to undefined if no user input in React - instead of an empty JSON object like "customer": { }

I have a JSON variable data that has a customer field with 6 properties:
const submit = async (values) => {
const data = {
customer: {
firstname: values.firstname,
lastname: values.lastname
...
},
...
...
And a form in which user inputs are submitted to the JSON variable:
<Field name="firstname" component={InputField} type="text" />
<Field name="lastname" component={InputField} type="text" />
These fields are not required but the empty customer object still gets sent to my API as "customer": { }
How can I get rid of it? I know if I set the customer object to undefined, it will be ignored from the whole JSON, but can't seem to figure out where I should set it so that it does not look bad.
I guess it is something like this?
data.keys(customer).length > 1 ? customer : undefined
Q: is there any way to check inside the const variable, that values contain customer data, and if not, it defaults to undefined?
By using delete keyword you can delete the customer property if it is empty, now your data will have all the properties without the customer property
function isEmpty(obj) {
return Object.keys(obj).length === 0;
}
if('customer' in data)
{
if(isEmpty(data.customer))
delete data.customer;
}
You can try this:
data.customer = Object.keys(data.customer).length ? data.customer : undefined
let name = { d: 'test', };
let data = { name: name.d ? name.d : undefined, email: name.email ? name.email : undefined, };
List item
let name = {
d: 'test',
};
let data = {
name: name.d ? name.d : undefined,
email: name.email ? name.email : undefined,
};
console.log('data===>', data);
console.log('data===>', data);

Get parent VALUE on React-select grouped options

Im using react-select with grouped options, they are grouped like this:
{
label: PARENT_NAME,
value: PARENT_ID,
options: [
{
label: CHILD_NAME,
value: CHILD_ID,
}
]
}
I have an array with those options, and im passing it to the component like this:
<Select
options={ARR_OF_OPTIONS}
onChange={this.handleChange("name")}
/>
My handleChange function is like this:
handleChange = name => selectedOption => {
const value = selectedOption.value
this.setState({ [name]: value, })
}
My question is:
Is it possible to get the PARENT_ID when selecting the child option?
Hopefully I made myself clear.
Thanks in advance
Every option can have more properties
{
label: PARENT_NAME,
value: PARENT_ID,
options: [
{
label: CHILD_NAME,
value: CHILD_ID,
// additional properties
group: PARENT_ID,
otherValue: OTHER_VALUE,
}
]
}
selectedOption is an object - you can easily access group, otherValue
handleChange = name => selectedOption => {
const value = selectedOption.value
console.log("group", selectedOption.group )
this.setState({ [name]: value, })
}
This method (based on original react-select grouped example) duplicates data (in this case) but is safe for case when value can exists in multiple groups (can't be reliably found by comparing value).
You can achieve this with pure JavaScript. On your handleChange method, you should filter out the grouped object from ARR_OF_OPTIONS that contains the selected child option.
const selectedParent = ARR_OF_OPTIONS
.find((group) => group.options.find(({ value }) => value === selectedOption.value));
const { value } = selectedParent; // this gives you the parent id

Mapping a variable to the state in React

I'm having a problem mapping a certain value to the state.For example, using this json var on my state (its an example only, doesnt need to make sense the json variable):
this.state={
person:
{
nose:'',
legs:{
knees:'',
foot:{
finger:'',
nail:''
}
}
}
}
What I want to to is to create this 'person' on my frontend, by user input, and the send it to my backend,but Im having a problem.
Imagine that I want to change the person.nose atribute of my state variable.
The user writes the information by using this input field:
<input name={props.name} onChange={handleChange} type="text" className="form-control" />
And this is the call that I made to that same component:
<TextInput name="nose" onChange={this.handleChange} />
When executing the handleChange method,I cant update the variable,its always empty, I have tried using on the name field on my textInput "name","this.state.person.nose" but nothing happened, its always empty.
Here is my handleChange method:
handleChange(evt) {
this.setState({ [evt.target.name]: evt.target.value });
}
NEW EDIT:
So, now Im having this problem.This is a more realistic json object than the first one:
{
name: '',
iaobjectfactory: {
institution: '',
parameter: [{
value: '',
classtype: ''
}],
name: '',
usedefaultinstitution: '',
methodname: ''
},
ieventhandlerclass: ''
}
This is the output that my frontend should give me, but this is what the most recent solution returned me:
{
"name":"d",
"iaobjectfactory":{
"institution":"",
"parameter":[
{
"value":"",
"classtype":""
}
],
"name":"",
"usedefaultinstitution":"",
"methodname":""},
"ieventhandlerclass":"d",
"institution":"d",
"methodname":"d",
"usedefaultinstitution":"d"
}
The values that should be on the iaobjectfactory are outside of it,I dont know why, I used this:
handleChange(evt) {
const { name, value } = evt.target;
// use functional state
this.setState((prevState) => ({
// update the value in eventType object
eventType: {
// keep all the other key-value pairs
...prevState.eventType,
// update the eventType value
[name]: value
}
}))
EDIT 2:
This is the json output now.
{
"name":"",
"iaobjectfactory":{
"institution":"bb",
"parameter":[
{"value":"",
"classtype":""
}],
"name":"bb",
"usedefaultinstitution":"bb",
"methodname":"bb",
"ieventhandlerclass":"aa"},
"ieventhandlerclass":""}
Problems:The first name is not reading and the ieventhandlerclass is inside the iaobjectfactory and it shouldnt
Problem with your code is, it will create a new variable nose in state and assign the value to that key. you can access the input value using this.state.nose.
Updating nested state is not that easy, you have to take care about all the other key-value pairs. In your case nose will be accessible by this.state.person.nose, so you need to update person.nose value not nose value.
You need to write it like this:
this.handleChange(evt) {
const { name, value } = evt.target;
// use functional state
this.setState((prevState) => ({
// update the value in person object
person: {
// keep all the other key-value pairs
...prevState.person,
// update the person value
[name]: value
}
}))
}
What it will do is, it will keep all the key-value pairs as it is and only update the person.nose value.
Update:
You are trying to update value of person.iaobjectfactory.name not person.name, so you need to keep all the key-values of person.iaobjectfactory and update only one at a time, like this:
handleChange(evt) {
const { name, value } = evt.target;
// use functional state
this.setState((prevState) => ({
// update the value in eventType object
eventType: {
// keep all the other key-value pairs of eventType
...prevState.eventType,
// object which you want to update
iaobjectfactory: {
// keep all the other key-value pairs of iaobjectfactory
...prevState.eventType.iaobjectfactory,
// update
[name]: value
}
}
}))
}

How to create a filter dropdown using React.js?

How can I implement logic for filter dropdown?
In the application is page when we can manage users, like: create, edit, remove and show. Also there is option to disable user.
There is Table for Users, on which I need to implement filter.
I need to filter by users which are "Active" that mean they have property disable: false. And "Deactive" users which have disabled: true
Here is how my Filter dropdown array looks:
const statusOptions = [
{
key: 'all',
text: 'All',
value: 'all'
},
{
key: 'disabled',
text: 'Active',
value: false
},
{
key: 'disabled',
text: 'Deactive',
value: true
}
]
<Form.Dropdown
label="Filter by Status"
name="disabled"
selection
onChange={this.handleFieldChange}
value={disabled || 'all'}
fluid
options={statusOptions}
/>
Handle Field Change function:
handleFieldChange = (e, { name, value } = {}) => {
const { onChange } = this.props
this.setState((current = {}) => {
const next = {
...current,
[name]: value
}
onChange && onChange(next)
return next
})
}
Any idea how to organize this filter logic on correct way?
The code you have posted is a little confusing, but I think what you need is the ability to update your view depending on whether a specific user is enabled or disabled.
The original array of users is presumably injected into the component as a prop; I assume that each of these users has an "enabled" property which is set to 'enabled', 'disabled' or 'all'. I'm also assuming that you somehow iterate over this list to build your UI, specifically something like:
<ul>
{ this.users.filter((user) => user.state === this.filterState)
.map((relevantUser) => {
return (
<User {..relevantUserProps}>
)
})
}
</ul>
So your handleChange callback simply needs to set the filterState of the component:
handleFieldChange = (event) => {
const newFilterState = this.statusOptions.find((option) => option.text === event.target.value)).key
this.setState({
filterState: newFilterState,
})
Clearly this logic might not exactly fit your component, but hopefully you get the gist. Hope that helps.

Best way for a React and HTML Select-component to return String instead of Integer

I have a React-class (JSX) that contains following (slightly simplified here) code:
var Select = React.createClass({
onChange: function (ev) {
console.log(ev.target.value);
},
render: function() {
var optionsHtml = this.state.options.map(function (el) {
console.log(this.props.getValue(el);
return (
<option key={this.props.getValue(el)}
value={this.props.getValue(el)}> { this.props.getLabel(el) }
</option>
)
});
return <select onChange={this.onChange}>
{optionsHtml}
</html>
}
In the render-function, console.log returns Integers for values (i.e. 1, 2, 3) when initializing the Options-HTML and setting the values, however inside the onChange-method value is a String (i.e. "1", "2", "3") when the actual Select-box value is changed.
One way to fix this would be to check and cast the value to Number before using it inside onChange, but is there any other way to do it?
EDIT:
Options-array could look something like this
var options = [
{ id: 1, name: "Test" },
{ id: 2, name: "Test2" },
{ id: 3, name: "Test3" }
]
Component then could be called with getValue and getLabel -functions like this:
<Select options={options},
getValue: function(v) {
return v.id;
},
getLabel: function(v) {
return v.name;
}/>
Different type is an issue once I generate a JSON that I'm sending to backend, and I need to the conversion at some point.
When your onChange function executes and attempts to read the value of an option tag, it's important to remember that all attributes will be read as strings.
With that being said, note that
onChange: function (ev) {
console.log(ev.target.value);
// ^^^^^^^^^^^^^^^ always string
}
So each time you want to handle a value in your onChange function, you must cast the value to an number. Something like this should do the trick:
onChange: function (ev) {
var valueInt = parseInt(en.target.value, 10);
console.log(valueInt);
}
Or if the value isn't necessarily going to be a number, you can attempt to parse it as a number if applicable:
onChange: function (ev) {
var valueInt;
try{
valueInt = parseInt(en.target.value, 10);
}catch(e){
// handle value not being a number if unexpected
}
console.log(valueInt);
}
I would change render method and event listener to this:
onChange(event) {
const el = this.state.options[event.target.value];
const value = this.props.getValue(el);
},
render() {
const options = this.state.options.map((el, idx) => (
<option key={this.props.getValue(el)} value={idx}>{ this.props.getLabel(e) }</option>
));
return (
<select onChange={this.onChange}>
{ options }
</select>
)
}
Doing this, you are not getting actual value. You are telling "Pick object at index N from within predefined objects and get it's value."

Categories