ReactJS Complex Form Input Field Duplicating Text in Multiple Input Fields - javascript

I have a form where you can add/remove groups and input items, I was able to get the groups of input field working, but I'm having trouble with the items input within the respected groups:
I created a code sand box here: https://codesandbox.io/s/twilight-cache-4ipv6?file=/src/Form.jsx
If you click on Add Items + button, and type in the item fields, the value duplicates to all the fields.
Also, sometimes I feel like the x button doesn't work, and will only remove the last item or something, I believe this is "controlled component?"
In addition, I want to ask if there's a better method on what I'm doing? It seems like there's a lot of complexities in the code I'm trying to write up. I feel like I'm writing too much of the set state hooks.

I think we don't need that fields state.
And we can update Add Handlers like this
const handleAddGroup = i => {
const newGroup = [...group];
newGroup.push({
id: null,
cat: "",
items: [
{
name: "",
value: ""
}
]
});
setGroups(newGroup);
};
const handleAddField = i => {
setGroups(state => {
const stateCopy = JSON.parse(JSON.stringify(state));
stateCopy[i].items.push({
name: "",
value: ""
});
return stateCopy;
});
};
https://codesandbox.io/s/cool-frog-2yrlt

Related

Angular: RxWeb unique() validator not working properly

I have implemented a form that has a FormArray. In the FormArray, one control needs to have a unique value throughout the array. The unique() validator from RxWeb is working fine normally but the issue is working when I am pushing values in the FormArray manually it is not triggering the unique() validator. An example method mentioned below which is called on a button click:
abc() {
let skillsArray = <FormArray>this.jobFormGroup.controls.skills;
skillsArray.removeAt(0);
const arr = [
{ skillName: 'A' },{ skillName: 'A' },
];
arr.forEach(item => skillsArray.push(this.formBuilder.group(item)))
}
None of the field is highlighed as red.
Highlighted in red when I enter data from UI.
You can use this Stackblitz example for playing around with the issue. Please click on the "Trigger Issue" button to create the issue shown in Image 1.
Because your function abc() does not add the controls with the unique validator
const arr = [
{ skillName:['A',RxwebValidators.unique()] },{ skillName:
['A',RxwebValidators.unique()] },
];

How to push new column into array using setState

I am using an external library to build a Taskboard and what I want to achieve is to add a new column when clicking and add column button. I am struggling with adding the column, I have the newly created column but it doesn't get added to the array. What am I doing wrong and how can I insert the newly created column? Here is my code:
onAddColumn = () => {
const newColumn: TaskBoardColumnModel = {
id: this.state.columnsData.length + 1,
title: 'New Column',
status: 'new',
edit: true,
};
console.log(this.state.columnsData);
this.setState({
columsData: newColumn,
});
console.log(this.state.columsData);
};
}
Your main issue is the way you update your state. This is what you have:
this.setState({
columsData: newColumn,
});
This piece of code will set the state to columsData: newColumn, which is wrong for a few reasons:
columsData should be columnsData
Your piece of code will remove all the other columns and replace it with only one. Which will fail the code because columnsData will become an object and not an array
Here is what it should be:
this.setState({
columnsData: [...this.state.columnsData, newColumn],
});
This will keep your current state, and add the new column to your existing list.
You have a typo in columsData. Additionally columnsData should be an array so you probably need to set the new state to the old one plus the new column.
e.g. something like:
this.setState({
columnsData: [...this.state.columnsData, newColumn],
});
this.setState({
if(this.state.columnsData && this.state.columnsData.length>0)
{
columnsData: [...this.state.columnsData, newColumn],
}
});

How to add dynamic input values to the local state for retrieval

I have a React Native form that allows me to add an Input UI in the form, by clicking a button with this function. This allow me to generate it on the fly. The code for that is this.
addClick() {
this.setState(prevState => ({ values: [...prevState.values, ""] }));
console.log(this.values[0].name);
}
That part works well, but I'm having a problem extracting the data from the dynamic inputs, and add it to an array. So far I have tried this
setVal = value => {
const values = this.state.values[0];
if (values[0].name === "" || values[0].description === "") return;
[...this.state.values, value];
this.setState(values);
console.log(values);
};
How do I organize my states properly so that I can add as many inputs I need, and when I'm finished, I can update the state, and access the new data in my list component?
How do I update my state to the new Array? at the moment, this.state only shows the initial state set at the top.
I'm missing a few things
Please take a look at the full code sandbox HERE so you can see:
See...your created isssue is not so obvious we need to see where you call setVal() function but....
i think you will be more comfortable if you render your <input/> s directly from your state array, not from const x = [] variant. because it seems like you want a dynamic view and in such a cases you will need to bind your loop quantity from state. so:
this.state = {
x: [0,1,2,3,4]
}
and inside your render :
{this.state.x.map(x => {
return (
<TextInput
placeholder={`name${x}`}
value={values[x.toString()]}
handleBlur={() => handleBlur(x.toString())}
onChangeText={handleChange(x.toString())}
style={styles.input}
/>
);
})}

multiple filters, one onChange function

My structure:
index.js
--> Filters
--> {list}
Filters contains multiple input elements that set the state in index.js via props.
list displays as you guessed it, a list of elements. I now want to filter this list based on the values returned by the filters. Pretty standard I think and found on millions of sites.
The issue is that I want to make the input onChange function reusable. With only one input in the Filters component I had this (shortened):
<input
value={this.state.anySearch}
onChange={this.handleChange}
/>
handleChange = event => {
const value = event.target.value;
this.setState({ anySearch: value });
};
With multiple inputs I tried this, aka reusable for any input:
handleChange = name => event => {
const value = event.target.value;
this.setState({ name: value });
};
onChange={this.handleChange("anySearch")}
But this doesn't work anymore. State now shows only one letter at a time when console logged.
What is best practice to filter according to multiple different criteria à la kayak, and how do I rewrite the handleChange function without pushing each letter into an array?
handleChange = name => event => {
const value = event.target.value;
this.setState({ name: value });
};
your idea of returning a function is correct, you just have an error when setting the state
this.setState({ name: value });
change it to
this.setState({ [name]: value });
Regarding the second question, you can simply iterate over your array and filter out the objects that match that specific criteria, to avoid unnecessary overhead you can implement a caching mechanism that keep track of the searches the user has already done.
something like this:
function filter(criteria) {
if(cache[criteria]) {
return cache[criteria];
}
cache[criteria] = myArray.filter(elem => elem.criteria === criteria);
return cache[criteria];
}

rxjs - single observable for multiple inputs or an observable per input

I was wondering if there were any negative reasons for using a single observable to track multiple input fields. The only problem I've really come across from doing this is that I can't really use distinctUntilChanged because there are cases where the text may end up overlapping, which means it doesn't trigger.
Example of my single observable:
this.subscription = Rx.Observable.fromEvent($(joined), 'keyup')
.pluck('target')
.flatMap(target=>
Rx.Observable.of(target.value)
.filter( (text) => {
text = text.trim();
if (!text.length) // empty input field
{
this.setState({
list: {
company: [],
country: [],
state: [],
suburb: [],
street: []
}
});
}
return text.length > 0;
})
.map(response => ({
id: target.id.replace("_input", ""),
term: target.value
}))
)
.debounceTime(200)
.switchMap(r => this.search_type(r.term, r.id))
.subscribe(
/* some code */
)
Would it be alright if i just stuck to a single observable or should I have an observable per input?
In my opinion, it depends on the situation.
Lets say we have two inputs firstName, lastName . I want to be able to search in any of the fields and so if you enter 'john' in firstName or 'john' in lastname it results in same result and rightfully so.
If you want different result , then you can convert your query adding source of input too . That way first queryparam would be {firstnameQuery: 'john'} and second one {lastnameQuery: 'john'} since these two are different there wont be any issue.
If each input has different search trigger , then there is no point in clubbing them together.

Categories