I have an issue when I want to show data in VueJS. Previously I have successfully displayed "User Online" data, but the problem is why do I have to click on the page if I want to display the existing data? I want the data to be displayed automatically without having to click on page 1.
Here is the code:
data() {
return {
sales: [],
warehouses: [],
warehouse_id: "",
stock_alerts: [],
report_today: {
revenue: 0,
today_purchases: 0,
today_sales: 0,
return_sales: 0,
return_purchases: 0,
expenses: 0,
shipments: 0
},
products: [],
CurrentMonth: "",
loading: true,
echartSales: {},
echartProduct: {},
echartCustomer: {},
echartPayment: {},
users: {
data: [],
current_page: 1,
last_page: 1,
per_page: 10,
total: 0
},
currentPage: 1,
perPage: 10,
};
},
computed: {
totalPages() {
return this.users.last_page;
},
<!-- Status Online/Offline Users -->
<b-row>
<div class="col-md-12">
<div class="card mb-30">
<div class="card-body p-1">
<h5 class="card-title border-bottom p-3 mb-2">Online Users</h5>
<table class="table table-bordered data-table">
<thead>
<tr>
<th>No</th>
<th>Name</th>
<th>Email</th>
<th>Last Seen</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr v-for="(user, index) in users.data" :key="user.id">
<td>{{ index + 1 + ((users.current_page - 1) * users.per_page) }}</td>
<td>{{ user.username }}</td>
<td>{{ user.email }}</td>
<td>{{ user.last_seen_diff }}</td>
<td>
<span :class="{'text-success': user.status === 'Online', 'text-secondary': user.status === 'Offline'}">
{{ user.status }}
</span>
</td>
</tr>
</tbody>
</table>
<!-- Pagination Controls -->
<nav aria-label="Page navigation">
<ul class="pagination">
<li class="page-item" :class="{ disabled: users.current_page <= 1 }">
<a class="page-link" href="#" @click.prevent="changePage(users.current_page - 1)">Previous</a>
</li>
<li v-for="page in totalPages" :key="page" class="page-item" :class="{ active: page === users.current_page }">
<a class="page-link" href="#" @click.prevent="changePage(page)">{{ page }}</a>
</li>
<li class="page-item" :class="{ disabled: users.current_page >= totalPages }">
<a class="page-link" href="#" @click.prevent="changePage(users.current_page + 1)">Next</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</b-row>
And this method
//---------- Online/Offline Users --------------\
async getUsers(page = 1) {
this.loading = true;
console.log('Getting users for page:', page);
try {
console.log('Fetching data for page:', page);
const response = await axios.get('/online-user', {
params: {
page: page,
limit: this.perPage
}
});
console.log(response.data);
this.users = response.data;
this.currentPage = page;
this.loading = false;
} catch (error) {
console.error('There was an error!', error);
this.loading = false;
}
},
async changePage(page) {
if (page > 0 && page <= this.totalPages) {
this.currentPage = page;
await this.getUsers(page);
}
},
async mounted() {
await this.getUsers(this.currentPage);
},
2
Answers
I think if you use conditional rendering it will work, do something like this and check it again :
The problem with your current code is with users object and an array inside it. so changing in inner array can’t re-render the whole page, so by changing the loading state you can have re-render.
Directly assigning
this.users.data = response.data
can cause reactivity issues.To ensure proper reactivity in Vue.js, use:
Use code with caution.
This guarantees that Vue tracks the change and updates the view accordingly.
Alternatively, you might try:
Use code with caution.
However, this approach is less reliable and could lead to unexpected behavior.
Always prioritize this.$set for consistent reactivity.