Can't Submit Axios Post form Nuxt.js (VueJS) - javascript

I'm playing around with my first ever form in Vue. I've created my app with Nuxt.
I'm able to get data via an axios get request from my API but I can't seem to post data.
new.vue
<template>
<section class="container">
<div>
<h1>Gins</h1>
<form #submit.prevent="addGin">
<h4>New Product</h4>
<p>
<label for="name" class="input-label">Title:</label>
<input id="name" v-model="title" type="text" name="name" class="input">
</p>
<p>
<button type="submit" value="Submit" class="button">Add Gin</button>
</p>
</form>
</div>
</section>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
title: '',
errors: []
}
},
methods: {
addGin() {
axios.post('/apv/v1/gins', this.title)
.then((Response) => {})
.catch((err) => {
this.errors.push(err)
})
}
}
}
</script>
When clicking the submit button, I'm not receiving any errors, but I can confirm no entry is added to my API database.
My API is running on a different server localhost:4000 and I have set up the proxy in nuxt.config.js
axios: {
proxy: true
},
proxy: {
'/api/v1/': 'http://localhost:4000'
},
I've experimented with both <form #submit.prevent="addGin"> and <form v-on:submit.prevent="addGin"> but this doesn't seem to make a difference.
What else might I be missing?

Add #nuxtjs/axios module into modules part of nuxt.config
Use this.$axios instead of imported one. Proof: https://axios.nuxtjs.org/usage

OK so was really close. Changing my axios params to title: this.title, apparently did the trick.

Related

InertiaJS keep form data after validation error

In my InertiaJS/VueJS project I have a prop that receive some data from the backend:
event: {
type: Object,
default: () => { return {} }
},
That's how the event obj looks in the backend:
['name' => 'Event Name']
I use toRefs to convert the reactive prop and update its properties in the UI:
const eventRef = toRefs(props).event
So the Event has the name 'Event Name' when the component loads, when I update the event name in the UI to 'New Name' and submit the form, I send the eventRef obj in the request to create the new event:
Inertia.post(url, eventRef, only: ['global'])
If there's a validation error in the backend, I return it to the frontend and show the error in the UI (This is working without problems). The problem I have is that Inertia (or maybe VueJS) is returning the object eventRef to his previous state when the component is created. Which means that the name property of the eventRef changes to 'Event Name' again, instead of staying with 'New Name` that was updated in the UI. I would like to preserve the state of the object after I submit the form. This is my Inertia response:
component: "Events/EventNew"
props: {
global: {} // Global object
}
url: "/app/qa/events/new"
version: null
As you can see I'm not even getting the 'event' prop from the backend, so it shouldn't be updated. After reading Inertia docs I thought that a simple preserveState:true in the request options would do the job but this is not happening. Every time the server returns an Inertia response, the eventRef obj is 'reset'.
What am I missing here? I would appreciate some help
I believe I had the same problem using Inertia with Vue2. If I understood correctly, you probably seeing this on a form where you trying to update and entry, right? Your validation is working but the form keeps resetting itself to the previous state. If that's the case, what solved this for me was this:
Instead of using Inertia.post() directly, use the Inertia Form Helper instead
Vue 2
<template>
<form #submit.prevent="form.post('/login')">
<!-- email -->
<input type="text" v-model="form.email">
<div v-if="form.errors.email">{{ form.errors.email }}</div>
<!-- password -->
<input type="password" v-model="form.password">
<div v-if="form.errors.password">{{ form.errors.password }}</div>
<!-- remember me -->
<input type="checkbox" v-model="form.remember"> Remember Me
<!-- submit -->
<button type="submit" :disabled="form.processing">Login</button>
</form>
</template>
<script>
export default {
data() {
return {
form: this.$inertia.form({
email: null,
password: null,
remember: false,
}),
}
},
}
</script>
Vue 3
<template>
<form #submit.prevent="form.post('/login')">
<!-- email -->
<input type="text" v-model="form.email">
<div v-if="form.errors.email">{{ form.errors.email }}</div>
<!-- password -->
<input type="password" v-model="form.password">
<div v-if="form.errors.password">{{ form.errors.password }}</div>
<!-- remember me -->
<input type="checkbox" v-model="form.remember"> Remember Me
<!-- submit -->
<button type="submit" :disabled="form.processing">Login</button>
</form>
</template>
<script>
import { useForm } from '#inertiajs/inertia-vue3'
export default {
setup () {
const form = useForm({
email: null,
password: null,
remember: false,
})
return { form }
},
}
</script>
I solved the problem, it was the toRefs that was modifying the props in the component after the request was sent. Using a reactive object was the solution:
const eventRef = reactive(props.event)

Dynamically display fetched data in input field using Laravel 8 Vue Js

I have a simple registration form in Laravel 8 using Vue js where I need to check first if the user who refers the person registering exists in my database prior to submitting. if a record exists, I need to dynamically display the user's full name in the input field on the #change event.
Here's my Vue component:
<template>
<div>
<h2>TESTING</h2>
<form #submit.prevent="submit" >
<input type="text" class="form-control" v-model="form.ucode" #change="getUser()">
<input type="text" class="form-control" v-model="form.uname">
</form>
</div>
</template>
<script>
export default {
data: function(){
return{
form: {
ucode: "",
uname: "",
},
}
},
methods:{
getUser(){
axios.get('api/checkUser?ucode=' + this.form.ucode).then(res=>{
this.form.uname = res.data.first_name
})
}
}
}
Here's my ResellerController and API route:
Route::get('/checkUser', [ResellerController::class, 'show']);
public function show()
{
$ucode = request('ucode');
$user = DB::table('resellers')->where('username', $ucode)->select('id', 'first_name')->get();
return response()->json($user);
}
I think I don't have issues with my controller because it returns back the correct JSON data
[{"id":1,"first_name":"William Hardiev"}]
But when I test my code, uname is undefined.
form:Object
ucode:"williambola_05"
uname:undefined
Can anyone help me with this?
You issue is the JSON response that you receive from the server. You are getting a JSON Array from the server, whereas your JS code is handling a JSON object
You can handle it like this:
<template>
<div>
<h2>TESTING</h2>
<form #submit.prevent="submit">
<input
type="text"
class="form-control"
v-model="form.ucode"
#change="getUser()"
/>
<input type="text" class="form-control" v-model="form.uname" />
</form>
</div>
</template>
<script>
import axios from "axios";
export default {
data: function() {
return {
form: {
ucode: "",
uname: ""
}
};
},
methods: {
getUser() {
axios.get("api/checkUser/?ucode=" + this.form.ucode).then(res => {
this.form.uname = res.data[0].first_name;
});
}
}
};
</script>
OR you can just change the get query on the server side to simply return a single JSON object rather than an array and your js code should automatically start working:
$user = DB::table('resellers')
->where('username', $ucode)
->select('id', 'first_name')
->first();

Vue js with firebase not switching pages [duplicate]

This question already has answers here:
Is there something to auto update this code in vue?
(2 answers)
Closed 2 years ago.
So my problem is that when I log in with firebase and my mounted function should switch the component, I tried a lot of stuff, and nothing works. I just need a way to with what my router will switch the page after I sign in.
<template>
<div class="vue-tempalte" id="regForm">
<form>
<h1 id="middle">Sign In</h1>
<div class="form-group">
<label>Email address</label>
<input type="email" id="email" v-model="email" required />
</div>
<div class="form-group">
<label>Password</label>
<input type="password" id="password" v-model="password" required />
</div>
<button type="submit" #click="login" class="button is-light" id="btn1">
Sign In
</button>
</form>
</div>
</template>
<style scoped>
</style>
<script>
import firebase from "firebase";
export default {
name: "login",
data() {
return {
email: "",
password: "",
};
},
mounted: function () {
if (firebase.auth().currentUser) this.$router.replace("/HeaderLoggedIn");
},
methods: {
login: function () {
firebase
.auth()
.signInWithEmailAndPassword(this.email, this.password)
.then((user) => {
console.log(user.user);
});
},
},
};
</script>
The problem is in this code:
mounted: function () {
if (firebase.auth().currentUser) this.$router.replace("/HeaderLoggedIn");
},
Right now you're checking whether the user is signed in when the component is mounted. This happens once, while the user being authenticated at many times, since it is an asynchronous operatation.
You'll want to instead *listen for authentication state changes, as shown in the first snippet in the documentation on determining the signed in user:
mounted: function () {
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
this.$router.replace("/HeaderLoggedIn");
}
});
},
Instead of this method, you can try to set a global router.beforeEach method in your main.js file and check the auth state before entering each page and all in one place, not separate for each page then you can do something based on each state.

vue.js post list not updating after form submission

In my vue app I have two components one which is a form that posts the form data to my api. And the other gets and displays these posts in a section on the page. My issue is that when I submit a new post the posts lists aren't updated. The data stays the same unless I refresh the page. How can I get my posts list to update when I submit the form?
My Code:
client/src/App.vue
<template>
<div id="app">
<MainHeader :modalVisability="modal" v-on:showModal="toggleModal" />
<div id="content_wrap">
<Summary />
</div>
<OppForm :modalVisability="modal" />
</div>
</template>
<script>
import MainHeader from './components/MainHeader.vue';
import OppForm from './components/oppForm.vue';
import Summary from './components/Summary.vue';
export default {
name: 'App',
components: {
MainHeader,
Summary,
OppForm
},
data () {
return {
modal: false
}
},
methods: {
toggleModal (modalBool) {
this.modal = modalBool;
}
}
}
</script>
client/src/components/oppForm.vue
<template>
<div id="opp_form_modal" >
<form #submit.prevent="SubmitOpp" v-if="modalVisability">
<input type="text" name="company_name" v-model="company_name">
<button type="submit">Submit</button>
</form>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'oppForm',
props: {
modalVisability: Boolean,
},
data () {
return {
company_name: ''
}
},
methods: {
SubmitOpp () {
axios.post('http://localhost:5000/', {
company_name: this.company_name,
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
}
}
</script>
client/src/components/Summary.vue
<template>
<div id="summary_section">
<h2>Summary</h2>
<div id="summary_board">
<div class="column">
<div class="head">
<h3>Opportunities</h3>
</div>
<div class="body">
<div class="post"
v-for="(post, index) in posts"
:key="index"
>
<p class="company">{{ post.company_name }}</p>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return{
posts: []
};
},
created() {
axios.get('http://localhost:5000/')
.then(res => {
// console.log(res);
const data = res.data;
this.posts = data;
})
.catch(error => console.log(error));
}
}
</script>
The problem is that you're actually fetching your posts only on the app creation (i.e. inside the created() method).
You should wrap your axios call inside a function updatePosts() and then call it whenever you add a new post successfully, or you could create a custom event that is triggered whenever a new post is added.
created() is called only once (see vue lifecycle) so you fetch API before submitting form.
Try to add some console.log to understand what is called when.
You could use an global event bus and send form value as event data to summary. I could imagine also a solution where event is used to "tell" summary that form was submitted (just boolean, not data itself). In summary you then call API each time you receive event.
Or simple add an "update" button to summary to manually call API.
See Communication between sibling components in VueJs 2.0
or global vue instance for events for detailed examples.

VueJS - V-for doesn't re-render after data is updated and needs page refresh to see the change

So this code does adds or delete an entry, But whenever I add or delete, it does not show the changes or rather re-render. I need to refresh the page in order to see what changes had.
note: I am using ME(Vue)N stack.
I have this code:
<script>
import postService from '../../postService';
export default {
name: 'postComponent',
data() {
return {
posts: [],
error: '',
text: ''
}
},
async created() {
try {
this.posts = await postService.getPosts();
}catch(e) {
this.error = e.message;
}
},
methods: {
async createPost() {
await postService.insertPost(this.text)
this.post = await postService.getPosts();
// alert(this.post,"---")
},
async deletePost(id) {
await postService.deletePost(id)
this.post = await postService.getPosts();
// alert(this.post)
}
}
}
</script>
<template>
<div class="container">
<h1>Latest Posts</h1>
<div class="create-post">
<label for="create-post">input...</label>
<input type="text" id="create-post" v-model="text" placeholder="Create a post">
<button v-on:click="createPost">Post</button>
</div>
<!-- CREATE POST HERE -->
<hr>
<p class="error" v-if="error">{{error}}</p>
<div class="posts-container">
<div class="post"
v-for="(post) in posts"
v-bind:key="post._id"
v-on:dblclick="deletePost(post._id)"
>
{{ `${post.createdAt.getDate()}/${post.createdAt.getMonth()}/${post.createdAt.getFullYear()}`}}
<p class="text">{{ post.username }}</p>
</div>
</div>
</div>
</template>
sorry if there's an error in the snippet. I just needed to show the code and I cant make the script work on the code sample {}.
Any help would be appreciate. Vuejs beginner here.
This code is copied and typed through a youtube tutorial.
Your component has a data property posts, but you're assigning to this.post in several places in the code.
I suspect a typo, but it's also worth remembering that if this additional property (this.post) isn't available when the component is instantiated, it won't be (magically) converted into a reactive property when you create/assign to it.

Categories