VueJS 3 equivalent of JS Select() function - javascript

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.

Related

Use EmailJS with custom React components correctly

I am trying to implement in a portfolio a functional form contact. I used to use smtpjs or AWS Lambda with a serverless function but this time I am trying to use EmailJS. I achieve to send an email to my account properly when the form is filled but the message does not show the email of the user and the text the user introduced and I do not know why exactly. Here it is my code:
export const Contact = () => {
const email = useFormInput('');
const message = useFormInput('');
const [sending, setSending] = useState(false);
const [complete, setComplete] = useState(false);
const initDelay = tokens.base.durationS;
const form = useRef()
const sendEmail = (e) => {
e.preventDefault();
emailjs.sendForm('ID', 'KEY', form.current, 'SECRET')
.then(alert("Message Sent! I'll reply you ASAP!"));
e.target.reset()
}
return (
<Section className={styles.contact}>
<Meta
title="Contact"
description="Send me a message if you're interested in discussing a project or if you just want to say hi"
/>
<Transition unmount in={!complete} timeout={1600}>
{(visible, status) => (
<form ref={form} onSubmit={sendEmail} className={styles.form}>
<Heading
className={styles.title}
data-status={status}
level={3}
as="h1"
style={getDelay(tokens.base.durationXS, initDelay, 0.3)}
>
<DecoderText
text="Keep in Touch!"
start={status !== 'exited'}
delay={300} />
</Heading>
<Divider
className={styles.divider}
data-status={status}
style={getDelay(tokens.base.durationXS, initDelay, 0.4)} />
<Input
name="mail"
required
className={styles.input}
data-status={status}
style={getDelay(tokens.base.durationXS, initDelay)}
autoComplete="email"
label="Your Email"
type="email"
maxLength={512}
{...email} />
<Input
name="body"
required
multiline
className={styles.input}
data-status={status}
style={getDelay(tokens.base.durationS, initDelay)}
autoComplete="off"
label="Message"
type="email"
maxLength={4096}
{...message} />
<Button
className={styles.button}
data-status={status}
data-sending={sending}
style={getDelay(tokens.base.durationM, initDelay)}
disabled={sending}
loading={sending}
loadingText="Sending..."
icon="send"
type="submit"
>
Send message
</Button>
</form>
)}
</Transition>
<Footer className={styles.footer} />
</Section>
);
};
Everything seems right. However the email that is received lacks the user's text input or email address. You must check that the name properties of the email and message inputs correspond to the keys used in the emailjs.sendForm method in order to make it work.
Hence, in the input components, modify the "name" attributes. Like that:
< Input
name = "from_email"
required
className = {
styles.input
}
data - status = {
status
}
style = {
getDelay(tokens.base.durationXS, initDelay)
}
autoComplete = "email"
label = "Your Email"
type = "email"
maxLength = {
512
} { ...email
}
/>
<
Input
name = "message"
required
multiline
className = {
styles.input
}
data - status = {
status
}
style = {
getDelay(tokens.base.durationS, initDelay)
}
autoComplete = "off"
label = "Message"
type = "email"
maxLength = {
4096
} { ...message
}
/>

How to integrate react-intl-tel-input

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}
/>

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.

Warning: Failed prop type: Invalid prop `initialValues` supplied to `Form(AddComment)`

My application has dynamic routes (dynamic route param), in which it contains the redux form.In order to distinguish the form data, I need to post redux form data along with the react route param.
I have passed the react route param as props from the parent component to the child component having the redux form i.e, initial values in props have the param value.I want to initialize the route param to the input field with hidden type.
import React from 'react';
import { Field, reduxForm,propTypes } from 'redux-form';
import submit from '../actions/commentActions'
import connect from 'react-redux';
const validate = values => {
const errors = {}
if (!values.email) {
errors.email = 'Required'
} else if (!/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
errors.email = 'Invalid email address'
}
if (!values.message) {
errors.message = 'Required !!'
}else if (values.message.length > 15) {
errors.message = 'Must be 15 characters or less'
}
return errors
}
const renderField = ({
input,
label,
type,
meta: { touched, error, warning }
}) => (
<div>
<div>
<input {...input} placeholder={label} type={type} className="form-control" />
{touched &&
((error && <span className="text-danger">{error}</span>) )}
</div>
</div>
)
const renderTextAreaField = ({
input,
label,
type,
meta: { touched, error, warning }
}) => (
<div>
<div>
<textarea {...input} rows="3" placeholder={label}
className="form-control shareThought mt-1"></textarea>
{touched &&
((error && <span className="text-danger">{error}</span>) )}
</div>
</div>
)
const AddComment = props => {
const { error,handleSubmit, pristine, reset, submitting,initialValues } = props;
// console.log(initialValues); prints route param i.e honda
// console.log(props);
return (
<div className="leaveComment pb-2">
<form onSubmit={handleSubmit(submit)}>
<Field
name="email"
component={renderField}
type="email"
label="Email Id"
placeholder="Enter Email"
/>
<Field name="message"
component={renderTextAreaField}
label="Share Your thought"
type="text"
/>
<Field name="modelname"
type="text"
component="input"
value={initialValues}
hidden
/>
<span className="text-danger">{error && <span>{error}</span>}</span>
<div className="row mx-0" >
<button type="submit" className="btn btn-sm btn-info btn-block mt-2" disabled={pristine || submitting}>Leave a comment</button>
</div>
</form>
</div>
);
};
export default reduxForm({
form: 'addcommentmsg',
validate
})(AddComment);
I solved this issue by passing initialValues with key-value
let initialValues = {
initialValues: {
modelname: this.props.pageId
}
};
Therefore you dont have to define the initialValues either in input field or props.
I also could make it work only this way:
const mapStateToProps = state => {
return {
initialValues: {
status: state.profile.userStatus
}
}
}
And input has such value:
value={props.initialValues}

Categories

Resources