React native how to update multiple state values - react-native

Here is the user details which I want to update values when user enters data in Textinput
const [details, setDetails] = React.useState({
isValidName: true,
isValidMobile: true,
isValidEmail: true,
isValidGSTIN: true,
isValidPAN: true,
name: '',
mobile: '',
email: '',
company: '',
baddr1: '',
baddr12: '',
bcity: '',
bpincode: '',
bstate: ' TAMIL NADU',
bcountry: 'INDIA',
saddr1: '',
saddr2: '',
sbranch: '',
sgstin: '',
scity: '',
spincode: '',
sstate: '',
scountry: '',
pan: '',
gstin: '',
userlevel: '',
});
//In this method i am updating values each time when user enters data
const submitBillAddress = (data, type) => {
console.log('bill', type);
switch(type){
case 'addr1':
setDetails((prevState)=>{
return({
...prevState,
baddr1: data
});
});
break;
}
console.log('billdetails', details);
};
return (
<View>
<TextInput
style={styles.TextInputStyleClass}
placeholder="Address Line 1"
value={sameAddress?null:details.baddr1}
onChangeText={val => submitBillAddress(val, 'addr1')}
/>
</View>
)
I am new to React Native application development and I know this question is basic but I am not getting exact output. Here I have one Textinput in which I am entering data that I wanted to store in details.
The issue is if I enter data in textinput it's not updating value in details. Let's say I am entering 'C' in Textinput if I try to check the value in console the value of details.baddr1='' it's empty, Second time if I enter value 'H' on that time in console the value of details.baddr1='C'. Instead of showing the value details.baddr1='CH' it's showing previously entered value.
How can I fix this issue?

I'm guessing this is for a form of some sort. In that case, a package is your best bet I believe. While what you're trying to achieve is possible without a package, using a package is far less painful in the long run for your app.
Please check out formik or react-hook-form.
They're both decent.

Related

I am using Formik with Yup validation, How to use notOneof() of Yup. I have tried but fails

I have two fields "fromAccount" and "toAccount", both are objects. suppose both ojects have value:
formAccount={title:'abc',type:'xyz', ...}
toAccount={accountName:'abc',type:'xyz', ...}
Actually I want if, fromAccount.title become equals to toAccount.accountName generate error on onSubmit (formik).
below is validationSchema that I have tried but it doesn't invoke error.
const validationschema = Yup.object().shape({
fromAccount: Yup.object().shape({
title:Yup.string()
}).required().nullable().label('* From Account'),
toAccount: Yup.object().shape({
accountName:Yup.string().notOneOf([Yup.ref('title')], 'Select another account')
}).required().nullable().label('* To Account'),
amount: Yup.number().min(1).required().label("* Amount"),
});

Filter Vue list based on select option value

I try to filter my list with 2 select lists based on the selected value. It seems like my computed filter is not working?
You should be able to filter the list on 'Price from' and 'Price to'
List.vue
My computed filter property:
filteredData() {
const LowerCaseSearch = this.search.toLowerCase();
return this.products.filter(
product =>
(product.name.toLowerCase().includes(LowerCaseSearch) ||
product.category.toLowerCase().includes(LowerCaseSearch)) &&
(!this.checked.length || this.checked.includes(product.category)) &&
(!this.selectedFrom.length || this.selectedFrom.includes(product.price)) &&
(!this.selectedTo.length || this.selectedTo.includes(product.price))
);
},
In my registered component I use v-model to bind to the computed property selectedFrom
<Price v-model="selectedFrom" />
How do I bind to the other property selectedTo in one v-model and what's wrong with my filter?
I also use a prefix 'From' and 'To' to put in front of the options.
data: () => {
return {
selectedFrom: '0,00',
priceFrom: [
{ prefix: 'From', text: '0,00', value: '0,00' },
{ prefix: 'From', text: '200,00', value: '200,00' },
{ prefix: 'From', text: '400,00', value: '400,00' }
],
selectedTo: 'No max',
priceTo: [
{ prefix: 'To', text: '400,00', value: '400,00' },
{ prefix: 'To', text: '600,00', value: '600,00' },
{ prefix: 'To', text: '800,00', value: '800,00' },
{ text: 'No max', value: 'No max' }
]
}
},
Is there a more elegant and D.R.Y way to do this?
Here is a sandbox what I have so far.
You should bind an object to your v-model on the <price> component.
This way you can pass multiple values to and from your component, without having to use multiple props.
I would also suggest you convert your value in your selects to numbers, so it's easier to use them to compare to your prices.
You've also defined data properties and computed properties in the sandbox (<price> component) with the same name, this is not possible. So you should remove the data properties and stick to the computed ones to handle your data.
Fork of your sandbox with my suggested changes.

How to set validation schema based on condition using Yup? Formik

I'm trying to use Yup to validate data in an array. For example, this is my initialValue:
{name:'',extra:[]}
After dynamic render the form field , the initialValue will become like this:
{name:'',extra:[{label:'age',value:'',required:true}]}
I want to set the validation scheme to validate the 'value' in the object only when 'required' is true.
I use this data to mock the situation:
{name:'john',extra:[{label:'age',value:'',required:true}]};
Method that i had try:
const validationschema = yup.object().shape({
name: yup.string().required(),
extra: yup.lazy((value,index)=>{
return yup.mixed().required();
})
})
There should be an error when the user submit , because the 'value' for age is empty.
I not sure why, i can't really validate the 'value'. How do I change my validationschema so it can validate the 'value' ?
Try to validate like:
name: yup.string().required(),
extra: yup.array()
.of(
yup.object().shape({
required: yup.bool(),
value: yup.object().when('required', {
is: true,
then: yup.string().required('Please, select position')
}),
})
)
There you should check field required. If it true you validate it.

How to make a searchable droplist in react native to open an specific screen?

I'm trying to make a search bar with a list,dropdown list,
how to make a search list lik this code:
onPress={() =>this.props.navigation.navigate('LinhaDiurno03')
when an item is pressed?
....I want that each item in the list open a different screen in the application....
How can i to it?
here is the my teste:
Code to dropDown List
here some code:
var items = [
//name key is must.It is to show the text in front
{id: 1, name: 'ANA RECH', prestadora: 'UNIDOS', pos: 'P01'},
{id: 2, name: 'ARROIO DAS MARRECAS', prestadora: 'UNIDOS', pos: 'P01'},
{id: 3, name: 'VILA SECA', prestadora: 'UNIDOS', pos: 'P01'},];
onItemSelect={item => Alert.alert(" ", JSON.stringify(item.prestadora + ", LINHA: " + item.pos), [{ text: "open the especifc screen", onPress: () =>('some code here')},{ text: "bacvk", onPress: () => console.log("OK Pressed")}],{ cancelable: true })}
//onItemSelect called after the selection from the dropdown
I read the library API, you can set the navigation keys in the item, then in the onItemSelect to go to the special screen. the example code is below.
// in the item every element add a router key
const item = [
...
{
id: 8,
name: 'Swift',
key:"the navigation params" //like the example LinhaDiurno03
},
...
]
<SearchableDropdown
multi={true}
selectedItems={this.state.selectedItems}
onItemSelect={(item) => {
his.props.navigation.navigate(item.key)
}}
/>
Here is the final code, you just need to make the route before in your app...
the full code

Why is my POST faling in this simple VueJS form?

This is for a vueJS form. I have a nested value named "medications" I'm trying to submit for a form....I have this code in my template and data area that is related to medications. after I select the medication from the select box and enter the remaining fields and submit I get an error telling me I'm not submitting all my values...here are snips from my code...
NOTE: I'm not showing the entire form...only the part related with medication form field.
<template>
...
<div class="col-sm-2">
<b-form-select v-model="medication">
<option selected :value="null">Medication</option>
<option value="name" v-for="catMed in catMedications">{{catMed.medication.name}}</option>
</b-form-select>
</div>
...
</template>
data(){
...
duration: '',
frequency: '',
name: '',
medication: {name: '', duration: '', frequency: '', dosage: '', notes: ''},
...
(also, here is my POST function..if it helps)
postFeedings(catID, catName) {
const vm = this;
axios.post(`/api/v1/carelogs/`,{
cat: {id: catID, name: catName},
weight_unit_measure: 'G',
weight_before_food: this.weight_before_food,
food_unit_measure: 'G',
amount_of_food_taken: this.amount_of_food_taken,
food_type: this.food_type,
weight_after_food: this.weight_after_food,
stimulated: this.stimulated,
stimulation_type: this.stimulation_type,
medication: {name: vm.name, duration: vm.duration, frequency: vm.frequency, dosage: vm.dosage, notes: vm.notes},
medication_dosage_unit: 'ML',
medication_dosage_given: this.medication_dosage_given,
notes: this.notes
})
.then(response => {
console.log(response);
response.status === 201 ? this.showSwal('success-message','Carelog added') : null;
this.getFeedings(catName);
})
.catch(error => {
console.log(catID, catName);
console.log(error);
this.showSwal('auto-close', error);
})
}
ERROR: This is the error I get back ....
{"medication":{"frequency":["This field may not be blank."],"name":["This field may not be blank."]}}
ALL THE OTHER PARAMS ARE BEING SENT...but the ones for medication are not...
What am I doing wrong?
EDIT: updated axios post as Husam Ibrahim suggested
Like Husam says, In a function definition, this refers to the "owner" of the function. So when u access this in the axios function, this refers to the axios function, not to the vue instance.
Also - what i like to do is, create the object in the data of the vue instance, and use that for your post. Makes much cleaner code, and vue can access the object and properties.
Like this:
data () {
myObject: {
data1: 'abc',
data2: 'def',
data3: 123,
data4: false
}
}
and the axxios function like this:
const vm = this;
axios
.post('url.here', vm.myObject)
.then(response => {
// Handle response..
});
In vue you can use v-model="myObject.data1" to access the properties. This way you can use axxios get and assign the result to vm.myObject and vue will render the new data.
The key was in how I was getting "name" in my template. So I changed it up to this...
<div class="col-sm-2">
<b-form-select v-model="medication">
<option selected :value="null">Medication</option>
<option :value=catMed.medication.name v-for="catMed in catMedications">{{catMed.medication.name}}</option>
</b-form-select>
</div>
NOTE: see how :value=catMed.medication.name is configured? That's the key. now when I inspect my params in the browser I can see that I'm setting Medication.name to the value I intend.
And inside my axios.post I change the medication line to this...
...
medication: {name: this.medication, duration: this.duration, frequency: this.medication_dosage_given, dosage: this.dosage, notes: this.notes},
...
Now the two values are posting params ^_^