vuejs this.$route not work - vue.js

when I send delete request to api it work well,
but next step I want to redirct to index,
so I use this code this.$router.push('/'); but it not working
index.vue
<template>
<div class="container">
<p>{{ message }}</p>
<p><a class="btn btn-primary" href="#/create">create</a></p>
<table class="table table-bordered">
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>edit</th>
<th>delete</th>
</tr>
</thead>
<tbody>
<tr v-for="user in users" v-bind="user" v-bind:key="user.id">
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td><a class="btn btn-warning" v-bind:href="'#/edit/'+ user.id">edit</a></td>
<td><a class="btn btn-danger" v-on:click="deleteUser(user)">delete</a></td>
</tr>
</tbody>
</table>
<nav aria-label="Page navigation example">
<ul class="pagination">
<li class="page-item"><a class="page-link" href="">Previous</a></li>
<li class="page-item"><a class="page-link" href="">1</a></li>
<li class="page-item"><a class="page-link" href="">Next</a></li>
</ul>
</nav>
</div>
</template>
<script>
var users = [
{id:'',name:''},
];
module.exports = {
data () {
return {
message:'',
users: users
}
},
created(){
this.fetchUsers();
},
methods: {
fetchUsers: function() {
axios.get('api/users').then(response => {
this.users = response.data.data;
})
},
deleteUser: function(user) {
axios.delete('api/users/'+user.id).then(response => {
})
this.$router.push('/');
},
}
}
</script>
index.js
var router = new VueRouter({
routes: [
{ path: '/', component: httpVueLoader('js/components/user/index.vue') },
{ path: '/create', component: httpVueLoader('js/components/user/create.vue') },
{ path: '/delete', component: httpVueLoader('js/components/user/delete.vue') },
{ path: '/edit/:id', component: httpVueLoader('js/components/user/edit.vue') },
],
});
new Vue({
el: '#app',
router:router,
template: '<router-view></router-view>',
});
new Vue({
el: '#foot',
components: {
'myfooter' : httpVueLoader('js/components/footer.vue'),
}
});
new Vue({
el: '#head',
components: {
'myheader' : httpVueLoader('js/components/header.vue'),
}
});

From the fact that I do not quite understand why you're creating multiple Vue.js instances, there is a way to accomplish this.
Instead of just creating a Vue instance with: new Vue(), assign it to a global variable: var vm1 = new Vue(). This way, you can access that Vue model via vm1.
// You probably have to assign it to the window object => window.vueApp = vueApp, because of the module bundler
var vueApp = new Vue({
el: '#app',
router:router,
template: '<router-view></router-view>',
});
var vueFoot = new Vue({
el: '#foot',
components: {
'myfooter' : httpVueLoader('js/components/footer.vue'),
}
});
var vueHead = new Vue({
el: '#head',
components: {
'myheader' : httpVueLoader('js/components/header.vue'),
}
});
Inside one of your Vue components:
<script>
export default {
// ...
methods: {
changeRoute() {
vueApp.$router.push(); //
}
},
}
</script>
I didn't tested it, but you get the idea.
You could also import the router and call the push method on that instance. Check out this answer
I would stick with the solution from that answer and create a little helper function. Something like redirect(). Everytime I need to redirect the user to something, this function will take care of that.

deleteUser: function(user) {
axios.delete('api/users/'+user.id).then(response => {
this.$router.push({
path: '/'
});
})
}
You have to use a routeObject like this.
Hopefully thats all. I don't see any other errors.
UPDATE: You are using more than one vue instance. This is as far as I know not good. Header and footer should be components included into your main App. And I do not know your httpVueLoader.

Related

After making a POST request to my heroku endpoint and saved it to my mongoDB, the data only shows if I refresh the page

I deployed my Vue app to Netlify and the backend to heroku. Everything works fine, I can edit, delete and get data from my database, except when I submit the form (creating a new client) and I redirect to this.$router.push("/tabela"); . The data is created, but when I go to the ListComponent.vue (path:'tabela') my data isn't there. It only shows when I refresh the page. Before deploying to heroku, I fixed the issue with window.location.href="/tabela"; instead this.$router.push but now, If I use window.location.href="/tabela" I cannot save to my database anymore. I need to use this.$router.push in order to make it "work" but as I said, then I need to refresh the page to update my table with the new client.
Here is my app https://cadastro-app.netlify.app/ .
CreateComponent.vue
methods: {
submitForm(){
if(this.cliente.cpf === ''){
this.cliente.cpf = 'Não Informado'
}else if(this.cliente.cnpj === ''){
this.cliente.cnpj = 'Não Informado'
}
axios.post('https://cadastro-backend-app.herokuapp.com/clientes', {
data: this.cliente
}).then(function(){
this.cliente = {
nome: '',
sobrenome: '',
email: '',
telefone: '',
cnpj: '',
cpf: ''
}
}).catch(function (error) {
console.log(error);
});
/* window.location.href="/tabela"; */
this.$router.push("/tabela");
}
}
ListComponent.vue
<template>
<div class="row">
<div class="col-md-12 ">
<div class="search">
<input #keyup.enter.prevent="search()" v-model='nomePesquisado' class="form-control mb-3" type="text" placeholder="Pesquisar" aria-label="Search"/>
</div>
<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th>Nome completo</th>
<th>Email</th>
<th>telefone</th>
<th>CNPJ</th>
<th>CPF</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="cliente in clientes" :key="cliente._id">
<td>{{ cliente.nome }}</td>
<td>{{ cliente.email }}</td>
<td>{{ cliente.telefone }}</td>
<td>{{ cliente.cnpj }}</td>
<td>{{ cliente.cpf }}</td>
<td>
<router-link :to="{name: 'edit', params: { id: cliente._id }}" class="btn btn-success">Editar
</router-link>
<button #click.prevent="removerCliente(cliente._id)" class="btn btn-danger">Remover</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
clientes: [],
nomePesquisado:''
}
},
created() {
let apiURL = 'https://cadastro-backend-app.herokuapp.com/clientes/';
axios.get(apiURL).then(res => {
this.clientes = res.data;
console.log(this.clientes);
}).catch(error => {
console.log(error)
});
},
methods: {
removerCliente(id){
const apiURL = `https://cadastro-backend-app.herokuapp.com/clientes/${id}`;
const indexOfArrayItem = this.clientes.findIndex(i => i._id === id);
if (window.confirm("Tem certeza que deseja remover este item?")) {
axios.delete(apiURL).then(() => {
this.clientes.splice(indexOfArrayItem, 1);
}).catch(error => {
console.log(error)
});
}
},
search(){
this.$router.push(`results/${this.nomePesquisado}`);
}
}
}
</script>
router index.js
import Vue from "vue";
import VueRouter from "vue-router";
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "home",
component: () => import("../components/CreateComponent")
},
{
path: "/tabela",
name: "tabela",
component: () => import("../components/ListComponent")
},
{
path: "/edit/:id",
name: "edit",
component: () => import("../components/EditComponent")
},
{
path: "/results/:id",
name: "results",
component: () => import("../components/Results")
}
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
export default router;
You are changing the route (this.$router.push("/tabela");) too early
This is what is happening:
You make a POST request
Without waiting for a request to complete, you are telling Vue router to switch to ListComponent (this.$router.push("/tabela");)
Router activates ListComponent component
ListComponent runs a GET request to the server in it's created hook
Result is a "race". Will POST request be fast enough so the GET request sees the new data ?
To be sure, move this.$router.push("/tabela"); inside then

Cant store api data called by axios in array through mounted, unless clicking on <Root> element from vue devtools (in browser)

i'm using axios to get data from api and store in an array after mounting then run a search query in the array later on, but it's not working unless i click on Root element in browsers Vue developer tools, after i click on vue Root element from vue dev tool everything works fine.Here is my code..
<script type="module">
const vueApp = new Vue({
el: "#pos",
data: {
searchTerm: "",
allProducts: [],
selectedProducts: [],
suggestions: []
},
mounted: function (){
axios.get("api/products").then( res => this.allProducts = res.data );
},
methods: {
select(item){
this.selectedProducts.push(item);
this.suggestions = [];
}
},
computed:{
matches(){
if(!this.searchTerm) return;
this.suggestions = this.allProducts.filter(sP=>(sP.prod_name).includes(this.searchTerm));
}
}
});
</script>
//HTML below------------------
<div id="pos">
<input type="text" v-model="searchTerm">
<ul v-for="match in suggestions">
<li #click="select(match)">
{{match.prod_name}}
</li>
</ul>
<table>
<tr v-for="(product,i) in selectedProducts">
<td>#{{product.prod_name}}</td>
</tr>
</table>
</div>
const vueApp = new Vue({
el: "#pos",
data: {
searchTerm: "",
allProducts: [],
selectedProducts: [],
suggestions: []
},
mounted: function() {
axios.get("api/products").then(res => this.allProducts = res.data);
},
methods: {
select(item) {
this.selectedProducts.push(item);
this.suggestions = [];
}
},
computed: {
matches() {
if (!this.searchTerm) return;
this.suggestions = this.allProducts.filter(sP => (sP.prod_name).includes(this.searchTerm));
}
}
});
<div id="pos">
<input type="text" v-model="searchTerm">
<ul v-for="match in suggestions">
<li #click="select(match)">
{{match.prod_name}}
</li>
</ul>
</div>
As I mentioned in the comments on your question, this is an error I cannot seem to understand how you are getting. I sense there is information that we are not being presented with.
As such, here is a quick "working" example of fetching items from the mounted lifecycle hook in a component. Note: If you are creating the component via a Single-File Component (.vue files) then don't worry too much about the declaration, pay attention only to the data and mounted methods.
const App = Vue.component('App', {
template: `<div>
<input v-model="searchTerm" type="search">
{{items.length}} results fetched
</div>`,
data() {
return {
searchTerm: '',
items: []
}
},
mounted() {
//Timeout used to mimic axios query
setTimeout(()=> this.items= [1,2,3,4], 1000)
}
});
const app = new App({
el: '#app'
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">Placeholder</div>
Edit
The code you have given us after your update seems to be working just fine. See the below snippet.
I noticed you are looping over suggestions but that value is never updated anywhere in your given code.
const vueApp = new Vue({
el: "#pos",
data: {
searchTerm: "",
allProducts: [],
selectedProducts: [],
suggestions: []
},
mounted: function() {
setTimeout(() => this.allProducts = [1,2,3,4,5], 1000);
},
methods: {
select(item) {
this.selectedProducts.push(item);
this.suggestions = [];
}
},
computed: {
matches() {
if (!this.searchTerm) return;
this.suggestions = this.allProducts.filter(sP => (sP.prod_name).includes(this.searchTerm));
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="pos">
<input type="text" v-model="searchTerm">
<ul v-for="match in suggestions">
<li #click="select(match)">
{{match.prod_name}}
</li>
</ul>
{{allProducts.length}} results loaded
</div>
mounted: function(){
var _self = this;
axios.get("api/products").then( res => _self.allProducts = res.data );
}

Vuetify data table creation

I'm looking for some simple tutorial to make data table with Vuetify.
I need first get my data from the JSON file, display it with first, middle, last name, email.
I want to use props.
Can you give me an idea of how to do this?
You can create a table child component with props and use that component by passing props.
Please check below working code snippet
new Vue({
el: '#app',
data: {
tableData: []
},
methods:{
onLoadDataClick(){
let self = this;
document.querySelector('.lds-roller').style.display="block";
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(json => {
document.querySelector('.lds-roller').style.display="none";
self.$data.tableData = json
})
}
},
components: {
'child' : {
template: `
<table style="width:100%;border-collapse: collapse;">
<tr>
<th>ID</th>
<th>Title</th>
<th>Body</th>
</tr>
<tr v-for="(item,key) in data" :key="key">
<td>{{item.id}}</td>
<td>{{item.title}}</td>
<td>{{item.body}}</td>
</tr></table>`,
props: ['data'],
watch: {
data: function(newVal, oldVal) { // watch it
console.log('Prop value changed: ', newVal, ' | was: ', oldVal)
}
}
}
}
});
.lds-roller{width:64px;height:64px;background-color:#00000075;position:absolute;border-radius:50%;z-index:9999;display:none}.lds-roller div{animation:lds-roller 1.2s cubic-bezier(.5,0,.5,1) infinite;transform-origin:32px 32px}.lds-roller div:after{content:" ";display:block;position:absolute;width:6px;height:6px;border-radius:50%;background:#fff;margin:-3px 0 0 -3px}.lds-roller div:nth-child(1){animation-delay:-36ms}.lds-roller div:nth-child(1):after{top:50px;left:50px}.lds-roller div:nth-child(2){animation-delay:-72ms}.lds-roller div:nth-child(2):after{top:54px;left:45px}.lds-roller div:nth-child(3){animation-delay:-108ms}.lds-roller div:nth-child(3):after{top:57px;left:39px}.lds-roller div:nth-child(4){animation-delay:-144ms}.lds-roller div:nth-child(4):after{top:58px;left:32px}.lds-roller div:nth-child(5){animation-delay:-.18s}.lds-roller div:nth-child(5):after{top:57px;left:25px}.lds-roller div:nth-child(6){animation-delay:-216ms}.lds-roller div:nth-child(6):after{top:54px;left:19px}.lds-roller div:nth-child(7){animation-delay:-252ms}.lds-roller div:nth-child(7):after{top:50px;left:14px}.lds-roller div:nth-child(8){animation-delay:-288ms}.lds-roller div:nth-child(8):after{top:45px;left:10px}#keyframes lds-roller{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}.as-console-wrapper{display:none!important}.btn{font-weight:700;cursor:pointer}td{border:1px solid #ccc}
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<div class="lds-roller" stypl="display:none;"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>
<button #click="onLoadDataClick" class="btn">Load data</button>
<br/> <br/>
<child :data="tableData"></child>
</div>

:class not updating when clicked in vuejs v-for

I want to add a css class to a item in v-for when the td in clicked
<template>
<div>
<h1>Forces ()</h1>
<section v-if="errored">
<p>We're sorry, we're not able to retrieve this information at the moment, please try back later</p>
</section>
<section v-if="loading">
<p>loading...</p>
</section>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>#</th>
<th>ID</th>
<th
#click="orderByName = !orderByName">Forces</th>
</tr>
<th>Delete</th>
</thead>
<tbody>
<tr v-for="(force, index) in forces" #click="completeTask(force)" :class="{completed: force.done}" v-bind:key="index">
<td>
<router-link :to="{ name: 'ListForce', params: { name: force.id } }">Link</router-link>
</td>
<th>{{ force.done }}</th>
<th>{{ force.name }}</th>
<th><button v-on:click="removeElement(index)">remove</button></th>
</tr>
</tbody>
</table>
<div>
</div>
</div>
</template>
<script>
import {APIService} from '../APIService';
const apiService = new APIService();
const _ = require('lodash');
export default {
name: 'ListForces',
components: {
},
data() {
return {
question: '',
forces: [{
done: null,
id: null,
name: null
}],
errored: false,
loading: true,
orderByName: false,
};
},
methods: {
getForces(){
apiService.getForces().then((data, error) => {
this.forces = data;
this.forces.map(function(e){
e.done = false;
});
this.loading= false;
console.log(this.forces)
});
},
completeTask(force) {
force.done = ! force.done;
console.log(force.done);
},
removeElement: function (index) {
this.forces.splice(index, 1);
}
},
computed: {
/* forcesOrdered() {
return this.orderByName ? _.orderBy(this.forces, 'name', 'desc') : this.forces;
}*/
},
mounted() {
this.getForces();
},
}
</script>
<style>
.completed {
text-decoration: line-through;
}
</style>
I want a line to go through the items when clicked, but the dom doesn't update. If I go into the vue tab in chrome I can see the force.done changes for each item but only if I click out of the object and click back into it. I'm not to sure why the state isn't updating as it's done so when I have used an click and a css bind before.
I've tried to make minimal changes to get this working:
// import {APIService} from '../APIService';
// const apiService = new APIService();
// const _ = require('lodash');
const apiService = {
getForces () {
return Promise.resolve([
{ id: 1, name: 'Red' },
{ id: 2, name: 'Green' },
{ id: 3, name: 'Blue' }
])
}
}
new Vue({
el: '#app',
name: 'ListForces',
components: {
},
data() {
return {
question: '',
forces: [{
done: null,
id: null,
name: null
}],
errored: false,
loading: true,
orderByName: false,
};
},
methods: {
getForces(){
apiService.getForces().then((data, error) => {
for (const force of data) {
force.done = false;
}
this.forces = data;
this.loading= false;
console.log(this.forces)
});
},
completeTask(force) {
force.done = ! force.done;
console.log(force.done);
},
removeElement: function (index) {
this.forces.splice(index, 1);
}
},
mounted() {
this.getForces();
}
})
.completed {
text-decoration: line-through;
}
<script src="https://unpkg.com/vue#2.6.10/dist/vue.js"></script>
<div id="app">
<div>
<h1>Forces ()</h1>
<section v-if="errored">
<p>We're sorry, we're not able to retrieve this information at the moment, please try back later</p>
</section>
<section v-if="loading">
<p>loading...</p>
</section>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>#</th>
<th>ID</th>
<th
#click="orderByName = !orderByName">Forces</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<tr v-for="(force, index) in forces" #click="completeTask(force)" :class="{completed: force.done}" v-bind:key="index">
<th>{{ force.done }}</th>
<th>{{ force.name }}</th>
<th><button v-on:click="removeElement(index)">remove</button></th>
</tr>
</tbody>
</table>
<div>
</div>
</div>
</div>
The key problem was here:
this.forces = data;
this.forces.map(function(e){
e.done = false;
});
The problem here is that the property done is being added to the data after it has been made reactive. The reactivity observers get added as soon as the line this.forces = data runs. Adding done after that counts as adding a new property, which won't work.
It's also a misuse of map so I've switched it to a for/of loop instead.
for (const force of data) {
force.done = false;
}
this.forces = data; // <- data becomes reactive here, including 'done'
On an unrelated note I've tweaked the template to move the Delete header inside the top row.
Make sure force.done is set to false in data before initialization so it is reactive.
data() {
return {
force:{
done: false;
}
}
}
If force exists but has no done member set, you can use Vue.set instead of = to create a reactive value after initialization.
Vue.set(this.force, 'done', true);

Vuejs does not render data from ajax

I use jQuery ajax to request api and get the respone, but the data cannot be rendered. Does someone know how to fix this problem?
var app = new Vue({
//router,
data: {
people: null
},
created: function() {
$.ajax({
url: 'test.php',
}).done(function(res){
console.log(res);
this.people = JSON.parse(res);
//console.log('124234234523');
//console.log(this.people.name);
});
}
}).$mount('#app');
<div id="app">
<ol>
<li v-for="person in people">
{{ person.name }}
</li>
</ol>
</div>
Code use vue router:
While I use Vue router, even I use arrow function. The template cannot be render by Vue. Whether do I misuse Vue router?
// Listing people component
var PeopleListing = Vue.extend({
template: '#people-listing-template',
data: function() {
return {
people: this.$parent.people
}
}
});
// Create the router
var router = new VueRouter({
mode: 'hash',
base: window.location.href,
routes: [
{path: '#/', component: PeopleListing},
{name: 'person', path: '/:id', component: PersonDetail }
]
});
var app = new Vue({
router,
data: {
people: null
},
created: function() {
$.ajax({
url: 'test.php',
}).done((res) =>{
//console.log(res);
this.people = JSON.parse(res);
//console.log('124234234523');
//console.log(this.people.name);
});
}
}).$mount('#app');
<div id="app">
<router-view class="view"></router-view>
</div>
<template id="people-listing-template">
<ul>
<li v-for="person in people">
{{ person.name }}
<router-link :to="{ name: 'person', params: { id: person.guid }}">View Details</router-link>
</li>
</ul>
</template>
Scope of this is creating issue, use arrow function like following:
var app = new Vue({
//router,
data: {
people: null
},
created: function() {
$.ajax({
url: 'test.php',
}).done((res) => {
console.log(res);
this.people = JSON.parse(res);
//console.log('124234234523');
//console.log(this.people.name);
});
}
}).$mount('#app');
You can get more details about this issue here.