Vuejs having increment numbers in forms - javascript

I have input field to type numbers
<input type="text" class="form-control" id="validationTooltip01" v-model="verse.number" required>
I'd like to increment this number after store it in database.
Example
I enter 1 and save my form, next time i open my form the number be 2 instead of i be needed to type it every time.
Code
data() {
return {
verse: {
number: '',
heading: '',
body: '',
book_id: '',
chapter_id: '',
}
}
},
submit: function(e) {
axios.post('/my_url', this.verse)
.then(res => {
this.isLoading = false;
$('#exampleModal').modal('toggle');
this.getVerses.push( res.data.verse );
this.verse = {
number: this.verse.number, // here
heading: '',
body: '',
book_id: this.verse.book_id,
chapter_id: this.verse.chapter_id,
};
})
.catch(error => {
// handle authentication and validation errors here
this.errors = error.response.data.errors
this.isLoading = false
})
}
I have already tried these but none worked as i wanted,
this.verse = {
number: this.verse.number +=1,
...
and
this.verse = {
number: this.verse.number +1,
...
any idea?

Your this.verse.number type is String, so
this.verse.number + 1 // ''+ 1 = '1'
You should set your default value of verse.number( in data() {} ) to 0 insteed ''. Just change number: '', to number: 0, And it will be
this.verse.number + 1 // 0 + 1 = 1
And next increment will 1 + 1 = 2 etc

Related

PhoneInput value display in data preview in React

I'm trying to display PhoneInput value in a data preview (React) using an event handler handleOnChangePhoneInput. How do I make it work?
Here is the source code.
I want to display the "phone number" value entered by a user in the "data preview" sheet right below the "Submit" button in the demo. For example, when one enters a "first name" value and click on "Submit", the first name is displayed in the data preview but I could not make it work for "phone number" and "data of birth".
Demo
Component
<PhoneInput
name="phoneNumber"
type="text"
country={"us"}
enableAreaCodes={true}
onlyCountries={["us"]}
areaCodes={{ us: ["000"] }}
inputProps={{
name: "phone",
country: "us",
required: true,
autoFocus: true
}}
value={this.state.phone}
onChange={this.handleOnChangePhoneInput}
inputStyle={{
width: "230px",
height: "45px"
}}
/>
Event
handleOnChangePhoneInput = value => {
this.setState({ phone: value }, () => {
return this.state.phone;
});
};
[Thanks! I'm new to React.]
So this is how you would do it , First of all you need to maintain the state of your inputs so you would have to modify the state a bit
state = {
firstName: "",
lastName: "",
phone: "",
emailAddress: "",
eligibleAge: false,
max: new Date(
new Date().getFullYear() - 21,
new Date().getMonth(),
new Date().getDate()
),
min: new Date(
new Date().getFullYear() - 120,
new Date().getMonth(),
new Date().getDate()
),
selectedDate: ""
};
the next thing you want to do is create three additional event listeners one for all the text inputs and one for the checkbox and one for the calender, this could be merged into one but for simplicity let's keep it separate
// Text Inputs
onChange = e => {
console.log(e);
this.setState(
{
...this.state,
[e.fieldProps.name]: e.fieldProps.value
},
() => {
console.log(this.state);
}
);
};
// CheckBox
onCheckBoxChange = e => {
this.setState(
{
...this.state,
eligibleAge: !this.state.eligibleAge
},
() => {
console.log(this.state);
}
);
};
// Calender
onSelect = e => {
var SelectedDate =
e.getDate() + "-" + (e.getMonth() + 1) + "-" + e.getFullYear();
this.setState(
{
...this.state,
selectedDate: SelectedDate
},
() => {
console.log(this.state);
}
);
};
the next thing you want to do is pass the arguments to the function.(since in the demo that you provided if a filed is empty it does not show.so i decided to mimic that by checking if that field is empty)
<Form
onSubmitStart={() =>
this.props.onSubmitStart({
...(this.state.firstName !== "" && {
firstName: this.state.firstName
}),
...(this.state.lastName !== "" && {
lastName: this.state.lastName
}),
...(this.state.emailAddress !== "" && {
emailAddress: this.state.emailAddress
}),
...(this.state.phone !== "" && { phone: this.state.phone }),
selectedDate: this.state.selectedDate,
eligibleAge: this.state.eligibleAge
})
}
>
and in the parent component(index.js) you would just change
handleSubmitStart = ({serialized}) => {
to this:
handleSubmitStart = serialized => {
CodeSandbox : here
your handle function must be something like:
const handleOnChangePhoneInput = value => {
this.setState({ phone: value });
};
and then, if you want to show the value make an onClick function inside the submit button
like:
const handleOnSubmit=()=>{
this.setState({visibleTelephone:true})
}
and in your component you need to add where is going to show the value:
<div>
{this.state.visibleTelephone?this.state.phone:null}
</div>

ReactJS -> problem with 'clearing' input forms

I've got simple form.
Every time I try to fill a form, the rest of the fields clears.
In addition validation errors are displayed below each field instead of just one. How to fix this?
This how it looks before any action: https://i.imgur.com/zjGsNRL.png
And this how it looks after wrong data: https://i.imgur.com/pSh6rFM.png
My constructor:
constructor(props) {
super(props);
this.state = {
title: {
text: ''
},
foods: [{
text: '',
kcal: '',
protein: '',
carbohydrate: '',
fat: ''
}],
};
Handlers and validation f():
handleKcalChange(event, index) {
const foods = this.state.foods.slice();
const value = event.target.value;
foods[index] = {
kcal: value,
...this.validateParam(value)
}
this.setState({
foods: foods
});
}
handleProteinChange(event, index) {
const foods = this.state.foods.slice();
const value = event.target.value;
foods[index] = {
protein: value,
...this.validateParam(value)
}
this.setState({
foods: foods
});
}
validateParam = (paramNumber) => {
if(paramNumber < 0) {
return {
validateStatus: 'error',
errorMsg: 'Number can`t be smaller than 0.'
}
} else if(paramNumber > 1000) {
return {
validateStatus: 'error',
errorMsg: 'Number is too big!'
}
} else {
return {
validateStatus: 'success',
errorMsg: null
}
}
}
One issue may be here in handleKcalEvent
foods[index] = {
kcal: value,
...this.validateParam(value)
}
you aren't changing the kcal of the object at the index, you're changing the object to a new object that just has kcal has a parameter, thereby erasing all of the other information (text, fat, carbs etc.)
try something like
const current = foods[index];
foods[index] = {...current,
kcal: value,
...this.validateParam(value)
}

Ionic/Angular send SMS to multiple numbers from array

I have a project that I want to send an SMS to a list of contacts that I have.
unfortunately, I have no idea how to do this and everything I try just does not seem to work.
I want to iterate through all the numbers in the array and then send an SMS with the IONIC SMS Plugin to these numbers.
Here is the Component that stores that contacts
constructor(private contacts: Contacts, private storage: Storage) {
this.getContact();
}
key = 'contacts';
mContacts = [
{
id: [0],
name: '',
number: ''
},
{
id: [1],
name : [''],
number: ['']
},
{
id: [2],
name : [''],
number: ['']
},
{
id: [3],
name : [''],
number: ['']
},
{
id: [4],
name : [''],
number: ['']
}
];
ngOnInit() {}
pickContact(contactId) {
this.contacts.pickContact().then((contact) => {
this.mContacts[contactId].name = contact.name.givenName;
this.mContacts[contactId].number = contact.phoneNumbers[0].value;
this.saveContacts();
});
}
saveContacts() {
this.storage.set(this.key, JSON.stringify(this.mContacts));
}
getContact() {
this.storage.get(this.key).then((val) => {
console.log('Contact Name: ', val);
if (val != null && val !== undefined) {
this.mContacts = JSON.parse(val);
}
});
}
}
and here is the function that sends the SMS. it starts with getContacts() method, as the Contacts are originally stored with the IONIC storage Plugin
EDIT
I want to retrieve the contents of the the array list from the Contacts Component, however when I call the function sendSMS() it returns a null for the number
sendSMS()
{
this.contactComponent.getContact();
let number = this.contactComponent.mContacts[0][2];
let message = "Hello World";
console.log("number=" + number + ", message= " + message);
//CONFIGURATION
var options = {
replaceLineBreaks: false, // true to replace \n by a new line, false by default
android: {
intent: 'INTENT' // send SMS with the native android SMS messaging
//intent: '' // send SMS without opening any other app
}
};
this.sms.send(number, message, options);
}
Hope this helps someone.
I decided to do this instead to make things simplier.
this.checkSMSPermission();
this.contactComponent.getContact();
const numberOne = this.contactComponent.mContacts[0].number;
const numberTwo = this.contactComponent.mContacts[1].number;
const numbeThree = this.contactComponent.mContacts[2].number;
const numberFour = this.contactComponent.mContacts[3].number;
const numberFive = this.contactComponent.mContacts[4].number;
console.log(numberOne);
// tslint:disable-next-line: max-line-length
const message = this.messageComponent.dangerMessage + ' my location is: lat: ' + this.latitude.toString() + 'lng: ' + this.longitude.toString();
console.log('number=' + numberOne + ', message= ' + message);
// CONFIGURATION
const options = {
replaceLineBreaks: false, // true to replace \n by a new line, false by default
android: {
intent: '' // send SMS with the native android SMS messaging
// intent: '' // send SMS without opening any other app
}
};
this.sms.send(numberOne,numberTwo ,numberThree,numberFour,numberFive, message, options).then(() => {
this.presentAlert('Success', 'message has been sent');
})
.catch(error => {
this.presentAlert('Error', 'Failed: ' + error);
});
}

Getter returning same value as the input value before action finish in Vue

I created a component and a module for a functionality X and I'm using Vuex for state management. The code works for the every first time insertion, but after this the Getter function always returns the same value of the input before the action ends and commit the mutation.
For example:
1 - everything is [0,0,0] and Getter is [0,0,0]. Insert 9 in the first position and the value is inserted.
2 - On the second time, the check if the value inserted is equal of what is on the state returns true, so we had to remove this verification.
By the way, the state continues to be modified without the action commit the changes to mutation, and when we look to the Getter (who retrieves the value from the state) the value inserted is already returned by the Getter.
Someone know how to fix this?
Here is the code
component:
Vue.component('profundidade-cell', {
data: function () {
return {
valorProfundidade: [0, 0, 0],
id: this.face + '-' + this.dente,
ids: [
this.face + '-profundidade-sondagem-' + this.dente + '-1',
this.face + '-profundidade-sondagem-' + this.dente + '-2',
this.face + '-profundidade-sondagem-' + this.dente + '-3'
],
changedId: null,
valorInserido: null,
valorAnt: null,
}
},
props: {
arcada: String,
sextante: String,
dente: String,
face: String,
face_json: String,
max_length: Number,
min_value: Number,
max_value: Number,
},
computed: {
profundidadeSondagem() {
return store.getters['profundidadeSondagem/profundidadeSondagem']({arcada: this.arcada,
sextante: this.sextante, dente: "dente_" + this.dente, face: this.face_json});
},
presente() {
return store.getters.dentePresente({arcada: this.arcada, sextante: this.sextante,
dente: "dente_" + this.dente});
}
},
created: function() {
this.debouncedAlterarProfundidade = _.debounce(this.alterarValorProfundidadeSondagem, 400);
this.$root.$on("vuex-carregado", this.carregar);
},
methods: {
getValue(e) {
this.changedId = e.target.id;
this.valorInserido = e.target.value;
this.debouncedAlterarProfundidade();
},
alterarValorProfundidadeSondagem() {
let modelRefs = {};
let patologia = {
arcada: this.arcada,
sextante: this.sextante,
dente: "dente_" + this.dente,
face: this.face_json,
valor: this.valorProfundidade,
modelRefs: modelRefs,
id: this.changedId,
valorInserido: this.valorInserido,
};
store.dispatch('profundidadeSondagem/MODIFY', patologia).catch(() => {
this.valorProfundidade = this.profundidadeSondagem;
})
},
carregar(){
this.valorProfundidade = this.profundidadeSondagem;
}
},
template: `
<div>
<input type="text" :id=ids[0] v-on:input.prevent="getValue($event)" :maxlength=max_length v-model=valorProfundidade[0] class="periograma-input col l4" v-bind:class="{ 'invisible': !presente }" />
<input type="text" :id=ids[1] v-on:input.prevent="getValue($event)" :maxlength=max_length v-model=valorProfundidade[1] class="periograma-input col l4" v-bind:class="{ 'invisible': !presente }" />
<input type="text" :id=ids[2] v-on:input.prevent="getValue($event)" :maxlength=max_length v-model=valorProfundidade[2] class="periograma-input col l4" v-bind:class="{ 'invisible': !presente }" />
</div>
`
});
module:
const moduleProfundidadeSondagem = {
namespaced: true,
actions: {
MODIFY({commit, dispatch, getters, rootGetters}, obj) {
let patologia = {
face: rootGetters.getNomeFace(obj.face),
dente: rootGetters.getNomeDente(obj.dente),
local: "FACE",
ficha: this.state.idPeriograma,
descricao: obj.valor.toString(),
paciente: this.state.idPaciente,
tipo: 'PROFUNDIDADE_DE_SONDAGEM'
};
if(obj.valor) != getters.profundidadeSondagem(obj)) {
let reg = new RegExp(/([0-9],[0-9],[0-9])/);
let param = null;
return new Promise((resolve, reject) => {
if(obj.valor[0] == 0 && obj.valor[1] == 0 && obj.valor[2] == 0) {
param = axios.delete('/patologia', {data: patologia});
} else if (reg.test(obj.valor)){
param = axios.post('/patologia', patologia);
}
if(param != null) {
param.then(function (response) {
if(response.status == 200 || response.status == 201 && response.data) {
commit('armazenarProfundidadeSondagem', obj);
let dentes_data = {};
let face = '';
if (obj.arcada == 'arcada_superior' && obj.face == 'face_lingual_palatal') {
face = 'palatina'
} else {
face = obj.face.split('_')[1];
}
let classe_canvas = rootGetters.getNomeClasseCanvas(obj, face);
drawGraph(rootGetters.prepareDentesData(obj, face, dentes_data), face,
classe_canvas);
resolve();
}
}).catch(error => {
store.dispatch('mensagemAlerta/ALERTA', {
tipo: 'error',
mensagem: 'Não foi possível cadastrar o nível de sondagem'
});
reject(error);
});
}
})
}
},
RESET_PROFUNDIDADE_SONDAGEM({commit}, ob) {
commit('RESET_ALL', ob);
}
},
getters: {
profundidadeSondagem: (state, getters, rootState) => obj => {
return rootState[obj.arcada][obj.sextante][obj.dente][obj.face].profundidade_sondagem;
}
},
my guess is your issue lies here:
TL;DR - you pass your getter as valor to your action.
only a guess - as i cant debug your code
store.dispatch('profundidadeSondagem/MODIFY', patologia).catch(() => {
this.valorProfundidade = this.profundidadeSondagem;
})
as you assign a reference from your rootState[...] and thus you change the properties of the rootState[...] in your component past the first run.
So your code then behaves like:
let patologia = {
arcada: this.arcada,
sextante: this.sextante,
dente: "dente_" + this.dente,
face: this.face_json,
// valor: this.valorProfundidade,
///* same as */ valor: this.profundidadeSondagem,
/* same as */ valor: this.$store.getters['profundidadeSondagem/profundidadeSondagem'](...),
modelRefs: modelRefs,
id: this.changedId,
valorInserido: this.valorInserido,
};
A solution can be to this.valorProfundidade = this.profundidadeSondagem.slice(); as long it is an array or Object.assign({},...) - so you prevent the references

Email Input Warning - A component is changing a controlled input of type text to be uncontrolled

In my React app, I'm getting this error during onChange event with my email input field:
Warning: A component is changing a controlled input of
type text to be uncontrolled. Input elements should not switch from
controlled to uncontrolled (or vice versa).
Here's the onChange block that's causing this warning; The error goes away if I remove the first if block but of course I need it there for email validation.
validateEmail(email) {
const re = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
handleOnChange = e => {
const { name, value } = e.target;
const emailInput = e.target.value;
const emailValid = this.validateEmail(emailInput);
if (name === 'email') {
this.setState({
inputs: {
email: emailInput,
},
errors: {
email: !emailValid,
},
});
} else {
this.setState({
inputs: {
...this.state.inputs,
[name]: value,
},
errors: {
...this.state.errors,
[name]: false,
},
});
}
};
State:
constructor() {
super();
this.state = {
inputs: {
name: '',
email: '',
message: '',
},
phone: '',
show: true,
errors: {
name: false,
email: false,
message: false,
},
};
}
How do I keep my current code and address the warning?
You need to spread the existing/previous state in the if-block. You likely have other input tags that were initially connected to the input-state object which looks like:
inputs: {
name: "",
email: "",
message: ""
}
<input value={this.state.input.name} name="name"/>
<input value={this.state.input.email} name="email"/>
<input value={this.state.input.message} name="message"/>
but when you used this.setState() in your posted code, the connection is lost. You are setting the inputs state to an object with a single property of email:
inputs: {
email: "valueFromEventTarget"
}
What you need to do is spread the existing state so you don't lose the other key/value pairs in the input object: Update your handleChange() function to this:
handleOnChange = e => {
const { name, value } = e.target;
const emailInput = e.target.value;
const emailValid = this.validateEmail(emailInput);
if (name === 'email') {
this.setState({
inputs: {
...this.state.inputs,
email: emailInput,
},
errors: {
...this.state.errors,
email: !emailValid,
},
});
} else {
this.setState({
inputs: {
...this.state.inputs,
[name]: value,
},
errors: {
...this.state.errors,
[name]: false,
},
});
}
};

Categories