Why is Axios posting the wrong data? - javascript

I'm confused with Axios:
In my Vue template I have a list of JS objects, each element is like:
covs.all_batches_tuples[
...
{'id': 45, 'bname': 'tcp_S1153', 'selected': False}
...
]
I have a checkbox loop:
<v-row>
<v-col v-for="batch in covs.all_batches_tuples" :key="batch.id" class="pa-0 ma-0 text-body-2" cols="1">
<input type="checkbox" :id="batch.id" v-model="batch.selected" :value="batch.bname"
#click="selected_batches()"/>
<label :for="batch.id">{{ batch.bname }}</label>
</v-col>
</v-row>
and finally I have a method that is fired after clicking a checkbox:
methods: {
selected_batches() {
console.log("1 ", this.covs.all_batches_tuples)
axios({
method: 'post',
url: 'http://192.168.21.152:8002/showAnns/covs/',
data: {
checked_batches_ids_string: this.covs.all_batches_tuples,
},
})
console.log("2 ", this.covs.all_batches_tuples)
},
}
In Chrome the initial state looks like this:
when I click a checkbox, the selected_batches method fires two console.log() functions, and axios funciton.
All variables (this.covs.all_batches_tuples) are the same variables and in console.log looks good, the checkbox is selected:
But in axios post it as unselected:
If I click this checkbox again, so it is "unchecked", the axios shows it as "checked":
What is going on here? Thanks for help!

This problem actually happens because the v-model update later after the axios is called. In this case, you can use #change instead of #input.
<v-row>
<v-col v-for="batch in covs.all_batches_tuples" :key="batch.id" class="pa-0 ma-0 text-body-2" cols="1">
<input type="checkbox" :id="batch.id" v-model="batch.selected" :value="batch.bname" #change="selected_batches" />
<label :for="batch.id">{{ batch.bname }}</label>
</v-col>
</v-row>

Related

Vuetify Dynamic Binding of Property

I've got a form which contains a dynamic set of input components (v-selects and v-text-fields) that a user has to set. However, I'm really struggling to understand how to retrieve the values from these input components once the user submits the form. My input setup looks like this:
<v-row>
<v-col
v-for="(item, index) in documentTags.tags"
:key="index"
cols="18"
sm="8"
md="6"
>
<v-select
v-if="item.InputType === 'Combobox'"
:v-model="documentTagResponses[index]"
:name="item.Name"
:items="item.TagValueOptions"
:rules="rules.ComboboxRule"
item-text="Value"
:label="item.Name"
required
>
</v-select>
<v-text-field
v-else-if="item.InputType === 'Textbox'"
:v-model="documentTagResponses[index]"
:name="item.Name"
:label="item.Name"
:rules="rules.TextboxRule"
required
>
</v-text-field>
</v-col>
</v-row>
And my documentTags definition looks something like this:
{
tags: [
{
TagDefinitionId: '1',
InputType: 'Combobox',
Name: 'Name_1',
TagValueOptions: [
{
Value: 'Option 1',
},
{
Value: 'Option 2',
},
{
Value: 'Option 3',
},
],
},
{
TagDefinitionId: '2',
InputType: 'Textbox',
Name: 'Name_2',
TagValueOptions: [],
},
],
}
I'm trying to bind the form responses from these inputs to an array called documentTagResponses.
So, something like this:
export default {
name: 'MyModal',
data: () => ({
documentTagResponses: [],
}),
methods: {
validate() {
const valid = this.$refs.form.validate();
if (valid) {
for (const key of Object.keys(this.documentTagResponses)) {
console.log(`${key} -> ${this.documentTagResponses[key]}`);
}
}
},
};
Then, when the user clicks the submit button, I call the validate function to ensure the components are valid and then do something with the values... Right now I'm simply trying to print the values of each component to the console. However, my documentTagResponses array is always empty. Does anyone know why I can't seem to access the values that are being set in these components?
I just tested your code in my project and the problem was :v-model
We don't need : in v-model
So the code can be like below
<v-row>
<v-col
v-for="(item, index) in documentTags.tags"
:key="index"
cols="18"
sm="8"
md="6"
>
<v-select
v-if="item.InputType === 'Combobox'"
v-model="documentTagResponses[index]"
:name="item.Name"
:items="item.TagValueOptions"
:rules="rules.ComboboxRule"
item-text="Value"
:label="item.Name"
required
>
</v-select>
<v-text-field
v-else-if="item.InputType === 'Textbox'"
v-model="documentTagResponses[index]"
:name="item.Name"
:label="item.Name"
:rules="rules.TextboxRule"
required
>
</v-text-field>
</v-col>
</v-row>

How to submit form to array and clear inputs in vue

I have a vue form inside a dialog. Where the user can select a date and multplie starting times and ending times. So far I can save one object consisting of one date and multiple times. But when I want to add another object it takes the new date but changes the time values for every object.
for example if I add first an object with 05.09.2021 start:15:00 end: 16:00 and then add another object with date: 06.09.2021 start: 16:00 end: 17:00. The start and end is changed to the latest value of all objects, but I want each of them to be individually. I tried submitting a form, but sadly I could not make it work because it is reloading the page which I do not want, if i use .prevent on submit my error with time changing for every object still consists. Could someone take a look at my code and point me my mistake out`?
HTML:
<v-row>
<v-col cols="12" sm="12">
<v-menu
ref="menu3"
v-model="menu3"
:close-on-content-click="false"
:return-value.sync="dates"
transition="scale-transition"
offset-y
min-width="auto"
>
<template v-slot:activator="{ on, attrs }" >
<v-text-field
v-model="dates"
label="Picker in menu"
prepend-icon="mdi-calendar"
readonly
v-bind="attrs"
v-on="on"
></v-text-field>
</template>
<v-date-picker
v-model="dates"
no-title
scrollable
>
<v-spacer/>
<v-btn
text
color="primary"
#click="menu3 = false"
>
Cancel
</v-btn>
<v-btn
text
color="primary"
#click="$refs.menu3.save(dates) "
v-on:click=" menu3 = false"
>
OK
</v-btn>
</v-date-picker>
</v-menu>
<v-btn v-on:click="addTimeFields()">Add Time</v-btn>
</v-col>
</v-row>
<v-row v-for="(find, index) in selectedTime" >
<v-col
cols="6"
sm="6">
<v-text-field
v-model="find.startTime"
label="Starttime"
type="time"
></v-text-field>
</v-col>
<v-col
cols="6"
sm="6">
<v-text-field
v-model="find.endTime"
label="Untiltime"
type="time"></v-text-field>
</v-col>
</v-row>
</form>
Javascript:
<script>
import MeetingsTableComponent from "#/components/MeetingsTableComponent";
import DatePickerComponent from "#/components/DatePickerComponent";
export default {
name: "NextMeetingCardComponent",
data: () => ({
selectedTime: [],
dates: new Date().toISOString().substr(0,10),
datesFinal: [],
dialog: false,
menu: false,
modal: false,
menu2: false,
menu3: false
}),
methods:{
addTimeFields(){
this.selectedTime.push({
startTime:"",
endTime: "",
})
},
saveDateAndTIme(e){
this.datesFinal.push({
date: this.dates,
times : [this.selectedTime]
}
)
this.$refs.form.submit()
},
clearArrays(){
while (this.selectedTime.length){
this.selectedTime.pop()
}
}
}
};
</script>
I tried clearing the selectedTimes array which is pushed to datesFinal after pushing it but then every value is deleted.
I think there's an error in saveDateAndTIme(): times contains a nested array of the this.selectedTime array, but that should be unnested (i.e., set times to this.selectedTime itself).
After pushing this.selectedTime into datesFinal, you could clear the form by setting this.selectedTime to an empty array.
export default {
methods: {
saveDateAndTIme(e) {
this.datesFinal.push({
date: this.dates,
times: this.selectedTime, 👈
})
this.selectedTime = [] 👈
},
}
}
demo

Vue push into nested array

I have a vue application where I am trying to save an array which consists of a date field and has another array inside with time and time has startTime and untilTime as values.
What i want to achieve is that that when I click on a button the fields connected to time.startTime and untilTime should be added on button click. But I am getting this error:
vue.runtime.esm.js?2b0e:619 [Vue warn]: Avoid using non-primitive value as key, use string/number value instead.
found in
---> <DatePickerComponent> at src/components/DatePickerComponent.vue
<VCard>
<VThemeProvider>
<VDialog>
<VsRow>
<VCard>
<NextMeetingCardComponent> at src/components/NextMeetingCardComponent.vue
<DashboardComponent> at src/views/DashboardComponent.vue
<VMain>
<VApp>
<App> at src/App.vue
<Root>
I am a bit new to vue and javascript could someone point out my error maybe?
<template>
<div>
<v-row>
<v-col cols="12" sm="12">
<v-menu v-for="item in dates" :key="item"
ref="menu"
v-model="menu"
:close-on-content-click="false"
:return-value.sync="dates"
transition="scale-transition"
offset-y
min-width="auto"
>
<template v-slot:activator="{ on, attrs }" >
<v-text-field
v-model="item.date"
label="Picker in menu"
prepend-icon="mdi-calendar"
readonly
v-bind="attrs"
v-on="on"
></v-text-field>
</template>
<v-date-picker
v-model="dates"
no-title
scrollable
>
<v-spacer/>
<v-btn
text
color="primary"
#click="menu = false"
>
Cancel
</v-btn>
<v-btn
text
color="primary"
#click="$refs.menu.save(dates)"
>
OK
</v-btn>
</v-date-picker>
</v-menu>
<v-btn v-on:click="addTimeFields()">Add Time</v-btn>
</v-col>
</v-row>
<v-row v-for="i in dates" :key="i">
<v-col
cols="6"
sm="6"
>
<v-text-field
v-model="i.time.startTime"
label="Starttime"
type="time"
></v-text-field>
</v-col>
<v-col
cols="6"
sm="6"
>
<v-text-field
v-model="i.time.untilTime"
label="Untiltime"
type="time"
></v-text-field>
</v-col>
</v-row>
</div>
</template>
<script>
export default {
name: "DatePickerComponent",
data: () => ({
dates: [{date: new Date().toISOString().substr(0,10), time: [{
startTime: "",
untilTime: ""
}]}],
timeInputFields:[],
selectedDate: [],
menu: false,
modal: false,
menu2: false,
}),
methods:{
addTimeFields(){
this.dates[0].time.push({
startTime: "",
untilTime: "",
})
}
}
};
</script>
Output Vue:
Vue output
I think there are a couple of issues.
time is not an array, it is an object
You don't have 2 dates in the array, so probably want the 0 based index.
#2 is where the error is coming from.
addTimeFields(){
this.dates[0].time.push({
startTime: "",
untilTime: "",
})
}
Since your first entry already has start and until times set, to update you just need to to:
this.dates[0].time = {
startTime: "",
untilTime: "",
}
or
this.dates[0].time.startTime = "",
this.dates[0].time.untilTime = "",
EDIT one
I created a code pen for your code, there are quite a few errors, probably around the setup, but this screenshot shows what happens if you add two dates into the array. You get a list of them at the top, and then a list of the times. This makes me think you probably are just wanting one?
Please see this pen, https://codepen.io/OblivionSY/pen/rNyOLpw?editors=1011 it is not amazing, and doesn't fully work (date picker has an error)
Some general notes though:
make sure your :key value are primitive (string, int etc) and unique
try and split up the functionality into components. If you have multiple dates, then have one component to deal with editing a single date and the respective times.
feel free to edit the pen if you want me to take another look.

how to pass variable between to vue file?

how to pass variable between to vue file ?
Hello, this is my file SendCode.vue has variable NewEmail which I want to use it in another file changePass.vue .
Is there anyway to sole this ?
Can someone help me ? Thanks
<template>
<v-app id="inspire">
<v-content>
<v-container class="fill-height" fluid>
<v-row align="center" justify="center">
<v-col cols="12" sm="8" md="4">
<v-card class="elevation-12">
<v-toolbar color="#ff8c00">
<v-toolbar-title>Glömt lösenord!</v-toolbar-title>
</v-toolbar>
<v-card-text>
Skrive ditt email.
<v-form>
<v-text-field v-model="email"
:error-messages="emailErrors"
label="E-mail"
required
#input="$v.email.$touch()"
#blur="$v.email.$touch()"></v-text-field>
</v-form>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn #click="getCode" color="primary">Skicka koden</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</v-container>
</v-content>
</v-app>
</template>
<script>
import axios from 'axios'
import router from '#/router.js'
import { validationMixin } from 'vuelidate'
import { required, email } from 'vuelidate/lib/validators'
export default {
mixins: [validationMixin],
validations: {
email: { required, email },
checkbox: {
checked(val) {
return val
}
}
},
props: {
source: String,
},
data: () => ({
email: ""
}),
methods: {
getCode: async function() {
let obj = {
"email": this.email,
};
let NewEmail = this.email;
let response = await this.$store.dispatch("getCode", obj);
//console.log(email)
//console.log(this.email)
if (response.status == 200) {
setTimeout(function() {
router.push({
path: 'ChangePass'
});
}, 500);
}
}
}
}
</script>
I want to use/pass variable NewEmail in this file from SendCode.vue file
I am new in vue and javascript so I do not know how to do this.
<template>
<v-app id="inspire">
<v-content>
<v-container class="fill-height" fluid>
<v-row align="center" justify="center">
<v-col cols="12" sm="8" md="4">
<v-card class="elevation-12">
<v-toolbar color="#ff8c00">
<v-toolbar-title>ÄNDRA LÖSENORDET</v-toolbar-title>
</v-toolbar>
<v-card-text>
<v-form>
<v-text-field :error="pass1Error" label="Koden" v-model="code1" type="password" />
<v-text-field :error="pass2Error" label="Lössenord" v-model="newPassword" type="password" />
<v-text-field :error="pass1Error" label="Samma Lössenord" v-model="rePassword" type="password" />
</v-form>
</v-card-text>
<v-alert v-if="passError" type="error">
password are not same
</v-alert>
<v-alert v-if="passwordChanged" type="success">
Password has been updated!
</v-alert>
<v-card-actions>
<v-spacer />
<v-btn #click="change" color="primary">Ändra</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</v-container>
</v-content>
</v-app>
</template>
<script>
import axios from 'axios'
import SendCode from "#/views/SendCode.vue";
import { validationMixin } from 'vuelidate'
import { required, email } from 'vuelidate/lib/validators'
export default {
mixins: [validationMixin],
validations: {
email: { required, email },
checkbox: {
checked(val) {
return val
}
}
},
props: {
source: String,
},
data: () => ({
code1: "",
newPassword: "",
rePassword: ""
}),
methods: {
change: async function() {
let obj = {
"code1": this.code1,
"newPassword": this.newPassword,
"rePassword": this.rePassword,
};
console.log(obj)
let response = await this.$store.dispatch("changePass", obj);
}
}
}
</script>
We recommend that you use Vuex (State management) for easy transfer and management of data through pages
Documentation:
https://vuex.vuejs.org/
If its only a variable with some value in it you can store it in localstorage i assume.
So in your function where you have the data you want to pass add:
localStorage.setItem('email', variable).
This works as a key value pair where email is the key and the variable is the data you want to access.
Then where you want to access the data you can use:
localStorage.getItem('email')
You probably don't want to do what you're trying to do, but would be better off with state management (vuex/pinia/genericVueStore), or, if you want to pass the data between components in the same app (same project), then the main method is $emits and $props. Check Vue documentation to see if that is what you want, which it probably is.
Nevertheless, within a Vue project, you can generally use Node/ES methods. So, the following would be fine, and would fit into the "composables" category if they weren't ".vue" files.
>> file1.vue
<script setup>
const oneData = "this_text"
export {oneData}
...
>> file2.vue
import {oneData} from "#/file1.vue"
console.log(oneData}
This would be an anti-pattern. Just follow the documentation for the standard things people try to accomplish.

vue / vuetify dynamically modify v-text-field properties

I've got a couple fields:
<v-row>
<v-col cols="12" class="d-flex">
<v-text-field clearable outlined required :rules="rules.codeRules" name="code" v-model="attribute.code" label="Code"></v-text-field>
</v-col>
</v-row>
<v-row>
<v-col cols="12" class="d-flex">
<v-text-field clearable outlined required :rules="rules.nameRules" name="name" v-model="attribute.name" label="Name"></v-text-field>
</v-col>
</v-row>
In Vuetify's documents I see there's a couple properties named error which triggers an error state and error-messages with messages to be displayed.
When the form's submitted, if there's any errors on any of the fields I want to trigger these properties.
How can I do that? For instance, how can I manually set the field with the name of "code" into an error state by using the error property? how can I pass a personalized message to it? Do I need to specifically create a variable in the data() object in order to do what I wanna do? because if I have to do it that way it'd mean that I need to create an error and an error-messages properties in the data object for each and every field in my form!? or it can do by selecting exactly the field that I want to modify and somehow update its properties directly without the need of any variable from the model?
Thanks
Edit
Here's what I'm doing:
<v-row>
<v-col cols="12" class="d-flex">
<v-text-field clearable outlined required :error="formErrors.code.error" :error-message="formErrors.code.errorMessages" :rules="rules.codeRules" name="code" v-model="attribute.code" label="Code"></v-text-field>
</v-col>
</v-row>
My submit method is the following:
axios.post(postUrl, this.attribute, { Accept: "application/json" })
.then(response => {
if (response.data.success) {
Event.fire('message', {
type: 'success',
message: 'Attribute successfully saved'
});
this.$router.push('/attributes/list')
}
})
.catch(errors => {
// eslint-disable-next-line no-console
console.log(errors.response.data)
const responseErrors = errors.response.data
if (responseErrors) {
// eslint-disable-next-line no-console
console.log('here modafucka')
//const self = this
for (const key of Object.keys(responseErrors)) {
// eslint-disable-next-line no-console
console.log(responseErrors[key][0])
this.formErrors[key].error = true;
this.formErrors[key].errorMessages = responseErrors[key][0];
}
}
})
}
By setting this.formErrors[key].error = true; I'm able to put the field in an error state, but still the customized error message is not being displayed
First of all, you don't need both error and error-messages prop. If you just set error-messages, the input field will go in error state and the message will be shown
Do I need to specifically create a variable in the data() object in
order to do what I wanna do? because if I have to do it that way it'd
mean that I need to create an error and an error-messages properties
in the data object for each and every field in my form!
Yes, you'll need to set error-messages prop for each and every field. You already have separate variables for v-model and rules.
Ideally you would be running a for loop to generate the input fields(shown below), but a simple :error-messages="errorMessages.code" & :error-messages="errorMessages.name" will also work.
// Fields array
[
{
name: 'code',
rules: [ // list of rules ],
value: '' // Some value,
errorMessages: [] // Could be list or string
},
{
name: 'name',
rules: [ // list of rules ],
value: '' // Some value,
errorMessages: [] // Could be list or string
}
]
// Your form template
<v-row v-for="field in fields" :key="field.name">
<v-col cols="12" class="d-flex">
<v-text-field
clearable
outlined
required
:rules="field.rules"
:name="field.name"
v-model="field.value"
:label="field.name"
:error-messages="field.errorMessages"
>
</v-text-field>
</v-col>
</v-row>

Categories