i have created vue file to display data in frontend. but i'm unable to print 2 tables on same page at same time. only table 2 is displaying data , in first table it shows data for 2 seconds and than disappears. what i'm doing wrong? please help. i am super new in vuejs and have not much knowledge.
here is my index.vue file,
Table 1
<tbody>
<tr
v-show="items && items.length"
v-for="(data, i) in items"
:key="i">
<td></td>
<td></td>
</tr>
and this is function code,
async fetchData1() {
this.$store.state.operations.loading = true;
let currentPage = this.pagination ? this.pagination.current_page : 1;
await this.$store.dispatch("operations/fetchData", {
path: "/api/calldata?page=",
currentPage: currentPage + "&perPage=" + this.perPage,
});
table 2
<tbody>
<tr
v-show="items && items.length"
v-for="(data, i) in items"
:key="i">
<td></td>
<td></td>
</tr>
and here is the function for table 2
async fetchData2() {
this.Loading2 = true
let currentPage = this.Pagination2 ? this.Pagination2.current_page : 1;
await this.$store.dispatch("operations/fetchData", {
path: "/api/datacall/data2?page=",
currentPage: currentPage + "&perPage=" + this.perPage,
});
this.Loading2 = false;
and this are the controller functions
public function index(Request $request)
{
return DataResource::collection(Datamodl::with('user')->where('type',1)->latest()->paginate($request->perPage));
}
public function index2(Request $request)
{
return DataResource::collection(Datamodl::with('user')->where('type',0)->latest()->paginate($request->perPage));
}
And Route ,
Route::get('/calldata/data2', [DataController::class, 'index2']);
Route::apiResource('calldata', DataController::class);
Observation : You are updating same variable which is items for both the tables. Hence, it is overriding the latest items with the old items array.
Solution : Here is the implementation as per my comment.
new Vue({
el: '#app',
data: {
table1Items: null,
table2Items: null
},
mounted() {
this.fetchData1();
this.fetchData2();
},
methods: {
fetchData1() {
this.table1Items = [{
id: 1,
name: 'table 1 alpha'
}, {
id: 2,
name: 'table 1 beta'
}]
},
fetchData2() {
this.table2Items = [{
id: 1,
name: 'table 2 alpha'
}, {
id: 2,
name: 'table 2 beta'
}]
}
}
})
table, th, td {
border: 1px solid black;
margin: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<table>
<thead>
<th>ID</th>
<th>Name</th>
</thead>
<tbody>
<tr v-show="table1Items" v-for="(data, i) in table1Items" :key="i">
<td>{{ data.id }}</td>
<td>{{ data.name }}</td>
</tr>
</tbody>
</table>
<table>
<thead>
<th>ID</th>
<th>Name</th>
</thead>
<tbody>
<tr v-show="table2Items" v-for="(data, i) in table2Items" :key="i">
<td>{{ data.id }}</td>
<td>{{ data.name }}</td>
</tr>
</tbody>
</table>
</div>
you are using same property which is items for both. so second request will changed first items. so in both table same data will visible. you have to store in different state property for different data rendering.
solution :
make another action fetchData2.
call another mutation setItems2. add state propery item2: []. and setItems2 value from this mutation.
render second table like this.
<tr
v-show="items2.length"
v-for="(data, i) in items2"
:key="i">
<td></td>
<td></td>
</tr>
For code quailty:
give proper and related variable name . don't use items1 and items2 like that.
never used v-if/v-show and v-for in same element.for more info
use template first in this senerio.
use the item's unique id instead of the index in the key.
if you take the items default value as [], instead of null, then you only required to check items.length instead of items && items.length. so always use list default value []
if both requests are not dependent on each other then you should use Promise.all() for fetching data concurrently. which saved tremendous time and also in this case you don't require two loading property.
Related
When using v-for, I need to allocate a number of materials with a checkbox. But when you click on the checkbox, a group of materials is immediately highlighted. This is due to the fact that the Quantity parameter is the same for many materials. How do I make sure that when I click on the checkbox, only one material is highlighted and the Quantity value is added to checkedMaterials?
<table>
<thead>
<tr>
<th>#</th>
<th>Material name</th>
<th>Количество</th>
</tr>
</thead>
<tbody>
<tr v-for="material in materials">
<td><input type="checkbox" :value="material" v-model="checkedMaterials">
{{material.id}}
</td>{{ material.name }}</td>
<td>{{ material.Quantity }}</td>
</tr>
export default {
name: "Show",
data() {
return {
materials: '',
checkedMaterials: [],
}
},
mounted() {
this.getPart()
this.getMaterials()
},
methods: {
getPart() {
axios.get(`/api/part/${this.$route.params.id}`).then(res => {
this.part = res.data.data
})
},
getMaterials() {
axios.get('/api/material').then(res => {
this.materials = res.data.data;
})
},
},
}
take id as value instead of whole material.
<tr v-for="material in materials">
<td><input type="checkbox" :value="material.id" v-model="checkedMaterials">
{{material.id}}
</td>{{ material.name }}</td>
<td>{{ material.Quantity }}</td>
</tr>
make computed propery for getting quantity .
computed : {
allSelectedMaterial() {
return this.materials.filter((material) =>
this.checkedMaterials.includes(material.id) )
},
selectedMaterialQuantitry(){
return this.allSelectedMaterial.map((material) => material.quantity)
},
uniqueSelectedQuantity(){
return [...new Set(this.selectedMaterialQuantitry)]
}
},
code : https://jsfiddle.net/d9nwz4kt/35/
I have a Vue3 component that renders tables based on model data. Then I add DataTables functionality to the table to be able to filter and sorting data. Everything works fine. But if I click on the delete button I need to send a delete ajax request to the server and then on success redraw the whole table with new data. I tried to use draw() method but it does not work. Deleted rows are still in the table. I don't know if I need to remove the whole table and create it again or there is another solution.
This is the Vue template code.
<template>
<div class="table-responsive">
<table :id="id" class="table table-bordered nowrap" width="100%;">
<thead>
<tr>
<th>id</th>
<th>Title</th>
<th>Visible</th>
<th>User</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="article in articles" :key="article.id">
<td>{{article.id}}</td>
<td>{{article.title}}</td>
<td>{{article.visible}}</td>
<td>{{article.user.name}}</td>
<td>
delete
</td>
</tr>
</tbody>
</table>
</div>
</template>
And this is the deleteArticle() code
deleteArticle(id) {
axios.get( apiRoutes.ARTICLE_DELETE_URL + id )
.then( response => {
this.getArticles();
})
.catch( response => {
console.log(response);
});
},
getArticles()
{
axios.get( apiRoutes.ARTICLES_URL )
.then((response) => {
this.articles = response.data.articles;
this.$nextTick(function() {
this.setDataTable();
});
})
.catch((response) => {
console.log(response);
});
},
setDataTable() {
var table = $('#'+this.id);
if( this.dataTableObject )
{
this.dataTableObject.reload().draw(); // This is the code I need to fix
return;
}
...
},
What is the right flow of this component?
Im using jQuery datatables for displaying my data in my users component in Vue.js, but when I run my code it displays the data but it has some text that says "No data found". Can someone help me with this? I really don't have any idea because I'm new in this Frontend tools.
Users.vue:
<template>
<table id="table" class="table table-striped table-bordered">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Email</th>
<th>Type</th>
<th>Created</th>
</tr>
</thead>
<tbody>
<tr v-for="user in users" :key="user.id">
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.email }}</td>
<td>{{ user.type }}</td>
<td>{{ user.created_at }}</td>
</tr>
</tbody>
</table>
</template>
<script>
export default {
data() {
return {
users: [],
form: new Form({
id: "",
name: "",
email: "",
password: "",
type: ""
})
};
},
methods: {
loadUsers() {
axios.get("api/user").then(({ data }) => (this.users = data));
}
},
created() {
console.log("Component mounted.");
this.loadUsers();
}
};
$(document).ready(function() {
$("#table").DataTable({});
});
</script>
Probably, you should init your widget DataTable after receiving data from api, more precisely in then method.
axios.get("api/user").then(({ data }) => {
this.users = data;
this.$nextTick(() => {
$("#table").DataTable({});
});
});
Explanation about Vue.$nextTick:
Defer the callback to be executed after the next DOM update cycle. Use
it immediately after you’ve changed some data to wait for the DOM
update. This is the same as the global Vue.nextTick, except that the
callback’s this context is automatically bound to the instance calling
this method.
axios.get("api/user").then(({ data }) => {
this.users = data;
$(function() {
$("#table").DataTable({});
});
});
I created a web route that must delete a contact based on a specific id and it looks like this:
Route::delete('/api/deleteContact/{id}', 'ContactController#destroy');
Then inside the controller, I have the following:
public function destroy($id)
{
// delete a contact by id
return response()->json(Contact::whereId($id), 200);
}
Inside one of my blade template files, I call the Vue component which displays the list of contacts:
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Phone</th>
</tr>
</thead>
<tbody>
<tr v-for="contact in contacts">
<td> {{ contact.id }} </td>
<td> {{ contact.name }} </td>
<td> {{ contact.phone }} </td>
<td><button class="btn btn-secondary">Edit</button></td>
<td><button #click="deleteContact(contact.id)" class="btn btn-danger">Delete</button></td>
</tr>
</tbody>
</table>
The delete button calls the deleteContact method and received the contact id in question.
The method looks like this:
deleteContact(id){
axios.delete('/api/deleteContact/' + id)
.then(res => {
for(var i = 0; i < this.contacts.length; i++) {
if(this.contacts[i].id == id) {
this.contacts.splice(i, 1);
}
}
})
.catch(err => console.log(err));
}
When I click to delete, the promise(then) occurs, however, after refreshing the page, I noticed that nothing was deleted and I see no errors in the console.
How can I successfully delete the contact based on the id passed in the deleteContact function ?
You have to append delete at the end of query like this:
public function destroy($id)
{
// delete a contact by id
return response()->json(Contact::where('id',$id)->delete(), 200);
}
I want to send array of id's to backend with one button from vuejs table but i get error 500.
Logic
Check the check boxes
Collect the id's
Send id's to back-end when click on button
update the view
Code
template
<table class="table table-dark table-hover table-bordered table-striped">
<thead>
<tr>
<th class="text-center" width="50">
//the button
<button class="btn btn-outline-danger" #click="withdraw(index)">Withdraw</button>
</th>
<th class="text-center" width="50">#</th>
<th class="text-center">Amount</th>
</tr>
</thead>
<tbody>
<tr v-for="(income,index) in incomes" v-bind:key="index">
<td class="text-center">
//check box input
<input v-if="income.withdraw == '0'" type="checkbox" :id="income.id" :value="income.amount" v-model="checkedNumbers">
</td>
<td class="text-center">{{index+1}}</td>
<td class="text-center">Rp. {{formatPrice(income.amount)}}</td>
</tr>
<tr>
<td colspan="2"></td>
<td>
<span>Withdraw for today, Sum: <br> Rp. {{ formatPrice(sum) }}</span>
</td>
</tr>
</tbody>
</table>
script
export default {
data() {
return {
incomes: [],
checkedNumbers: [],
}
},
computed: {
sum() {
return this.checkedNumbers.reduce(function (a, b) {
return parseInt(a) + parseInt(b);
}, 0);
}
},
methods: {
withdraw(index) {
let checkedids = this.incomes[index]
axios.post(`/api/withdrawbutton/`+checkedids).then(response => {
this.income[index].withdraw = '1'
this.$forceUpdate()
});
}
}
}
route
Route::post('withdrawbutton/{id}', 'IncomeController#withdrawbutton');
controller
public function withdrawbutton($id)
{
$dowithdraw = Income::where('id', $id)->get();
$dowithdraw->withdraw = '1';
$dowithdraw->save();
return response()->json($dowithdraw,200);
}
Any idea where is my mistake and how to fix it?
......................................................................................................................
Don't send the list as a GET parameter, send it as a POST:
let params = {}
params.ids = this.checkedNumbers
axios.post(`/api/withdrawbutton/`, params)
.then(response => {
this.income[index].withdraw = '1'
this.$forceUpdate()
});
Controller
public function withdrawbutton(Request $request)
{
$dowithdraws = Income::whereIn('id', $request->input('ids', []));
$dowithdraws->update(['withdraw' => '1']);
return response()->json($dowithdraws->get(), 200);
}
Route
Route::post('withdrawbutton/', 'IncomeController#withdrawbutton');
And I don't think you need to update anything in the front because you already have them checked (if you want to keep them checked)