When I am using state variable as a value for the input fields, second input field is not working.
Here is the code:
<input
type="text"
className="form-control"
placeholder="mobileNumber"
onChange={this.handleLoginMobileNumber}
onKeyUp={this.handleLoginMobileNumber}
value={this.state.loginMobileNumber}
/>
<input
type="text"
className="form-control"
placeholder="Passcode"
maxLength="4"
value={this.state.loginPasscode}
/>
<br/>
<button
className="btn btn-large btn-primary medata-login-form-input medata-login-form-submit-button"
onClick={this.submitLogin}>
Log in
</button>
Help me, Thanks.
Issue is, you are using Controlled Component and you forgot to define the onChange method and update the state value with password field, because of that password field is read only.
Check this example:
class App extends React.Component{
constructor(){
super();
this.state = {
loginMobileNumber: '',
loginPasscode: ''
}
}
handleLoginMobileNumber(e){
this.setState({loginMobileNumber: e.target.value})
}
loginPasscode(e){
this.setState({loginPasscode: e.target.password})
}
render(){
return(
<div>
<input
type="text"
className="form-control"
placeholder="mobileNumber"
onChange={this.handleLoginMobileNumber.bind(this)}
value={this.state.loginMobileNumber}
/>
<input
type="password"
className="form-control"
placeholder="Passcode"
maxLength="4"
value={this.state.loginPasscode}
onChange={this.loginPasscode.bind(this)}
/>
</div>
)
}
}
ReactDOM.render(<App/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'/>
Related
I am trying to test a form in Vue, using the forms from the Bootstrap-Vue library.
I have made a an event for the form (submit) and I added a function to this event (addText).
Then I made a method for this function, telling it to log my input data to the console, but when I press the "save" button and go into the console nothing has been logged.
This used to work with Materialize, so I am wondering if the error lies somewhere with the Bootstrap forms.
Any help will be much appreciated.
<template>
<b-container fluid>
<h2>Add or edit content for this section</h2>
<b-form-group #submit="addText">
<div class="fieldHeadline">
<label for="headline">Add headline</label>
<b-form-input type="text" name="headline" v-model="headline"></b-form-input>
</div>
<div class="fieldSecodnaryHeadline">
<label for="secondaryHeadline">Add secondary headline</label>
<b-form-input type="text" name="secondaryHeadline" v-model="secondaryHeadline"></b-form-input>
</div>
<div class="fieldText">
<label for="text">add text</label>
<b-form-input type="text" name="text" v-model="text"></b-form-input>
</div>
<b-button variant="success">Save</b-button>
</b-form-group>
</b-container>
</template>
<script>
export default {
name: 'NewsSectionCreate',
data() {
return {
headline: null,
secondaryHeadline: null,
text: null
}
},
methods: {
addText(){
console.log(this.headline, this.secondaryHeadline, this.text)
}
}
}
</script>
b-form-group is not a form it's layout that structures the label and inputs, in order to submit that inputs you should wrap the b-form-group tags with a b-form component which has #submit event:
<b-form #submit="addText">
<b-form-group >
<div class="fieldHeadline">
<label for="headline">Add headline</label>
<b-form-input type="text" name="headline" v-model="headline"></b-form-input>
</div>
<div class="fieldSecodnaryHeadline">
<label for="secondaryHeadline">Add secondary headline</label>
<b-form-input type="text" name="secondaryHeadline" v-model="secondaryHeadline"></b-form-input>
</div>
<div class="fieldText">
<label for="text">add text</label>
<b-form-input type="text" name="text" v-model="text"></b-form-input>
</div>
<b-button type="submit" variant="success">Save</b-button>
</b-form-group>
</b-form->
don't forget to add type="submit" to the b-button component.
I am writing a react component that holds a form, with radio buttons inside it. I've tried to create onChange() and handleSubmit() functions that would collect the value of the selected button and console log the value of it, but the event object isn't being recognised, and I get this error:
Uncaught TypeError: Cannot read property 'target' of undefined
Why is this happening and what can I do about it now?
Here is my code:
class NoteInput extends React.Component {
constructor(props) {
super(props);
this.state={
selectedValue: ''
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
this.setState({selectedValue: e.target.value})
}
handleSubmit(e) {
e.preventDefault();
console.log(this.state.selectedValue);
}
render() {
return (
<div>
<form onChange={this.handleChange()} >
<input type="radio" id="0" name="location" value={this.props.locations[0]} />
<label htmlFor="choice1">Safa Park</label>
<input type="radio" id="1" name="location" value={this.props.locations[1]} />
<label htmlFor="choice2">Mercato</label>
<input type="radio" id="2" name="location" value={this.props.locations[2]} />
<label htmlFor="choice3">Burj Khalifa</label>
</form>
<input onSubmit={this.handleSubmit()} type="submit" value="Submit" />
</div>
);
}
}
You are calling functions instead of passing them to event handler. So pass the function instead, by removing () like this
onChange={this.handleChange}
onSubmit={this.handleSubmit}
I am starting with angular2. I have a simple template driven form and I can access the data in console. But I am having problem with passing the data. Here is my code.
import {Component} from "angular2/core";
#Component({
selector: 'my-template-driven',
template:`
<h2>Sign-up form</h2>
<form (ngSubmit)="onSubmit(f)" #f="ngForm">
<div>
<label for="email">Mail</label>
<input ngControl="email" type="text" id="email" required #email="ngForm">
<span class="validation-error" *ngIf="!email.valid">Not Valid</span>
</div>
<div>
<label for="password">Password</label>
<input ngControl="password" type="text" id="password" required #password="ngForm">
<span class="validation-error" *ngIf="!password.valid">Not Valid</span>
</div>
<div>
<label for="confirm-password">Confirm Password</label>
<input ngControl="confirm-password" type="text" id="confirm-password" required #passwordConfirm="ngForm">
<span class="validation-error" *ngIf="!passwordConfirm.valid">Not Valid</span>
</div>
<button type="submit" [disabled]="!f.valid || password.value !== passwordConfirm.value">Submit</button>
</form>
<h2>You Submitted</h2>
`
})
export class TemplateDrivenFormComponent {
user: {email: '', password: ''};
onSubmit(form){
//console.log(form);
this.user.email = form.value['email'];
//this.user.password = form.controls['password'].value;
}
}
I am getting this angular2.js:23941 ORIGINAL EXCEPTION: TypeError: Cannot set property 'email' of undefined error constantly. How can I access the data of the form submitted.
You don't declare your local correctly, and you must initialize it when you declare it, or in your constructor maybe
user: any;
constructor() {
this.user = {email: "", password: ""} as any;
}
after : you must provide the type.
Html input must have "ngModel" attribute in it.
Attention: It should work with the new forms API!
Is there a possibility to submit a raw form without any bindings of its elements?
An Example:
<div class="form-mantle">
<form (ngSubmit)="onSubmitForm1(f1.value)" #f1="ngForm">
<input ngControl="name1" name="name1" type="text" required/><br/>
<input ngControl="text1" name="text1" type="text" required/><br/>
<button class="btn btn-primary" [disabled]="!f1.form.valid">Next </button>
</form>
</div>
<pre>
{{ form1 | json }}
</pre>
How should onSubmitForm1() look like, so that I get form1 like below rendered:
{
name1: "Michael Jackson",
text1: "They don't really care about us"
}
I've already preapared a component to copy+paste, for those, who want to help:
import { Component } from '#angular/core';
#Component({
moduleId: module.id,
selector: 'form1',
templateUrl: 'form1.component.html',
styleUrls: ['form1.component.css']
})
export class Form1Component {
form1 : any = {};
constructor() { }
onSubmitForm1 (data?:any) {
// get raw data from form without bindings
this.form1 = data;
console.log("Data", data);
return false;
}
}
Edit: The exact working copy in plnkr (http://plnkr.co/edit/nMPTYLGxgWzzJuD9Be3f?p=preview) does not work within the seed from https://github.com/mgechev/angular2-seed . Maybe it is a version problem ??
Double binding works without errors:
<div class="form-mantle">
<form (ngSubmit)="onSubmitForm1(f1.value)" #f1="ngForm">
<input [(ngModel)]="f1.name1" #name="ngModel" name="name1" type="text" required/><br/>
<input [(ngModel)]="f1.text1" #name="ngModel" name="text1" type="text" required/><br/>
<button class="btn btn-primary" [disabled]="!f1.form.valid">Next </button>
</form>
</div>
<pre>
{{ f1.value | json }}
</pre>
Just call it like so in your ngSubmit:
(ngSubmit)="onSubmitForm1(f1.value)"
To every control you want to submit add the ngControl attribute to set its name:
<input ngControl="name1" name="name1" type="text" required/><br/>
<input ngControl="text1" name="text1" type="text" required/><br/>
Then in your onSubmitForm1:
onSubmitForm1 (data?:any) {
console.log("Data", data);
this.form1 = data;
}
Plunker for example usage
Yeap, for now (rc4) you have only two ways for accepting a data after submit:
1) model-driven strategy (bindings)
2) template-driven strategy (ngControls)
Finaly the following has worked (double bindings :/ ):
<form (ngSubmit)="onSubmitForm()" #s1="ngForm">
<input [(ngModel)]="step1.name1" [ngModelOptions]="{standalone: true}" type="text" required/><br/>
<input [(ngModel)]="step1.text1" [ngModelOptions]="{standalone: true}" type="text" required/><br/>
<button class="btn btn-primary" [disabled]="!s1.form.valid">Next </button>
</form>
I have a simple AddUser component and in the render function I am returning the following html:
<form ref="form" className="users-form" onSubmit={ this.handleAddNew }>
<input ref="username" type="text" name="username" placeholder="username"
value={this.state.username} onChange={function() {}} /><br />
<input ref="email" type="email" name="email" placeholder="email"
value={this.state.email} onChange={function() {}} /><br />
<button type="submit"> Add User </button>
</form>
I am binding the state of username and email to this.state which I am setting to blank in getInitialState like so:
getInitialState() {
return { username: '', email: '' };
}
I am binding state to the form so I can set it to blank after form submission.
The problem with this setup is that the form now renders as readonly.
I cannot get any user input into either text fields. What am I doing wrong?
Your input fields are controlled components, since you are using the value property. This makes the inputs readonly and they will always reflect the value, the variable (in this case, the state variable) holds. You have to explicitly setState onChange since you are setting username field as a state variable.
Read more about it here
onUserNameChange : function(e){
this.setState({username : e.target.value})
},
render: function(){
return ...
<input ref="username" type="text" name="username" placeholder="username"
value={this.state.username} onChange={this.onUserNameChange} /><br />
...
<button type="submit"> Add User </button>
</form>
}
A better way to do this is :
onChange : function(field,e){
this.setState({field: e.target.value});
},
render : function(){
return <form ref="form" className="users-form" onSubmit={ this.handleAddNew }>
<input ref="username" type="text" name="username" placeholder="username"
value={this.state.username} onChange={this.onChange.bind(this,"username")} /><br />
<input ref="email" type="email" name="email" placeholder="email"
value={this.state.email} onChange={this.onChange.bind(this,"email")} /><br />
<button type="submit"> Add User </button>
</form>
}
It looks like you saw the console warning about controlled fields needing an onChange handler and added one just to shut the warning up :)
If you replace your empty onChange handler functions with onChange={this.handleChange} and add this method to your component, it should work:
handleChange(e) {
this.setState({[e.target.name]: e.target.value})
}
(Or for people not using an ES6 transpiler:)
handleChange: function(e) {
var stateChange = {}
stateChange[e.target.name] = e.target.value
this.setState(stateChange)
}
However, if your component is an ES6 class extending React.Component (instead of using React.createClass()), you will also need to ensure the method is bound to the component instance properly, either in render()...
onChange={this.handleChange.bind(this)}
...or in the constructor:
constructor(props) {
super(props)
// ...
this.handleChange = this.handleChange.bind(this)
}