How to integrate react-intl-tel-input - javascript

Hello I am new in ReactJS and I have to implement react-intl-tel-input for taking phone number from all over the world but while integration I was facing some issues. When I write this code:
<IntlTelInput
containerClassName="intl-tel-input"
inputClassName="form-control"
name="mobile"
placeholder="Enter Your Number"
input
type="tel"
value={this.state.phoneNumber}
onChange={this.handleChange}
I was not able to access this.handleChange but When I write my normal code like this
<input
type="tel"
id="phone"
name="mobile"
placeholder="Enter Your Number"
required
onChange={this.handleChange}
/>
I was able to access this.handleChange and my code work perfectly but I was unable to take country code. If anyone know the solution please help. I was getting this error
TypeError: Cannot read properties of null (reading 'phoneNumber')
This is my complete code.
Login.js
import React from 'react'
import firebase from './firebase'
import 'firebase/auth';
import "./App.css";
import { getDatabase, ref, child, get } from "firebase/database";
import IntlTelInput from 'react-intl-tel-input';
import 'react-intl-tel-input/dist/main.css';
class Login extends React.Component {
handleChange = (e) => {
console.log (e)
const { name, value } = e.target
this.setState({
[name]: value
})
console.log (value)
this.setState({ phoneNumber: value }, () => {
console.log(this.state.phoneNumber);
});
}
configureCaptcha = () =>{
window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button', {
'size': 'invisible',
'callback': (response) => {
// reCAPTCHA solved, allow signInWithPhoneNumber.
this.onSignInSubmit();
console.log("Recaptca varified")
},
// defaultCountry: "IN"
}
);
}
onSignInSubmit = (e) => {
e.preventDefault()
this.configureCaptcha()
const phoneNumber = this.state.mobile
console.log(phoneNumber)
const appVerifier = window.recaptchaVerifier;
const dbRef = ref(getDatabase());
get(child(dbRef, `Users/${phoneNumber}`)).then((snapshot) => {
if (snapshot.exists()) {
firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier)
.then((confirmationResult) => {
window.confirmationResult = confirmationResult;
alert('An OTP has been sent to your registered mobile number')
localStorage.setItem("Phone_No", phoneNumber)
console.log(localStorage.getItem('Phone_No'));
}).catch((error) => {
console.error(error);
alert("Oops! Some error occured. Please try again.")
});
}
else {
alert('Sorry, this mobile number is not registered with us. Please use your registered mobile number.');
}
})
}
onSubmitOTP = (e) => {
e.preventDefault()
const code = this.state.otp
console.log(code)
window.confirmationResult.confirm(code).then((result) => {
// User signed in successfully.
const Users = result.user;
console.log(JSON.stringify(Users))
this.props.history.push("/home");
}).catch((error) => {
alert("You have entered wrong code")
});
}
render() {
return (
<div className="Main-header">
<img src="./55k-logo.png" alt="Company Logo" style={{ height: "80px", width: "200px" }} />
<br />
<div>
<h2>Login Form</h2>
<p>Limtless Water. From Unlimited Air.</p>
<form onSubmit={this.onSignInSubmit}>
<div id="sign-in-button"></div>
{/* <PhoneInput */}
<label>Mobile Number</label> <br />
{/* for="phoneNumber" */}
<IntlTelInput
containerClassName="intl-tel-input"
inputClassName="form-control"
name="mobile" placeholder="Enter Your Number"
input type="tel" value={this.state.phoneNumber}
onChange={this.handleChange}
/>
{/* <input type="tel" id="phone" name="mobile" placeholder="Enter Your Number" required onChange={this.handleChange} /> */}
<div className="buttons">
<button type="submit">Submit</button>
</div>
</form>
</div>
<div>
<form onSubmit={this.onSubmitOTP}>
<label >Code</label> <br />
{/* for="code" */}
<input type="number" name="otp" placeholder="Enter The 6 Digit OTP" required onChange={this.handleChange} />
<div className="buttons" >
<button type="submit">Submit</button>
</div>
</form>
</div>
</div>
)
}
}
export default Login;

Issues
There is no defined initial state so this is why accessing this.state.phoneNumber is throwing an error.
The IntlTelInput component takes an onPhoneNumberChange handler that takes a validation status, current value, and country details as arguments instead of an onChange handler taking an onChange event object.
Solution
Provide valid initial state for the component. In React class components state is simply a class property, it just needs to be defined.
state = {};
Create a new change handler specifically for the IntlTelInput component.
handlePhoneChange = (status, phoneNumber, country) => {
this.setState({ phoneNumber });
};
Switch from onChange to onPhoneNumberChange event handler.
<IntlTelInput
containerClassName="intl-tel-input"
inputClassName="form-control"
name="mobile"
placeholder="Enter Your Number"
input
type="tel"
value={this.state.phoneNumber}
onPhoneNumberChange={this.handlePhoneChange}
/>

Related

VueJS 3 equivalent of JS Select() function

I want my code to select the password textbox when it does not matched with the confirm password textbox after clicking the register button. Click here to see the image of the wanted output
Is there an equivalent way of doing select() function in VueJS? The textbox that I want to be selected is in ref state.
I've tried value.select() but it showed on console that it is not a function.
Just a disclaimer that I'm still learning about VueJS and Quasar. Been googling and reading documents and still no luck.
Here's the code below.
<template>
<div class="window-height window-width row justify-center items-center">
<q-card class="my-card">
<q-card-section class="col-10" style="width: 800px">
<q-input v-model="nameTextBox" label="Name" />
<q-input ref="email" v-model="emailTextBox" type="email" label="Email" />
<q-input ref="password" v-model="passTextBox" type="password" label="Password" />
<q-input v-model="conPassTextBox" type="password" label="Confirm Password" />
<br />
<br />
<q-btn color="secondary" class="q-mr-lg"
#click="registerProfile(emailTextBox, nameTextBox, passTextBox, conPassTextBox)">
Register
</q-btn>
<q-btn :to="'/'">Cancel</q-btn>
</q-card-section>
</q-card>
</div>
</template>
<script setup>
import { ref, getCurrentInstance } from 'vue'
const { $feathers } = getCurrentInstance().appContext.config.globalProperties
const nameTextBox = ref('')
const emailTextBox = ref('')
const passTextBox = ref('')
const conPassTextBox = ref('')
const checkConfirmPassword = (pass, conPass) => {
// console.log(pass, conPass)
if (pass === conPass) {
return true
} else {
return false
}
}
const registerProfile = (emailText, nameText, passText, conPassText) => {
console.log(emailText)
$feathers.service('/users').find({
query: {
email: emailText
}
})
.then(() => {
// email found
alert('Email has already been registered. Please use anothere email.')
// ref.email.select()
})
.catch(() => {
console.log(checkConfirmPassword(passText, conPassText))
if (checkConfirmPassword(passText, conPassText) === false) {
alert('Password is the same. Please retype it again.')
passTextBox.value.select() // -> This syntax does not work.
} else {
console.log('Passed')
$feathers.service('/users').create({
email: emailText,
name: nameText,
password: passText
})
}
})
}
</script>
You are calling the select method on the value of your password textbox (on a string!). You need to define your ref instances and use them. In order to define refs first, define ref names:
const password = ref(null)
const email = ref(null)
then in the HTML part use the exact names for the ref prop:
<q-input ref="email" v-model="emailTextBox" type="email" label="Email" />
<q-input ref="password" v-model="passTextBox" type="password" label="Password" />
and finally, use these variables to reference elements.
password.value.select()
// or
email.value.select()
Full code would be:
<template>
<div class="window-height window-width row justify-center items-center">
<q-card class="my-card">
<q-card-section class="col-10" style="width: 800px">
<q-input v-model="nameTextBox" label="Name" />
<q-input ref="email" v-model="emailTextBox" type="email" label="Email" />
<q-input ref="password" v-model="passTextBox" type="password" label="Password" />
<q-input v-model="conPassTextBox" type="password" label="Confirm Password" />
<br />
<br />
<q-btn color="secondary" class="q-mr-lg"
#click="registerProfile(emailTextBox, nameTextBox, passTextBox, conPassTextBox)">
Register
</q-btn>
<q-btn :to="'/'">Cancel</q-btn>
</q-card-section>
</q-card>
</div>
</template>
<script setup>
import { ref, getCurrentInstance } from 'vue'
const { $feathers } = getCurrentInstance().appContext.config.globalProperties
const nameTextBox = ref('')
const emailTextBox = ref('')
const passTextBox = ref('')
const conPassTextBox = ref('')
// Define refs to components.
// Use this variable name as the one you set in the ref prop for the component.
const password = ref(null)
const email = ref(null)
const checkConfirmPassword = (pass, conPass) => {
// console.log(pass, conPass)
if (pass === conPass) {
return true
} else {
return false
}
}
const registerProfile = (emailText, nameText, passText, conPassText) => {
console.log(emailText)
$feathers.service('/users').find({
query: {
email: emailText
}
})
.then(() => {
// email found
alert('Email has already been registered. Please use anothere email.')
email.value.select() // this works either
})
.catch(() => {
console.log(checkConfirmPassword(passText, conPassText))
if (checkConfirmPassword(passText, conPassText) === false) {
alert('Password is the same. Please retype it again.')
password.value.select() // -> This works know.
} else {
console.log('Passed')
$feathers.service('/users').create({
email: emailText,
name: nameText,
password: passText
})
}
})
}
Please look at this link to figure out how refs work in Vue3 and composition API.

how to change an UseStatus targeting an axios post reponse?

I'm back once more with something that has been breaking my head today.
so I'm making a contact form is almost done except for an animation I want to include that comes in three steps.
1- prompting the user to contact
2-making the waiting for the user-friendlier with a small loader
3-showing either everything went good and the form was sent or something went wrong
so my idea to accomplish this was to use three different icons/loaders and position all of them on top of each other and make them visible or hide them as necessary using UseState.
for now, I can hide the first icon(from step one) as soon as the submit button is clicked, but I haven't been able to make appear the loader or as the API completes the response the last icon
wondering if I should access it any other way?
import styled from "styled-components";
import { RiMailSendFill,FcApproval } from 'react-icons/all';
import '../../Style/styleComponents/Style.css';
import {sendMessage} from '../../Actions/msgAction';
import { useDispatch, useSelector } from 'react-redux';
import { useForm } from "../../Hook/useForm";
const ContactForm = () => {
const dispatch = useDispatch();
const initFormValues =
{
nombre : "nico ",
email : "sasjaja#asdsa ",
telefono : "asda ",
empresa : "dasd",
mensaje : "dasdas",
date: "s"
}
const[formValues, handleInputChange, reset] = useForm(initFormValues);
const{nombre, email, telefono, empresa, mensaje} = formValues
//loader submit buttons
const[mail, setMail]= useState(true);
const[loading, setLoading]= useState(false);
const[approved, setApproved]= useState(false);
const handleSendMsg = ( event ) =>
{
event.preventDefault();
dispatch( sendMessage( formValues ) )
.then( ( result ) =>
{
if( result )
{
console.log(initFormValues);
//closeModal();
console.log('dat')
};
setLoading(true);
});
reset();
}
const showE =()=> {
if (mail) {
setMail(false)
setLoading(true)
console.log("pressed submit");
}
}
const showL=()=>{
if (loading) {
setLoading(false)
console.log("sending email ");
}
}
return (
<Container>
<Left>
<h1>Tráenos tus desafíos</h1>
</Left>
<Right>
<form onSubmit={ handleSendMsg }>
<Label>
<Linput>
<Name>
<label htmlFor="name">Nombre:</label>
<input type="text" id="name" required name="nombre" value={ nombre } onChange={ handleInputChange } />
</Name>
<Tel>
<label htmlFor="name">Telefono:</label>
<input type="text" id="phone" required name="telefono" value={ telefono } onChange={ handleInputChange } />
</Tel>
<Company>
<label htmlFor="company">Empresa:</label>
<input type="text" id="company" name="empresa" value={ empresa} onChange={ handleInputChange }/>
</Company>
</Linput>
<Rinput>
<Email>
<label htmlFor="email">E-mail:</label>
<input type="email" id="email" required name="email" value={ email } onChange={ handleInputChange }/>
</Email>
<Msg>
<label htmlFor="message">Mensaje:</label>
<textarea id="message" required name="mensaje" rows="8" cols="50" value={ mensaje } className="bigger" onChange={ handleInputChange }/>
</Msg>
</Rinput>
</Label>
<Button>
<Send>
<button type="Submit" id ="submit" onClick={showE, showL}>Enviar</button>
</Send>
<Sent>
<RiMailSendFill id="mail" className={ mail ? 'svg': "svg active"}/>
<Loader className={ loading ? 'spin': "spin active"}>
<div class="spin"></div>
</Loader>
{/* <FcApproval id= "approve" className={ approved ? 'approve': "approve active"}/> */}
</Sent>
</Button>
</form>
</Right>
</Container>
);
};
export default ContactForm;
thanks, yall always saving me!
There are ways to make states work with each other easiest way is like this.
1-useStates for each of the
elements you want to be able to switch states to.
const [mail, setMail] = useState(true);
const [approved, setApproved] = useState(false);
2 Main function with smaller functions,
for each one to change accordingly.
function showL( ){
setMail(false);
if(!mail){
return setApproved(true);
}
}
//hide mailIcon / show approve
function showA( ){
setApproved(true);
if(approved){
return setMail(false);
}
}
add an event listener to the specific
the element you will work with to trigger the changes,
here you pass the two functions like this.
<Button>
<Send>
<button type="Submit" id="submit" onClick={() => {showL(); showA();}}>
Enviar
</button>
</Send>
TERNARY EXPRESION if true, render element and false null
<Sent>
<EMail>
{mail ? <RiMailSendFill/> : null}
</EMail>
<Loader>
{approved ? <FcApproval/>: null}
</Loader>
</Sent>
</Button>```

Why onSubmit is not working with React ES6 syntax?

I am a newbie in React world. Actually, I come across a situation. When I use modern syntax, I am not getting things done. But, with bind.this method everything is working smoothly. Below is my code. Can you please find out mistakes. It giver error like "cant find state of undefined". Thank you.
import React, { Component } from 'react';
class Login extends Component {
state = {
email: '',
password: '',
}
handleChange = e => {
this.setState({ [e.target.name]: e.target.value });
};
signin(e) {
e.preventDefault();
const { email, password } = this.state;
if (email === 'xyz#gmail.com' && password === '123456') {
console.log('logged in')
}
}
render() {
return(
<div className='login'>
<div className='login-div'>
<form
onSubmit={this.signin}>
<fieldset>
<h2 className='heading'>Sign into your account</h2>
<label htmlFor="email">
<input
type="email"
name="email"
placeholder="email"
value={this.state.email}
onChange={this.handleChange}
/>
</label>
<label htmlFor="password">
<input
type="password"
name="password"
placeholder="password"
value={this.state.password}
onChange={this.handleChange}
/>
</label>
<button type="submit">Sign In!</button>
</fieldset>
</form>
</div>
</div>
)
}
}
export default Login;
can you change your function to this
signin = (e) => {
e.preventDefault();
const { email, password } = this.state;
if (email === 'xyz#gmail.com' && password === '123456') {
console.log('logged in')
}
}
Just to explain what's going on :
It's because inside signin function, this refers to the context of the execution (the event handler) but not to your React component.
You can specify which this the signin function will be bound to using bind method.
Add this line at the begining of the class :
this.signin = this.signin.bind(this);
Note : You can avoid binding all your functions by writing them using arrow function syntax.

React Form: How to add error message that disappear if the input was typed in

I already built the form in React and it shows the input fields in red borders that'll change to regular borders once someone types it in. I used this example from this React form article link So everything is working except I wanted to add the error message under the input field that displays "Please fill in the blank field" that will disappear once someone starts typing in the field. How do I do this?
Here's my code in Form.js:
import React, { Component } from 'react';
import FormField from './FormFieldBox';
function validate(name, isin) {
// true means invalid, so our conditions got reversed
return {
name: name.length === 0,
isin: isin.length === 0
};
}
export default class PopupForm extends Component {
constructor(props) {
super(props)
this.state = {
name: '',
isin: '',
country: '',
errormessage: ''
}
}
updateInput = (e) =>{
this.setState({[e.target.name]: e.target.value})
}
closePopupSubmit = (e) => {
if (!this.canBeSubmitted()) {
e.preventDefault();
}
let security = { //1.gather security data from form submit
name: this.state.name,
isin: this.state.isin,
country: this.state.country
}
this.props.submitPopup(security); //2.closePopup function, add security data
}
canBeSubmitted() {
const errors = validate(this.state.name, this.state.isin);
const isDisabled = Object.keys(errors).some(x => errors[x]);
return !isDisabled;
}
cancelPopupSubmit = (e) => {
e.preventDefault()
this.props.cancelPopup();
}
render() {
const errors = validate(this.state.name, this.state.isin);
const isDisabled = Object.keys(errors).some(x => errors[x]);
return (
<div className='popup'>
<div className='popup-inner'>
<form onSubmit={this.closePopupSubmit}>
<FormField onChange={this.updateInput} className={errors.name ? "input error" : "input"} label="Name" type="text" name="name" value={this.state.name} />
<FormField onChange={this.updateInput} className={errors.isin ? "input error" : "input"} label="ISIN" type="text" name="isin" value={this.state.isin} />
<FormField onChange={this.updateInput} label="Country" type="text" name="country" value={this.state.country} />
<button type="button" onClick={this.cancelPopupSubmit} className="button">Cancel</button>
<button type="submit" className="button" disabled={isDisabled}>Submit</button>
</form>
</div>
</div>
)
}
}
And my component FormField.js
import React from "react";
const FormBox = props => {
return (
<div className="field">
<label className="label">{props.label}</label>
<div className="control">
<input onChange={props.onChange}
className={props.className}
type={props.type}
name={props.name}
value={props.value}
placeholder={props.placeholder} />
{/* {props.errormessage} */}
</div>
</div>
)
}
export default FormBox;
const FormBox = props => {
return (
<div className="field">
<label className="label">{props.label}</label>
<div className="control">
<input onChange={props.onChange}
className={props.className}
type={props.type}
name={props.name}
value={props.value}
placeholder={props.placeholder} />
</div>
{Boolean(props.value.length) || (
<div className="err-msg">
Please fill in the blank field
</div>
)}
</div>
)
}
There are two ways you can achieve this
First : oninvalid attribute in HTML5 and calling a custom function on that.
Second : along with each element name object in state have a length attribute. In validation function you can check for the length and throw a custom error that you want to display.

Unable to type into React input field

I am unable to type any input into my input field. I am using React, and have already set a handleChange and a handleSubmit function. The first two input fields, for 'name' and 'email', take input just fine. But for 'favoriteCity', it doesn't seem to work.
I am wondering if it is due to a MongoDB error that I am getting.
class UserPage extends Component {
state = {
user: [],
newUser: {
name: '',
email: '',
favoriteCity: ''
}
}
getAllUsers = () => {
axios.get('/api/users')
.then(res => {
this.setState({ user: res.data })
})
}
componentDidMount() {
this.getAllUsers()
}
handleChange = event => {
const newUser = { ...this.state.newUser };
newUser[event.target.name] = event.target.value;
this.setState({ newUser: newUser});
}
handleSubmit = event => {
event.preventDefault()
axios.post('/api/users', this.state.newUser)
.then(res => {
this.props.history.push(`/users/${res.data._id}`)
})
}
render() {
return (
<div>
{ /* This shows a list of All Users */ }
{this.state.user.map(user => (
<div key={user._id}>
<Link to={`/users/${user._id}`}>{user.name}</Link>
</div>
))}
<h1>New User Page</h1>
<form onSubmit={this.handleSubmit}>
<label>Name: </label>
<input
type="text"
name="name"
placeholder="Name?"
value={this.state.newUser.name}
onChange={this.handleChange}
/>
<label>Email: </label>
<input
type="text"
name="email"
placeholder="Email?"
value={this.state.newUser.email}
onChange={this.handleChange}
/>
<label>Favorite City: </label>
<input
type="text"
name="city"
placeholder="Favorite City?"
value={this.state.newUser.favoriteCity}
onChange={this.handleChange}
/>
<Button
type="submit"
value="Submit"
variant="contained"
color="primary"
>
Create User
</Button>
</form>
</div>
);
}
}
export default UserPage;
Please help.
Weird that email works fine, from what you posted your handleChange function is only updating the name on the newUser.
What you should see is what you type in all the inputs appear in the name input.
To fix this, you should probably have separate change handlers for each input:
handleNameChange
handleEmailChange
...
You should also consider storing name, email etc.. at the root of your state instead of nesting them in an object, that'll simplify the handler functions code.

Categories

Resources