How to fix Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'status') at app.js - laravel

I had the following code and everything was working as expected.
<template>
<div id="login">
<form #submit.prevent="submit">
<p class="loading" :class="{ hideLoad: !loading }">Loading...</p>
<label for="email">Email</label>
<input type="text" id="email" v-model="fields.email" />
<span v-if="errors && errors.email" class="error">{{
errors.email[0]
}}</span>
<label for="password">Password</label>
<input type="password" id="password" v-model="fields.password" />
<span v-if="errors && errors.password" class="error">{{
errors.password[0]
}}</span>
<button type="submit">Log In</button>
<span
>Don't have an account?
<router-link :to="{ name: 'Register' }">Sign Up</router-link></span
>
</form>
</div>
</template>
<script>
export default {
data() {
return {
fields: {},
errors: {},
loading: false,
};
},
methods: {
submit() {
this.loading = true;
axios
.post("/api/login", this.fields)
.then((res) => {
if (res.status == 201) {
localStorage.setItem("authenticated", "true");
this.$router.push({ name: "Dashboard" });
}
})
.catch((error) => {
if (error.response.status == 422) {
this.errors = error.response.data.errors;
this.loading = false;
}
});
},
},
};
</script>
I then decided to use pinia to manage state and came up with the following.
<template>
<div id="login">
<form #submit.prevent="loginStore.submit">
<p class="loading" :class="{ hideLoad: !loginStore.loading }">Loading...</p>
<label for="email">Email</label>
<input type="text" id="email" v-model="loginStore.fields.email" />
<span v-if="loginStore.errors && loginStore.errors.email" class="error">{{
loginStore.errors.email[0]
}}</span>
<label for="password">Password</label>
<input type="password" id="password" v-model="loginStore.fields.password" />
<span v-if="loginStore.errors && loginStore.errors.password" class="error">{{
loginStore.errors.password[0]
}}</span>
<button type="submit">Log In 2</button>
<span
>Don't have an account?
<router-link :to="{ name: 'Register' }">Sign Up</router-link></span
>
</form>
</div>
</template>
<script setup>
import {useLoginStore} from '../stores/login'
const loginStore = useLoginStore();
</script>
My login.js
import { defineStore } from 'pinia'
export const useLoginStore = defineStore('login', {
state: () => {
return {
fields: {},
errors: {},
loading: false,
}
},
actions: {
submit() {
this.loading = true;
axios
.post("/api/login", this.fields)
.then((res) => {
if (res.status == 201) {
localStorage.setItem("authenticated", "true");
this.$router.push({ name: "Dashboard" });
}
})
.catch((error) => {
if (error.response.status == 422) {
this.errors = error.response.data.errors;
this.loading = false;
}
});
},
},
})
Everything is working as before and the only error is that when I fill the form with the correct credential and submit then I get Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'status') at app.js
I've tried all I can and I just can't figure out what it is that I'm doing wrong.

After debugging it further, I realized the error was coming from this.$routerinstance since a user gets login successfully and the status code is okay when I console log.
The instance is available in components only https://router.vuejs.org/api/#component-injected-properties
So, I fixed the problem by importing router in the store.js file,
import router from '../router'
then I pushed to another route by just using
router.push({ name: "Dashboard" });
instead of this.$router.push({ name: "Dashboard" });

Related

Uncaught (in promise) csrf Vue js laravel

i am creating the login form in vuejs.i tested through postman api working well. when i check with vue js validtaion it is not working.login Error,Uncaught (in promise) csrf Vue js laravel.
what i tried so far i attached below.i think the json validation problem can you check it.i attached the full source code below.
Login.vue
<template>
<div class="row">
<div class="col-sm-4" >
<h2 align="center"> Login</h2>
<form #submit.prevent="LoginData">
<input type="hidden" name="_token" :value="csrf">
<div class="form-group" align="left">
<label>Email</label>
<input type="email" v-model="student.email" class="form-control" placeholder="Mobile">
</div>
<div class="form-group" align="left">
<label>Password</label>
<input type="password" v-model="student.password" class="form-control" placeholder="Mobile">
</div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
</div>
</div>
</template>
<script>
import Vue from 'vue';
import axios from 'axios';
Vue.use(axios)
export default {
name: 'Registation',
data () {
return {
csrf: document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
result: {},
student:{
email: '',
password: ''
}
}
},
created() {
},
mounted() {
console.log("mounted() called.......");
},
methods: {
LoginData()
{
axios.post("http://127.0.0.1:8000/api/login", this.student)
.then(
({data})=>{
console.log(data);
try {
if (data === true) {
alert("Login Successfully");
this.$router.push({ name: 'HelloWorld' })
} else {
alert("Login failed")
}
} catch (err) {
alert("Error, please try again");
}
}
)
}
}
}
</script>
LoginController
public function check(Request $request)
{
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (Auth::attempt($credentials))
{
return response()->json(['data' => true ]);
}
return response()->json(['data' => 'Fail']);
}
}
According to Laravel 9 docs you have to send csrf token. Here's the link that talk about it:
https://laravel.com/docs/9.x/sanctum#csrf-protection

How get quill and other form to JS submit function?

I wanna use quill rich editor and other fields on my form. But cant get access to quill innerHTML from JS function. I am using Laravel with Alpinejs and my code is
<form x-data="contactForm()" #submit.prevent="submit">
<div class="col-12">
<div class="mt-2 w-100 bg-white" wire:ignore>
<div
x-data
x-ref="quillEditor"
x-init="
quill = new Quill($refs.quillEditor, {
theme: 'snow',
modules: {toolbar: '#toolbar'}
});
quill.on('text-change', function () {
$dispatch('input', quill.root.innerHTML);
});"
wire:model.debounce.2000ms="description"
class="sign__textarea"
style="height: 300px;"
>{{ old('description', $services_users->description) }}
</div>
</div>
</div>
<div class="col-12">
<input name="message" x-model="data.title">
</div>
<div class="col-12 col-xl-3 mt-5">
<button type="submit" x-text="buttonText" :disabled="loading"></button>
</div>
</form>
<script>
function contactForm() {
return {
data: {
title: "",
myQuill: quill.root.innerHTML,
},
buttonText: "Save",
loading: false,
submit() {
this.buttonText = "Saving...";
this.loading = true;
fetch('myurl.endpoint', {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
},
body: JSON.stringify(this.data),
}).then(() => {
alert("Form submitted");
}).catch(() => {
alert("Something went wrong");
}).finally(() => {
this.data.title = ""
this.buttonText = "Save";
this.loading = false;
});
},
};
}
</scirpt>
Now i have an error Can't find variable: quill how can i get all fields from form and send to backend event if quill is not a form field?
It doesn't work because you're calling the variable "quill" in the parent and you're declaring it in the child. To fix it declare the x-init directive in the form.
listening to the "text-change" event is not necessary. A good option is to add the content of the container before submitting the form.
see : https://alpinejs.dev/directives/data#scope
<form x-data="contactForm()" x-init="
quill = new Quill($refs.quillEditor, {
theme: 'snow'
});
quill.on('text-change', function () {
$dispatch('input', quill.root.innerHTML);
});" #submit.prevent="submit">
<div class="col-12">
<div class="mt-2 w-100 bg-white" wire:ignore>
<div
x-ref="quillEditor"
wire:model.debounce.2000ms="description"
class="sign__textarea"
style="height: 300px;"
>{{ old('description', $services_users->description) }}
</div>
</div>
</div>
<div class="col-12">
<input name="message" x-model="data.title">
</div>
<div class="col-12 col-xl-3 mt-5">
<button type="submit" x-text="buttonText" :disabled="loading"></button>
</div>
</form>
<script>
function contactForm() {
return {
quill:null,
data: {
title: "",
// myQuill: function(){ return this.quill.root.innerHTML}
},
buttonText: "Save",
loading: false,
submit() {
this.buttonText = "Saving...";
//add content quill here
this.data.myQuill = this.quill.root.innerHTML;
this.loading = true;
fetch('myurl.endpoint', {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
},
body: JSON.stringify(this.data),
}).then(() => {
alert("Form submitted");
}).catch(() => {
alert("Something went wrong");
}).finally(() => {
this.data.title = ""
this.buttonText = "Save";
this.loading = false;
});
},
};
}
</script>
Ok this is what i did
<form x-data="contactForm()" x-init="initQuill()" x-on:submit="submit()" method="POST" action="target.url">
<div x-ref="editor"></div>
<input x-ref="editorValue" type="hidden" name="hidden_input">
<button>Save</button>
</form>
<script>
function contactForm(){
return {
initQuill(){
new Quill(this.$refs. editor, {theme: 'snow'});
},
submit(){
console.log(this.$refs. editor.__quill.root.innerHTML);
this.$refs.editorValue.value = this.$refs.editor.__quill.root.innerHTML;
}
}
}
</script>
Now is ok and works with basic. You can extend function with new features etc. Thx for help guys.

Axios post request error when sending an array with an image

I have a form that has an array input and an image, when sending the request without the image it's getting stored correctly in the database, when the image input and the "Content-Type": "multipart/form-data" header both added, it send the request with the correct data but it outputs that the array data is invalid.
the code is written in Vue 3 and the backend is a laravel api.
<script>
import axios from "axios";
export default {
name: "AddPayloadModel",
data() {
return {
drone_id: [],
drone_models: [],
image: null,
previewImage: null,
};
},
created() {
this.getDroneModels();
},
methods: {
getDroneModels() {
axios.get("http://127.0.0.1:8000/api/drone-models").then((response) => {
this.drone_models = response.data;
});
},
imgUpload(e) {
this.image = e.target.files[0];
const reader = new FileReader();
reader.readAsDataURL(this.image);
reader.onload = (e) => {
this.previewImage = e.target.result;
};
},
submit(e) {
const form = new FormData(e.target);
const inputs = Object.fromEntries(form.entries());
inputs.drone_id = Object.values(this.drone_id);
console.log(inputs.drone_id);
axios
.post("http://127.0.0.1:8000/api/payload-model/add", inputs, {
headers: {
"Content-Type": "multipart/form-data",
},
})
.then((res) => {
if (res.data.isUnattachableDrones) {
console.log(res);
alert(res.data.unattachableDrones);
} else {
this.$router.push("/home");
}
})
.catch((e) => {
console.error(e);
});
},
},
};
</script>
<template>
<main class="form-signin">
<form #submit.prevent="submit">
<h1 class="h3 mb-3 fw-normal">Add Payload Model</h1>
<div class="form-floating">
<input
class="form-control"
autocomplete="off"
name="brand_name"
placeholder="Brand Name"
/>
<label>Brand Name</label>
</div>
<div class="form-floating">
<input
class="form-control"
autocomplete="off"
name="model_name"
placeholder="Model name"
/>
<label>Model Name</label>
</div>
<div class="form-floating">
<input
class="form-control"
autocomplete="off"
name="type"
placeholder="Type"
/>
<label>Type</label>
</div>
<select
v-model="drone_id"
multiple="multiple"
name="drone_id"
style="height: auto"
class="form-select last-input"
>
<template v-for="drone in drone_models">
<option :value="drone.id">
{{ drone.brand_name }}
</option>
</template>
</select>
<input
name="image"
ref="fileInput"
accept="image/*"
type="file"
#input="imgUpload"
/>
<button class="w-100 btn btn-lg btn-form" type="submit">Submit</button>
</form>
</main>
</template>
here is the response when submitting the form.
and here is the payload.
It got solved by changing the way to push data to the post request to a formData and append it manually like this.
submit() {
const formData = new FormData();
formData.append(
"brand_name",
document.getElementById("brand_name").value
);
formData.append(
"model_name",
document.getElementById("model_name").value
);
formData.append("type", document.getElementById("type").value);
formData.append("image", document.getElementById("image").files[0]);
this.drone_id.forEach((drone_id) => {
formData.append("drone_id[]", drone_id);
});
const headers = { "Content-Type": "multipart/form-data" };
axios
.post("http://127.0.0.1:8000/api/payload-model/add", formData, headers)
.then((res) => {
console.log(res);
if (res.data.isUnattachableDrones) {
console.log(res);
alert(res.data.unattachableDrones);
} else {
this.$router.push("/home");
}
})
.catch((e) => {
console.error(e);
});
},

Post request by axios (VueJS) in laravel giving 500 error

I am trying to make a post request via axios but getting this error: app.js:285 POST http://127.0.0.1:8000/concerts/1/orders 500 (Internal Server Error)
The order is being processed though (I see it coming is Stripe and database). Another problem is that redirect is not happening as window.location =/orders/${response.data.confirmation_number}; I just stay on the same page.
Any ideas what could go wrong here?
<template>
<div>
<div class="row middle-xs">
<div class="col col-xs-6">
{{ csrf_token}}
<div class="form-group m-xs-b-4">
<label class="form-label">
Price
</label>
<span class='form-control-static '>
${{ priceInDollars }}
</span>
</div>
</div>
<div class="col col-xs-6">
<div class="form-group m-xs-b-4">
<label class="form-label">
Qty
</label>
<input type="number" v-model="quantity" class="form-control">
</div>
</div>
</div>
<div class="text-right">
<button class="btn btn-primary btn-block"
#click="openStripe"
:class="{ 'btn-loading': processing }"
:disabled="processing"
>
Buy Tickets
</button>
</div>
</div>
This is script part:
<script>
export default {
props: [
'price',
'concertTitle',
'concertId',
],
data() {
return {
quantity: 1,
stripeHandler: null,
processing: false,
}
},
computed: {
description() {
if (this.quantity > 1) {
return `${this.quantity} tickets to ${this.concertTitle}`
}
return `One ticket to ${this.concertTitle}`
},
totalPrice() {
return this.quantity * this.price
},
priceInDollars() {
return (this.price / 100).toFixed(2)
},
totalPriceInDollars() {
return (this.totalPrice / 100).toFixed(2)
},
},
methods: {
initStripe() {
const handler = StripeCheckout.configure({
key: App.stripePublicKey
})
window.addEventListener('popstate', () => {
handler.close()
})
return handler
},
openStripe(callback) {
this.stripeHandler.open({
name: 'TicketBeast',
description: this.description,
currency: "usd",
allowRememberMe: false,
panelLabel: 'Pay {{amount}}',
amount: this.totalPrice,
// image: '/img/checkout-icon.png',
token: this.purchaseTickets,
})
},
purchaseTickets(token) {
this.processing = true
axios.post(`/concerts/${this.concertId}/orders`, {
email: token.email,
ticket_quantity: this.quantity,
payment_token: token.id,
}).then(response => {
window.location =`/orders/${response.data.confirmation_number}`;
console.log('Charge succeeded.')
}).catch(response => {
this.processing = false
})
}
},
created() {
this.stripeHandler = this.initStripe()
}
}
You have to go and look under the Network tab if you are using Chrome browser, you can see the failed request response
The issue turns out to be Mailer. In .env file, along with Mailtrap credentials you must provide sender email and they don't tell you that :( This also somehow prevented the redirect. In case that helps someone.

Multiple file upload using laravel and vue js error not print

Multiple file upload using vue js in laravel my validation is like
$request->validate([
'title' => 'required',
'pics.*' => 'required|image|mimes:jpeg,png,jpg,gif'
]);
and my component is like below
<template>
<div class="col-md-6">
<div class="form-group">
<label>Title</label>
<input id="title" type="text" ref="myDiv" v-model="title" class="form-control" name="title">
<div v-cloak><label class="error" v-if="errors['title']">{{ errors.title[0]
}}</label></div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label>Upload Files</label>
<input id="uploadfile" type="file" ref="pics" name="pics[]" multiple class="form-control" #change="fieldChange">
<div v-cloak><label class="error" v-if="errors['pics']">{{ errors.pics[0] }}</label></div>
</div>
</div>
</template>
export default {
data(){
return {
attachments:[],
pics : [],
errors: [],
form: new FormData
}
},
methods:{
fieldChange(e){
let selectedFiles=e.target.files;
if(!selectedFiles.length){
return false;
}
for(let i=0;i<selectedFiles.length;i++){
this.attachments.push(selectedFiles[i]);
}
console.log(this.attachments);
},
uploadFile() {
this.errors = [];
this.form.append('img',this.attachments2);
if(this.attachments.length > 0){
for(let i=0; i<this.attachments.length;i++){
this.form.append('pics[]',this.attachments[i]);
}
}else {
this.form.append("pics", '');
}
//this.form.append('')
const config = { headers: { 'Content-Type':
'multipart/form-data' } };
axios.post('/admin/theme/',this.form,config).then(response=>
{
this.pics = [];
}).catch((error) => {
this.errors = error.response.data.errors;
console.log(this.errors.pics);
});
}
},
mounted() {
console.log('Component mounted.')
}
}
If i click to submit button empty title error print but multiple file error not print, i get error but not print
pics.0:["The pics.0 field is required."]
But title field validation error print perfectly
Please anyone help me to print multiple file upload error using vue js

Resources