REACT this.refs doesn't worked - javascript

Please check this code :
I have a ref attribute in my render template and I would like to play with him for some actions, but for test I just console.log of him but he didn't worked
If you see on my code the focusTextInputmethod, I made a simply console.log of ref value.
export default class Form extends Component {
constructor() {
super();
this._createBounds();
}
_createBounds() {
['focusTextInput']
.forEach((fn) => this[fn] = this[fn].bind(this));
}
static _getSkills() {
return [
{_id: 1, text: 'HTML'},
{_id: 2, text: 'CSS'},
{_id: 3, text: 'JavaScript'},
{_id: 4, text: 'PHP'},
{_id: 5, text: 'MYSQL'}
];
}
_renderSkills() {
return Form._getSkills().map((skills) => (
<Skills key={skills._id} content={skills.text}/>
));
}
/* THIS FUNCTION IS CALL WHEN ONCLICK IF FIRED */
focusTextInput() {
let val = this.refs.newText.value;
console.log(val)
}
/* END */
render() {
return (
<div className="header-form">
<h2 className="header-form-title">Hello, please type informations about you</h2>
<form className="form-container" action="#">
<div className="form-field">
<Input ref="newText" type='text' placeholder="Votre nom"/>
</div>
<div className="form-field">
<Input type='text' placeholder="Votre prénom"/>
</div>
<div className="form-field">
<Input type='text' placeholder="Votre âge"/>
</div>
<div className="form-field">
<Input type='text' placeholder="Votre email"/>
</div>
<div className="form-field">
<select className="form-field-select">
{this._renderSkills()}
</select>
</div>
<div className="form-field submit">
<Input onClick={this.focusTextInput} type='submit' value="Envoyer"/>
</div>
</form>
</div>
)
}
}

Related

Problem transfer list Localite to Add User in a selectBox

Good morning all,
Here I am starting in vue.js and I get stuck on a point that does not seem complicated.
Indeed, I try to pass my list of localities, in my adduser component. So that when creating the user he has to select localities.
But impossible to pass the list to him yet I know that it is necessary to use the props but I can not.
Can you help me ?
Thank you
Component Add user :
<template>
<div class="submitform">
<div v-if="!submitted">
<div class="form-group">
<label for="nom">Nom</label>
<input type="text" class="form-control" id="nom" required v-model="utilisateur.nom" name="nom">
</div>
<div class="form-group">
<label for="prenom">Prenom</label>
<input type="text" class="form-control" id="prenom" required v-model="utilisateur.prenom" name="prenom">
</div>
<div class="form-group">
<label for="profession">Profession</label>
<input type="text" class="form-control" id="profession" required v-model="utilisateur.profession" name="profession">
</div>
<div class="form-group">
<label for="adresse">Adresse</label>
<input type="text" class="form-control" id="adresse" required v-model="utilisateur.adresse" name="adresse">
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="text" class="form-control" id="email" required v-model="utilisateur.email" name="email">
</div>
<div class="form-group">
<label for="login">Login</label>
<input type="text" class="form-control" id="login" required v-model="utilisateur.login" name="login">
</div>
<div class="form-group">
<label for="mobile">Mobile</label>
<input type="text" class="form-control" id="mobile" required v-model="utilisateur.mobile" name="mobile">
</div>
<div class="form-group">
<label for="password">password</label>
<input type="text" class="form-control" id="password" required v-model="utilisateur.password" name="password">
</div>
<!--<div>
<ul>
<li v-for="(localite, index) in localites" :key="index">
{{localite.ville}}
</li>
</ul>
</div>-->
<!--<div>
<select>
<option v-for="(localite, index) in localites" :key="index">
{{localite.ville}}
</option>
</select>
</div>-->
<button v-on:click="saveUtilisateur" class="btn btn-success">Submit</button>
</div>
<div v-else>
<h4>You submitted successfully!</h4>
<button class="btn btn-success" v-on:click="newUtilisateur">Add</button>
</div>
</div>
</template>
<script>
import http from "../http-common";
import Localite from "../components/LocalitesList.vue"
export default {
name: "add-utilisateur",
data()
{
return {
utilisateur: {
id: 0,
nom:"",
prenom:"",
profession:"",
adresse:"",
email:"",
login:"",
mobile:"",
password:"",
actif: 0,
localite: 0
},
Localite: [],
submitted: false
};
},
components:
{
'localite': Localite
},
methods:
{
/* eslint-disable no-console */
saveUtilisateur() {
var data = {
nom: this.utilisateur.nom,
prenom: this.utilisateur.prenom,
profession: this.utilisateur.profession,
adresse: this.utilisateur.adresse,
email: this.utilisateur.email,
login: this.utilisateur.login,
mobile: this.utilisateur.mobile,
password: this.utilisateur.password,
localite: this.utilisateur.localite
};
http
.post("/utilisateur", data)
.then(response => {
this.utilisateur.id = response.data.id;
console.log(response.data);
})
.catch(e => {
console.log(e);
});
this.submitted = true;
},
/* retrieveLocalites() {
http
.get("/localites")
.then(response => {
this.localites = response.data; // JSON are parsed automatically.
console.log(response.data);
})
.catch(e => {
console.log(e);
});
},
refreshList() {
this.retrieveLocalites();
}
/* eslint-enable no-console */
},
/*mounted() {
this.retrieveLocalites();
}*/
/* eslint-enable no-console */
};
</script>
<style>
.submitform {
max-width: 300px;
margin: auto;
}
</style>
Component Localite:
<template>
<div v-if="this.localite">
<h4>Localite</h4>
<div>
<label>CP: </label> {{this.localite.cp}}
</div>
<div>
<label>Ville: </label> {{this.localite.ville}}
</div>
<span class="button is-small btn-danger" v-on:click="deleteLocalite()">Delete</span>
</div>
<div v-else>
<br/>
<p>Please click on a Localite...</p>
</div>
</template>
<script>
import http from "../http-common";
export default
{
name: "localite",
props: ["localite"],
methods:
{
/* eslint-disable no-console */
deleteLocalite() {
http
.delete("/localite/" + this.localite.id)
.then(response => {
console.log(response.data);
this.$emit("refreshData");
this.$router.push('/localite');
})
.catch(e => {
console.log(e);
});
}
/* eslint-enable no-console */
}
};
</script>
Thanks
Props are used to pass data down in the component hierarchy. If you want to get data from an API and pass it to several components I would suggest getting the list of Localite's in a parent component and then pass it via props. A rule of thumb is to have more logic in parent components and less logic in child components.
Example:
<template>
<div>
<localite :localite="listOfLocalites" />
</div>
</template>
Then you can in your localite component get the the prop via props: ["localite"]

React js TypeError: Cannot read property 'state' of undefined [duplicate]

This question already has answers here:
Value of this in React event handler
(3 answers)
Closed 2 years ago.
I'm getting this error TypeError: Cannot read property 'state' of undefined whenever I type in the form and click submit the error occur in const createAppointment , I want to display in the console then the error occurred
Can't find a similar issue for someone else over the internet.
here is the code:
export default class createAppointment extends Component {
constructor(props){
super(props);
this.onChangeUser = this.onChangeUser.bind(this);
this.onChangeName = this.onChangeName.bind(this);
this.onChangeSpecialty = this.onChangeSpecialty.bind(this);
this.onChangePhoneNumber = this.onChangePhoneNumber.bind(this);
this.onChangeReason = this.onChangeReason.bind(this);
this.onChangeEmail = this.onChangeEmail.bind(this);
this.onChangeDate = this.onChangeDate.bind(this);
this.state={
userName:'',
name:'',
specialty: '',
phoneNumber: Number,
reason: '' ,
email:'',
date: new Date(),
users: []
}
}
componentDidMount(){
this.setState({
users:['test user'],
userName:'test user'
})
}
onChangeUser(a){
this.setState({
userName: a.target.value
});
}
onChangeName(a){
this.setState({
name: a.target.value
});
}
onChangeSpecialty(a){
this.setState({
specialty: a.target.value
});
}
onChangePhoneNumber(a){
this.setState({
phoneNumber: a.target.value
});
}
onChangeReason(a){
this.setState({
reason: a.target.value
});
}
onChangeEmail(a){
this.setState({
email: a.target.value
});
}
onChangeDate(date){
this.setState({
date: date
});
}
onSubmit(a){
// will prevent usual submit and will submit what we want
a.preventDefault();
**//here are the errors**
const appoinrment = {
userName: this.state.userName,
name: this.state.name,
specialty: this.state.specialty,
phoneNumber: this.state.phoneNumber,
reason: this.state.reason,
email: this.state.email,
date: this.state.date
}
console.log(appoinrment)
window.location = '/';
}
render(){
return(
// start form
<div>
<h3>Book an appoinrment</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>Username: </label>
<select ref="userInput"
required
className="form-control"
value={this.state.userName}
onChange={this.onChangeUser}>
{
this.state.users.map(function(user) {
return <option
key={user}
value={user}>{user}
</option>;
})
}
</select>
</div>
<div className="form-group">
<label>Name: </label>
<input type="text"
required
className="form-control"
value={this.state.name}
onChange={this.onChangeName}
/>
</div>
<div className="form-group">
<label>Specialty: </label>
<select required
className="form-control"
value={this.state.specialty}
onChange={this.onChangeSpecialty}>
<option value="Orthopedics">Orthopedics</option>
<option value="Vascular">Vascular</option>
<option value="Cardiothoracic">Cardiothoracic</option>
<option value="Reconstructive">Reconstructive</option>
<option value="Oncology">Oncology</option>
<option value="Neurosurgery">Neurosurgery</option>
<option value="UrologySurgery">Urology surgery</option>
<option value="GeneralSurgery">General surgery</option>
<option value="PediatricSurgery">Pediatric surgery</option>
</select>
</div>
<div className="form-group">
<label>Phone Number: </label>
<input type="number"
required
className="form-control"
value={this.state.phoneNumber}
onChange={this.onChangePhoneNumber}
/>
</div>
<div className="form-group">
<label>Date </label>
<div>
<DatePicker
selected={this.state.date}
onChange={this.onChangeDate}
/>
</div>
</div>
<div className="form-group">
<label>Email </label>
<input
type="text"
className="form-control"
value={this.state.email}
onChange={this.onChangeEmail}
/>
</div>
<div className="form-group">
<label>Reason for visiting </label>
<textarea rows="4" cols="50" className="form-control" value={this.state.reason} onChange={this.onChangeReason}>
</textarea>
</div>
<br/>
<div className="form-group">
<input type="submit" value="Book appointment now!" className="btn btn-primary" />
<input type="reset" value="Reset" className="btn btn-primary reset"/>
</div>
</form>
</div>
// end form
)
}
}
You hav not done binding for your onSubmit inside your constructor. So the this inside onSubmit method does not refer to the class instance. and hence the error.
Just bind onSubmit
constructor(props){
super(props);
this.onChangeUser = this.onChangeUser.bind(this);
this.onChangeName = this.onChangeName.bind(this);
this.onChangeSpecialty = this.onChangeSpecialty.bind(this);
this.onChangePhoneNumber = this.onChangePhoneNumber.bind(this);
this.onChangeReason = this.onChangeReason.bind(this);
this.onChangeEmail = this.onChangeEmail.bind(this);
this.onChangeDate = this.onChangeDate.bind(this);
this.onSubmit = this.onSubmit.bind(this); //<------ here

how to set value form input vue js from json

please have a problem here. I want to display the value from the input form: name and position. but the data is in the form of json.
{"id":5,"name":"the name","pos":"the position"}
This is template html vue js
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
Edit <b>{{name}}</b>
</div>
<div class="card-body">
<form #submit="edit()" method="post" onclick="return false">
<div class="form-group">
<label for="">Name</label>
<input v-model="input.nameInput" type="text" value="?" autocomplete="off" class="form-control">
</div>
<div class="form-group">
<label for="">Position</label>
<input v-model="input.posInput" value="?" type="text" autocomplete="off" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Edit</button>
</form>
</div>
</div>
</div>
</div>
</div>
</template>
And this is java script of template file vue js
<script>
export default {
data(){
return{
name:'',
pos:'',
input:{
nameInput:'',
posInput:''
}
}
},
methods:{
getEmploye(){
axios.get('/employes_api/'+this.$route.params.id).then(response => {
this.name = response.data.name;
this.pos = response.data.pos;
});
},
edit(){
axios.put('/employes_api/'+this.$route.params.id, {
name: this.name,
pos: this.position,
}).then(response => {
this.$route.employe;
});
}
},
mounted(){
this.getEmploye();
}
}
</script>
Thanks for your help.
As described in your question, if the data received is
{"id":5,"name":"the name","pos":"the position"}
then you getEmploye method should be :
getEmploye(){
axios.get('/employes_api/'+this.$route.params.id).then(response => {
this.name = response.name;
this.pos = response.pos;
});
On element’s value, you may use the following to display data you have received from the api:
value=“{{name}}”
That means you are getting the value from name data.
Also, to test if that works, you may assign first a dummy data/value to name.
You don't need to make two separate variables one for the inputs and the other for the display, just keep the same variable for both, it will be automatically updated on the display and in the inputs while the user is typing, that's the beauty of Vue.
So instead of
data(){
return{
name:'',
pos:'',
input:{
nameInput:'',
posInput:''
}
}
},
Just keep
data(){
return{
name:'',
pos:''
}
},
For the template inputs use :
<input v-model="name" type="text" autocomplete="off" class="form-control">
...
<input v-model="pos" type="text" autocomplete="off" class="form-control">
The overall result should look like this :
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
Edit <b>{{name}}</b>
</div>
<div class="card-body">
<form #submit="edit()" method="post">
<div class="form-group">
<label for="">Name</label>
<input v-model="name" type="text" autocomplete="off" class="form-control">
</div>
<div class="form-group">
<label for="">Position</label>
<input v-model="position" type="text" autocomplete="off" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Edit</button>
</form>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data(){
return{
name:'',
pos:''
}
},
methods:{
getEmploye(){
axios.get('/employes_api/'+this.$route.params.id).then(response => {
this.name = response.data.name;
this.pos = response.data.pos;
});
},
edit(){
axios.put('/employes_api/'+this.$route.params.id, {
name: this.name,
pos: this.pos,
}).then(response => {
this.$route.employe;
});
}
},
created(){
this.getEmploye();
}
}
Ps : Didn't test the code, if there is any error just let me know
Use :value=“name”, e.g <input :value="name"/>.

Duplicate the input in the form React

I have react app.
And some form with input, and I want add button and function, when we click we can add new input in our form.
But I don't know? how I can make it. In native js, I can use create element and appendchild in parent block with some class or id. But in react ((
render() {
return (
<div>
<h1>Form</h1>
<form onSubmit = { this.onSubmit } action="/form" method="post">
<div>
<input type="text" value={this.state.first} name="first" autoFocus="autoFocus" onChange={ this.handleInputChange } />
<input type="text" value={this.state.second} name="second" onChange={ this.handleInputChange } />
</div>
<button onClick={this.handleDouble}>Double</button>
<button>Submit</button>
</form>
</div>
);
}
handleDouble(e) {
e.preventDefault();
}
You need to shape your data to produce the result you want in React.
For example, if I were trying to produce the two inputs you have here, my state would look something like this:
this.state = {
inputs: [{
name: 'first',
autoFocus: true,
type: 'text',
value: '1'
}, {
name: 'second',
autoFocus: false,
type: 'text',
value: '2'
}]
};
Then in my render() function, I would do something like this:
render() {
return (
<div>
<h1>Form</h1>
<form onSubmit = { this.onSubmit } action="/form" method="post">
<div>
{
this.state.inputs.map((input) => (
<input type={input.type} value={input.value} name={input.name} autoFocus={input.autoFocus} onChange={this.handleInputOnChange} />
);
}
</div>
<button onClick={this.handleDouble}>Double</button>
<button>Submit</button>
</form>
</div>
);
}
This would produce 1 input for each index of this.state.inputs.

[Vue warn]: Error in nextTick: "TypeError: Cannot read property 'key' of undefined"

I am fairly new to Vue (and using Vue components in particular), and I can't figure out what i'm doing wrong here. Essentially I have a signup wizard (using vue-good-wizard) which if the user never clicks the back button works fine, but if at some point they click back I get the error message described in the title. I think it has something to do with the following template being rendered a second time:
<template>
<div class="playerSelectionBox">
<table style="width:100%">
<tr v-for="i in 10" track-by="$index">
<td>Row: {{i}}</td>
<td><player-entry-box></player-entry-box></td>
</tr>
</table>
</div>
</template>
Here is the code for the template from the player-entry-box component:
<template>
<div class="PlayerEntryBox">
<input class="numberBox" type="text" #blur="sendData" v-model="number" placeholder="#">
<input class="nameBox" type="text" #blur="sendData" v-model="playerName" placeholder="Player Name"><br>
</div>
</template>
My best guess is that something is happening when the code is rendered where the player-entry-box components inside of the v-for have something which conflicts with the others, but it works as expected the first time it is rendered. Is there something here I am doing wrong?
Any advice or insights into what I am missing would be great, thanks!
Other information:
All of the components are currently registered globally in the main.js file.
Here is the code for the wizard:
<div id="TeamWizard" v-if="isCreatingTeam" style="padding-top=100px;">
<vue-good-wizard
:steps="teamSteps"
:onNext="nextClickedTeam"
:onBack="backClickedTeam">
<div slot="teamPage1">
<label class="myLabel">Team Name:</label>
<input type="text" v-model="teamName" placeholder="Team Name"><br>
<br>
<label class="myLabel">Sport:</label>
<br>
<select-sport :initialSport="tkdSport" style="display: inline-block;" #sportWasSelected="tkdSport=$event"></select-sport>
<h1></h1>
</div>
<div slot="teamPage2">
<h4>Add Players</h4>
<h1></h1>
<player-selection-box></player-selection-box>
</div>
<div slot="teamPage3">
<h4>Step 3</h4>
<label class="myLabel">Team ID:</label>
<input type="text" v-model="teamID" placeholder="Team ID"><br>
<br>
<label class="myLabel">Team Token:</label>
<input type="text" v-model="teamToken" placeholder="Team Token"><br>
<br>
</div>
</vue-good-wizard>
</div>
Here is where I called this.$nextTick():
mounted () {
this.$nextTick(() => {
this.loggedInUser = firebase.auth().currentUser;
});
}
The following is from the main component :
<template>
<div class="hello">
<h1>{{ tkdSport }}</h1>
<div id="mainPage" v-if="!(isCreatingTeam || isCreatingPlayer)">
<div id="mySidenav" class="sidenav">
×
<img src="../assets/images/testUser.png" width="100px" height="100px">
About
Services
Clients
Contact
<div style="scroll">
<div v-for="i in 50">
<div style="margin=10px; color=red;"><p>Test {{ i }}</p></div>
</div>
</div>
</div>
<h1>{{ loggedInUser.email }}</h1>
<button #click="logout">Logout</button>
<button #click="openNav">Open Nav</button>
<br>
<br>
<br>
<br>
<br>
<button #click="showTeam">New Team Account</button>
<br>
<br>
<br>
<button #click="showPlayer">New Player Account</button>
</div>
<div v-else>
<div id="createTeam" v-if="isCreatingTeam">
<h1>TEAM</h1>
<br>
</div>
<div id="createPlayer" v-if="isCreatingPlayer">
<h1>PLAYER</h1>
</div>
<div id="PlayerWizard" v-if="isCreatingPlayer" style="padding-top=100px;">
<div>
<vue-good-wizard
:steps="playerSteps"
:onNext="nextClickedPlayer"
:onBack="backClickedPlayer">
<div slot="playerPage1">
<label class="myLabel">Team Name:</label>
<input type="text" v-model="teamName" placeholder="Team Name"><br>
<br>
<label class="myLabel">Sport:</label>
<br>
<select-sport :initialSport="tkdSport" style="display: inline-block;" #sportWasSelected="tkdSport=$event"></select-sport>
<h1></h1>
</div>
<div slot="playerPage2">
<h4>Add Players</h4>
<h1>Player Selection will go here</h1>
</div>
</vue-good-wizard>
</div>
</div>
<div id="TeamWizard" v-if="isCreatingTeam" style="padding-top=100px;">
<vue-good-wizard
:steps="teamSteps"
:onNext="nextClickedTeam"
:onBack="backClickedTeam">
<div slot="teamPage1">
<label class="myLabel">Team Name:</label>
<input type="text" v-model="teamName" placeholder="Team Name"><br>
<br>
<label class="myLabel">Sport:</label>
<br>
<select-sport :initialSport="tkdSport" style="display: inline-block;" #sportWasSelected="tkdSport=$event"></select-sport>
<h1></h1>
</div>
<div slot="teamPage2">
<h4>Add Players</h4>
<h1></h1>
<player-selection-box></player-selection-box>
</div>
<div slot="teamPage3">
<h4>Step 3</h4>
<label class="myLabel">Team ID:</label>
<input type="text" v-model="teamID" placeholder="Team ID"><br>
<br>
<label class="myLabel">Team Token:</label>
<input type="text" v-model="teamToken" placeholder="Team Token"><br>
<br>
</div>
</vue-good-wizard>
</div>
</div>
</div>
</template>
<script>
import firebase from 'firebase';
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App',
loggedInUser: '',
teamName: '',
teamToken: '',
teamID: '',
playerName: '',
tkdSport: 'basketball',
isCreatingPlayer: false,
isCreatingTeam: false,
playerSteps: [
{
label: 'Name and Sport',
slot: 'playerPage1',
},
{
label: 'Link (OPTIONAL)',
slot: 'playerPage2',
}
],
teamSteps: [
{
label: 'Name and Sport',
slot: 'teamPage1',
},
{
label: 'Add Players',
slot: 'teamPage2',
},
{
label: 'Setup Linking (OPTIONAL)',
slot: 'teamPage3',
}
]
}
},
mounted () {
this.$nextTick(() => {
this.loggedInUser = firebase.auth().currentUser;
});
},
methods: {
logout: function() {
firebase.auth().signOut().then(() => {
this.$router.replace('login')
})
},
openNav: function() {
document.getElementById("mySidenav").style.width = "250px";
},
closeNav: function() {
document.getElementById("mySidenav").style.width = "0";
},
showTeam: function() {
this.isCreatingTeam = true
this.isCreatingPlayer = false
},
hideCreating: function() {
this.isCreatingTeam = false
this.isCreatingPlayer = false
},
showPlayer: function() {
this.isCreatingPlayer = true
this.isCreatingTeam = false
},
onComplete: function() {
alert('Yay. Done!');
},
nextClickedPlayer(currentPage) {
console.log('next clicked', currentPage)
if(currentPage==1){
this.hideCreating()
}
return true; //return false if you want to prevent moving to next page
},
backClickedPlayer(currentPage) {
console.log('back clicked', currentPage);
return true; //return false if you want to prevent moving to previous page
},
nextClickedTeam(currentPage) {
console.log('next clicked', currentPage)
if(currentPage==2){
this.hideCreating()
}
return true; //return false if you want to prevent moving to next page
},
backClickedTeam(currentPage) {
console.log('back clicked', currentPage);
return true; //return false if you want to prevent moving to previous page
}
}
}
</script>
The user logs in from a separate Login Component, and then gets routed to this component, I just need to have access to the user object within this component.
Here is the stack trace:
Error stack trace

Categories

Resources