I need to add predefined - '#domain' when user type on the form? - reactjs

My form only allows user to type their email without #domainname. for e.g. tomdickharyy#email.com the bit from #email.com is predefined. My handle change function will concatenate "#email.com" at the end. Once the form is submitted on my state i set {email : ''} and the form is empty as expected.
The problem is when I type a new email the form will concatenate #email.com for every letter typed. I don't know how to fix this problem, any help would be great.
handleChange({ target: {name, value} }){
const domainEmail = '#email.com';
name === "email" ? this.setState({ [name]: value + domainEmail}) : this.setState({ [name]: value});
} ```

You have two options:
1) Remove domainEmail and append it again on each change. Some very rude code:
handleChange({ target: {name, value} }) {
const domainEmail = '#email.com';
name === 'email'
? this.setState({ [name]: value.replace(domainEmail, '') + domainEmail })
: this.setState({ [name]: value });
}
2) Move out domainEmail to be purely representational, next to the input field. This is how many UI frameworks do it, see for example Bootstrap: https://getbootstrap.com/docs/4.3/components/input-group/
Then when you submit, remember to append the domain. I recommend this approach, it makes it much less fragile, removing many edge cases. It isalso very clear for the user that they should not type their email.

Related

Placeholder disappear after user interact with inputs

I'm facing this issue in my react app:
The application is used for manage storage of a shop, there is one page in which user can add a new obj ( with name , quantity etc.) and there is a page used for UPDATE the obj.
In the "update" page I display the same form of the "new" page but with the current value as placeholder, so that the user can see what value is actually set and change just one or few of the values and leave the others as they are.
The problem is that when the user interact with the input ( like start typing then cancel ) the placeholder disappear and the value is updated as empty.
Now I would like that if user leaves the field empty after interacting with it, the placeholder should appear again, and I would like to make that if the input is left empty then it would not be updated or should be updated with the previous value.
I'm using antd library, so all inputs and stuff are taken from there.
const [data, setData]=useState({
numero: 0,
date: '' ,
nome: "",
...
//get current data
useEffect(() =>get(child(dbRef,'test/' + searchParams.get('id'))).then((snapshot)=>{
if(snapshot.exists()){
setData(snapshot.val())
console.log('[CONVERTED-DATA]',snapshot.val(), '[stato]', data);
}else{
console.log('[GET] NO data available')
}
}).catch((error)=>{
console.log(error)
})
, [])
//now "data" is populated with the values from db
function onChange(e) {
const value = e.target.value ;
setData({
...data,
[e.target.name]: value
});
console.log("[CHANGE-VALUE]", value);
console.log("[event]", e);
}
<Form>
<Form.Item
name="nome"
label="Nome"
rules={[ { type: "string", min: 3 }]}
initialValue={data.nome}
>
<Input
placeholder={data.nome}
value={data.nome}
name="nome"
onChange={onChange}
className="update-input"
/>
</Form.Item>
... more inputs

react address lookup issue with changing final input value

I am building an address lookup functionality for an app, and my previous 2 questions have thus far, been unable to garner an answer. I am on the last step, and need to figure this out, so I turn to you stack overflow.
I start with an input, a button and a target input:
<input type='text' name='postcode-lookup' onChange={this.postcodeChange} />
<button onClick={this.searchPostcode}>Search</button>
<input type='text' name='target-for-data' />
Easy enough. Now for the functions attached to both of those elements:
postcodeChange = {e} => {
this.setState({'postcode': e.target.value});
}
searchPostcode = () => {
this.setState({'visible': true});
if(this.state.postcode.length . 0){
Axios.get('postcode look up api here')
.then(response => {
this.setState({'response': response.data});
})
}
}
Ok here, we have 3 state items: postcode, which we will set to an empty string '', visible, which is initially set to true, and response, which is an empty array, that we then populate with the response data of address objects.
My next step, was to display those addresses, so inside the render, I set a const that maps over the response array like so:
const result = this.state.response.map((item) => {
if(this.state.visible === true){
return(
<p key={item.id} onClick={addressClick}>{item.address1Field}</p>
)
}else {
}
})
Ok, so when we click the button, it will return a p tag filled with address data from the array. This also has a function, which is where my problem lies.
Inside of this function I set the visible state item to false, so that the addresses disappear. Easy enough.
But how do I then take the address that I clicked on, and populate it into the original input we started with?
I have tried many things, from setting the state in addressClick, targeting the innerHTML, e.target.value, e.target.innerHTML, and so on and so on for hours.
Any takers? Ideas?

Validate form inputs with conditional format checks

I have a function in React I am using to check the validation state of a form on submit.
The form contains 2 types of inputs.
Text and Number
However so I may have some control over the length of numbers in the field, the number input prop is set as text with a maxLength prop applied.
What I need to now do is validate that when submitting the form, the values in those inputs are indeed numbers.
My state is:
state = {
firstName: '',
lastName: '',
accountNumber: '',
sortCode1: '',
sortCode2: '',
sortCode3: ''
}
I am attempting to check this using the following....
checkValid = state => {
const rgx = new RegExp(/^[0-9]{0,9}$/)
const result = Object.keys(state).every(key => {
if (key.match(/(firstName|lastName|)/)) {
return !!state[key]
}
return rgx.test(state[key])
})
return result
}
What I am trying to achieve is a check if on firstName and lastName to ensure there are values and then a check on all other props to ensure they are numbers and numbers only.
I cannot seem to make this work though as the form either always returns true or always returns false depending on how I amend the code.
As soon as any field is invalid, I would like to simply return false.
Got some small errors with the regex. Below code should work. =) This one will return false as soon as one field is empty or the value isn't a number on the fields where you want a number.
checkValid = state => {
const rgx = new RegExp(/^[0-9]*$/)
const result = Object.keys(state).every(key => {
// If field is empty return false
if (state[key] === '') return false;
// If on firstName or lastName return true as we already know that the field isn’t empty
if (key.match(/^(firstName|lastName)$/)) return true;
// If not firstName or lastName test the field with rgx
return rgx.test(state[key])
})
return result;
}
It looks like you are trying to validate firstName and lastName based on their values simply being truthy and then the subsequent fields based on them being a number?
checkValid = ({ firstName, lastName, ...rest }) => {
const result = !!firstName && !!lastName && Object.keys(rest).every(key => !isNaN(rest[key]))
return result
}
By deconstructing state you can pick off properties and perform validation separately, with less complex code.
If your only concern is that the other fields are in fact a number, isNan should work.

React form validation still adds values

So I have a little bit of form validation going on and I am running into an issue. When I first load the web app up and try adding a value and submitting with my button it doesn't allow me and gives me the error I want to see. However, when I add a value setState occurs and then my value is pushed to UI and I try to add another blank value it works and my conditional logic of checking for an empty string before doesn't not go through what am I doing wrong?
addItem() {
let todo = this.state.input;
let todos = this.state.todos;
let id = this.state.id;
if (this.state.input == '') {
alert("enter a value");
document.getElementById('error').style.color = 'red';
document.getElementById('error').innerHTML = 'Please enter something first';
}
else {
this.setState({
todos: todos.concat(todo),
id: id + 1,
}, () => {
document.getElementById('test').value = '';
})
console.log(this.state.id);
}
}
You are checking this.state.input but no where in that code are you setting the input value on the state.
Try adding this where it makes sense in your application:
this.setState({ input: 'some value' });
Also, I recommend you use the state to define the application UI. So instead of using document.getElementById('error') or document.getElementById('test').value, have the UI reflect what you have in your state.
See here for more info: https://reactjs.org/docs/forms.html
Instead of manipulating the DOM directly:
document.getElementById('test').value = '';
you'll want to use React:
this.setState({ input: '' });
A good ground rule for React is to not manipulate the DOM directly through calls like element.value = value or element.style.color = 'red'. This is what React (& setState) is for. Read more about this on reactjs.org.
Before you look for the solution of your issue, I noticed that you are directly updating the DOM
Examples
document.getElementById('error').style.color = 'red';
document.getElementById('error').innerHTML = 'Please enter something first';
document.getElementById('test').value = '';
Unless you have special use case or dealing with external plugins this isn't recommended, when dealing with React you should update using the virtual DOM. https://www.codecademy.com/articles/react-virtual-dom
Pseudo code sample
constructor(props) {
this.state = {
// retain previous states in here removed for example simplicity
errorString: ''
}
}
addItem() {
let todo = this.state.input;
let todos = this.state.todos;
let id = this.state.id;
if (this.state.input == '') {
alert("enter a value");
this.setState({
errorString: 'Please enter something first'
});
}
else {
this.setState({
todos: todos.concat(todo),
id: id + 1,
input: '',
});
}
}
// notice the "error" and "test" id this could be omitted I just added this for your reference since you mentioned those in your example.
render() {
return (
<div>
{(this.state.errorString !== '') ? <div id="error" style={{color: 'red'}}>{this.state.errorString}</div> : null}
<input id="test" value={this.state.input} />
</div>
}
Every time you invoke setState React will call render with the updated state this is the summary of what is happening but there are lot of things going behind setState including the involvement of Virtual DOM.

How do we partially update a state in react?

I was wondering what is the best way to partially update a state of a component in React/React-Native. Other than the fact that I can make a function which takes the current state and creates a new state and merges the new {key:value} and the previous state. For example:
{
dataStream:[//having data here],
formData: {
'first_name': 'Richard',
'last_name' : 'Barbieri',
}
}
I want to update last_name to another value. When I call
this.setState(formData:{{'last_name':newValue}}), it resets the formData dictionary to just last name: new Value. Is there a way to this efficiently?
I think there are two things you could try:
Spread operator
liks so
this.setState({
formData: {
...this.state.formData,
"last_name" : newValue
}
});
or
Take current state's first_name and reapply it:
like so
this.setState({
formData: {
"first_name": this.state.formData.first_name,
"last_name" : newValue
}
})
I'm not too sure about the first one, but I think the second one should work.
What happens is normal because you reassign the whole forData.
If you want to add something to the existing form data do something like that (there are plenty of other solutions ^^)
this.setState({
formData: Object.assign(this.state.formData, { 'last_name': newValue }
})

Resources