While using
vee-validate#4.4.5
vue#3.1.4
I encountered following problem:
<Form #submit="onSubmit" :validation-schema="schema">
<div class="mb-3">
<label for="edit-email" class="form-label">E-mail</label>
<Field
id="edit-email"
class="form-control"
name="email"
type="text"
:validateOnInput="true"
/>
<ErrorMessage class="invalid-feedback" name="email" />
</div>
<button #click="checkEmail" type="button">Check e-mail address</button>
<!-- non-important part of the form -->
</Form>
I'd like to manually validate <Field /> when the button is clicked (error message should appear) and then I want to use the field's value to perform another action.
I wrote following code:
import { useFieldValue } from 'vee-validate';
// setup
setup() {
const schema = object({
email: string().required().email().label("e-mail"),
});
function verifyEmail(v) {
const emailValue = useFieldValue("email");
console.log(emailValue); // empty ComputedRefImpl
}
return {
schema,
verifyEmail,
};
},
}
And this doesn't work.
emailValue is returned as ComputedRefImpl with an undefined value.
I guess I'm mixing Components & Composition API flavors of vee-validate. But still don't know how to resolve this issue.
Created sandbox with this: https://codesandbox.io/s/vue3-vee-validate-form-field-forked-xqtdg?file=/src/App.vue
Any help will be much appreciated!
According to vee-validate's author:
https://github.com/logaretm/vee-validate/issues/3371#issuecomment-872969383
the useFieldValue only works as a child of a useForm or useField.
So it doesn't work when <Field /> component is used.
Related
I have react app with with complex component layout with multiple forms.
I know that placing one form inside another is not allowed. But I have a component which renders a form and must be placed inside my form. To prevent forms be rendered one inside another I use react portal.
But when I try to submit form rendered with portal, first form is also submitted that is unexpected. Looks like I miss something important.
How to prevent first form submit when submitting the second?
Thank you
Simplified example is here
import { createPortal } from "react-dom";
const Portal = ({ children, elm }) => createPortal(children, elm);
export default function App() {
return (
<div className="App">
<form
onSubmit={(e) => {
e.preventDefault();
alert("submit 1");
}}
>
First form <input type="text" value="1" />
<Portal elm={document.querySelector("body")}>
Second form{" "}
<form
onSubmit={(e) => {
e.preventDefault();
alert("submit 2");
}}
>
<input type="text" value="2" />
<input type="submit" value="submit 2" />
</form>
</Portal>
</form>
</div>
);
}
I had the same problem, as #EisaRezaei said in the first comment, using e.stopPropagation() in the form inside the portal, and submit type buttons, everything worked fine
I'm building a restaurant website and am doing the reservations page. I'm using my own custom form and using EmailJs to send the data from the reservations inputs to my email. When I fill out the form it gives me an error the 3rd parameter of the sendform function from emailjs is expected to be the html form element or the style selector of a form. My code below.
import diningroom from "../images/diningroom.jpg";
import { init, sendForm } from 'emailjs-com';
init('DlhTOjdE7Pqq5UJHA');
function Reservations() {
const initialState = {
lastname: "",
guests: "",
phone: "",
date: "",
time: "",
};
const [reservation, setReservation] = useState(initialState);
const onSubmit = (e) => {
e.preventDefault();
sendForm('Carmellos_Reservation','template_9oxce3q','#lastname','#amount','#guests','#phone','#day','#time')
.then(function(response) {
console.log('SUCCESS!', response.status, response.text);
setReservation(...reservation,initialState)
}, function(error) {
console.log('FAILED...', error);
});
}
const onChange = (e) => {
setReservation({
...reservation,
[e.target.name]: e.target.value,
});
};
return (
<>
<div className="reservation-container">
<h2 className="reservations">Reservations</h2>
<p className="parag">
For Reservations Please call 434 977 5200 or Please fill out the form
Below.
</p>
<div
className="container"
style={{ backgroundImage: `url(${diningroom})` }}
c
>
<p className="paragraph">
Carmello's is open for dinner only. Our hours are Tuesday-Saturday
from 5pm to 9:30pm and on Sundays 5 til 9pm
</p>
<p className="paragraph">
We can accomadate a reservation of 2 persons to large parties. The
restaurant is available for wedding rehearsals and private parties.
Please contact Stella Hedges regarding large parties. Reservations
are strongly urged on the Weekends and we do accept customers as
walkins. For any reservation greater than 10 please call the
restuarant directly.
</p>
<div className="form-div">
<form className="reservation-form" onSubmit={onSubmit}>
<label htmlFor="lastname">LastName</label>
<input
type="text"
name="lastname"
value={reservation.lastname}
id="lastname"
onChange={onChange}
placeholder="Last Name"
required
/>
<label htmlFor="amount"> Amount of Guests</label>
<input
type="number"
name="amount"
value={reservation.amount}
id="amount"
onChange={onChange}
placeholder="Amount of Guests"
required
/>
<label htmlFor="phone">Phone Number</label>
<input
type="text"
name="phone"
value={reservation.phone}
id="phone"
onChange={onChange}
placeholder="Phone Number"
required
/>
<label htmlFor="date" > Day</label>
<input
type="date"
name="date"
value={reservation.day}
id="date"
onChange={onChange}
placeholder="Date"
required
/>
<label htmlFor="time" >Time</label>
<input
type="time"
name="time"
value={reservation.time}
id="time"
onChange={onChange}
min="17:00"
max="21:00"
placeholder="time"
required
/>
<div className="div-button">
<button type="submit" name="submit">
Make Reservation
</button>
</div>
</form>
</div>
</div>
</div>
</>
);
}
export default Reservations;
SendForm=()=> {
3th- form.current
}
return(
<form onSubmit={sendForm} ref={form}
form.current get info from "form" and put in template params
of corse that we need create a ref to pass the function argument
The third parameter after 'template_9oxce3q' is te one tat should be of type HTMLFormElement ence maybe in this case e.target as HTMLFormElement
You need to use react hook 'useRef()'.
https://www.emailjs.com/docs/examples/reactjs/ this should be all you need
Like #Psikai said, you edit your onSubmit function as written below:
e.preventDefault();
sendForm('Carmellos_Reservation','template_9oxce3q',e.target, 'DlhTOjdE7Pqq5UJHA' )
.then(function(response) {
console.log('SUCCESS!', response.status, response.text);
setReservation(...reservation,initialState)
}, function(error) {
console.log('FAILED...', error);
});
}
This will work as it worked for me. Note I assumed 'DlhTOjdE7Pqq5UJHA' is your PUBLIC_KEY. By the way, I didn't add the init 'DlhTOjdE7Pqq5UJHA' when I wrote mine probably because I had the emailjs <script> tag already placed inside my index.html and the script tag contains my PUBLIC_KEY
I'm learning reactjs and I have a problem with the validation in forms
so I want to have a condition if the user don't enter his name a message 'empty field' appear
else alert hello 'his name' appears
My code
import React ,{Component} from 'react';
class Formular extends Component {
constructor(props) {
super(props);
this.state={
nom:'',
prenom:'',
email:'',
password:'',
error:false,
NameErr:''
}
}
handleValidation() {
if (this.state.nom =='')
{ this.state.error=true
this.state.NameErr='empty field'
//console.log( this.state.NameErr)
return(
this.state.NameErr
)
}
}
handleClick(event){
event.preventDefault()
let error = this.handleValidation()
if (!error)
{
alert('hello '+ this.state.nom)
}
}
render() {
/* console.log('nom',this.state.nom)
console.log('prenom',this.state.prenom) */
return (
<div >
<div className="form__group field">
<input type="input" className="form__field"
placeholder="Name" name="name" id='name'
required size='100' value={this.state.nom}
onChange={(event)=>this.setState({nom:event.target.value})} />
<label for="name" className="form__label">Name</label>
</div>
<div className='alert'> {this.state.NameErr} </div>
export default Formular
You must not change the state by force
like this
this.state.NameErr='empty field'
this.state.error=true
You need to use setState
like this example
this.setState({NameErr:'empty field',error:true})
then you can in render method
{ this.state.error && <div className='alert'> {this.state.NameErr}</div>}
Thus the element will only be displayed if there is an error
Mutation of state isn't correct, always mutate state using setState()
this.setState({NameErr:'empty field', error: true})
jsx
{this.state.error && <div className='alert'> {this.state.NameErr} </div>}
First, you should wrap your input in form tag instead simply div.
Next use event onSubmit on your form to trigger submission of the form.
Create un method to check if your value is not empty, then do what you want
render () {
return <form onSubmit={handleClick}>
<div className="form__group field">
<input
id='name' name="name" type="text"
className="form__field"
size='100' required
placeholder="Name" value={this.state.nom}
onChange={(event)=>this.setState({nom:event.target.value})}
/>
<label for="name" className="form__label">Name</label>
</div>;
<div className='alert'> {this.state.NameErr} </div>
</form>;
}
NT: type attribute of input should be "text" and not "input"
EDIT: Like said other guys, change also your changing state.
I'm using Aurelia and Typescript to build a web page. I have a simple login form and I'd like to validate the user email and password.
I am using Aurelia validation and by default it validates the content of my input each time it changes, which can be annoying. (ex: getting an error message saying that the email is not valid when you're not even done typing it). So I'd like to do the validation onBlur instead (when the focus on the input is lost) and when the user clicks on the Login button.
Here's my code:
login.html
<template>
<section>
<div class="container col-lg-12">
<div class="col-md-4 col-md-offset-4 centered">
<h2 t="signin_sign_in"></h2>
<form role="form" submit.delegate="login()" validate.bind="validation">
<br if.bind="errors" />
<div if.bind="errors" repeat.for="error of errors" class="alert alert-danger">
<h4 repeat.for="message of error">${message}</h4>
</div>
<div class="form-group">
<label class="control-label" t="signin_email_address"></label>
<input type="text" class="form-control" value.bind="email">
</div>
<div class="form-group">
<label class="control-label" t="signin_password"></label>
<input type="password" class="form-control" value.bind="password">
</div>
<button type="submit" class="btn btn-primary" t="signin_sign_in"></button>
</form>
</div>
</div>
</section>
</template>
login.ts
#autoinject()
export class Login {
email: string;
password: string;
router: Router;
application: ApplicationState;
accountService: AccountService;
errors;
validation;
i18n: I18N;
constructor(router: Router, application: ApplicationState, accountService: AccountService, validation: Validation, i18n: I18N) {
this.router = router;
this.application = application;
this.accountService = accountService;
this.i18n = i18n;
this.errors = [];
this.validation = validation.on(this)
.ensure('email')
.isNotEmpty()
.isEmail()
.ensure('password')
.isNotEmpty()
.hasLengthBetween(8, 100);
}
navigateToHome(): void {
this.router.navigate("/welcome");
}
login(): void {
var __this = this;
this.validation.validate()
.then(() => this.accountService.signin(this.email, this.password, this.rememberMe)
.then(result => {
// Do stuff
})
.catch(error => {
// Handle error
}
}));
}
}
My first thought was to add
& updateTrigger:'blur':'paste'
to my binding in the HTML, but it doesn't work. The binding is updated correctly when focus is lost but the validation stops working. There's no error in the Chrome debug console either.
Any idea on how to do this? Is is possible at all?
There's different binding behaviours you can use to tell when the validation should trigger. You can read more about them in the Aurelia docs on validation.
From the docs;
The validate binding behavior obeys the associated controller's
validateTrigger (blur, change, changeOrBlur, manual). If you'd like to
use a different validateTrigger in a particular binding use one of the
following binding behaviors in place of & validate:
& validateOnBlur: the DOM blur event triggers validation.
& validateOnChange: data entry that changes the model triggers validation.
& validateOnChangeOrBlur: DOM blur or data entry triggers validation.
& validateManually: the binding is not validated
automatically when the associated element is blurred or changed by the
user.
I recently encountered this exact use case and I solved it using Aurelia's built in debounce feature.
<input type="text" class="form-control" id="email" placeholder="Email"
value.bind="email & validateOnChangeOrBlur & debounce:600 ">
600ms is an arbitrary value, but you can always play around with it as needed.
In meteor, I current am using the default login field. However, I would like to have the user create a unique user ID upon creating an account. I could hardcode this in, but I was wondering if there was a way to do this by editing the loginButton field somehow.
Would anybody know how to add extra fields in general that the user signing up would be forced to fill out? Such as name, username, etc.?
The loginButtons helper is meant to be an easy, drop-in helper for prototyping. For customization, you need to create your own custom login/signup forms. This is actually pretty easy with the documented Accounts API. Here's a simple example of custom login/signup forms:
<template name="signupForm">
<form id="signup-form">
<h2>Sign Up</h2>
<label for="signup-username">Username</label>
<input type="text" id="signup-username" placeholder="Username" />
<label for="signup-password">Password</label>
<input type="password" id="signup-password" placeholder="Password" />
<label for="signup-name">Full Name</label>
<input type="text" id="signup-name" placeholder="Full Name" />
<button type="submit">Sign Up</button>
</form>
</template>
<template name="loginForm">
<form id="login-form">
<h2>Log In</h2>
<label for="login-username">Username</label>
<input type="text" id="login-username" placeholder="Username" />
<label for="login-password">Password</label>
<input type="password" id="login-password" placeholder="Password" />
<button type="submit">Log In</button>
</form>
</template>
<template name="logoutForm">
<form id="logout-form">
<button type="submit">Log Out</button>
</form>
</template>
Template.signupForm.events({
"submit #signup-form": function(event, template) {
event.preventDefault();
Accounts.createUser({
username: template.find("#signup-username").value,
password: template.find("#signup-password").value,
profile: {
name: template.find("#signup-name").value
// Other required field values can go here
}
}, function(error) {
if (error) {
// Display the user creation error to the user however you want
}
});
}
});
Template.loginForm.events({
"submit #login-form": function(event, template) {
event.preventDefault();
Meteor.loginWithPassword(
template.find("#login-username").value,
template.find("#login-password").value,
function(error) {
if (error) {
// Display the login error to the user however you want
}
}
);
}
});
Template.logoutForm.events({
"submit #logout-form": function(event, template) {
event.preventDefault();
Meteor.logout(function(error) {
if (error) {
// Display the logout error to the user however you want
}
});
}
});
You can use the Accounts.validateNewUser() and Accounts.onCreateUser() methods to validate the user fields and perform further customization on the user objects, respectively. For example, in your onCreateUser callback, you can change the user's _id field to whatever you want before returning the user object to be inserted into the DB.
Note that this example doesn't include the code for when the user forgot their password and wants to reset it. You can use the Accounts.forgotPassword and Accounts.resetPassword methods for that.
If you are having email as a field in your 'users' collection and you enters email id in the place of username it makes login into the system as we are not using accounts-ui here. So we can not be able to use accounts-ui config facility.