how would you go about replacing the "image" data array in this example with an external JSON file? Basically I want to fetch/get this data externally with axios but something is not quite working yet in this example. Any clue very much appreciated!
I also created a CodePen for this example working without the external reference if you prefer to look at it this way. Thanks a lot!
https://codepen.io/FloydGekko/pen/eLoRBQ
This is the html, css and vue.js code:
<head>
<style>
[v-cloak] {
display: none;
}
.imageBlock{
width:100%;
margin:10px;
}
div.polaroid {
width:310px;
height:440px;
margin:10px;
background-color: white;
box-shadow: 6px 4px 8px 0 rgba(0, 0, 0, 0.2), 6px 6px 20px 0 rgba(0, 0, 0, 0.19);
margin-bottom: 25px;
border-radius: 18px
}
div.container {
text-align: center;
padding: 10px 20px;
}
</style>
</head>
<body>
<div id="vue" v-cloak>
<h2 align="center">
Show
<select v-model="currentKind" #change="onChange">
<option v-for="kind, index in kinds" :value="kind" :key="`kind_${index}`">{{kind ? kind : 'kind...'}}</option>
</select>
<select v-model="currentColor" #change="onChange">
<option v-for="color, index in colors" :value="color" :key="`kind_${index}`">{{color ? color : 'color...'}}</option>
</select>
and
<select v-model="currentShape" #change="onChange">
<option v-for="shape, index in shapes" :value="shape" :key="`kind_${index}`">{{shape ? shape : 'shape...'}}</option>
</select>
</h2>
<isotope
id="root_isotope"
ref="isotope"
:options='options'
:list="images"
align="center">
<div class="polaroid" align="center"
v-for="(image, index) in images"
class="imageBlock"
:key="image.id">
<a target="_blank" :href="image.url"><img border="0" :src="image.pic" alt=""
style="
border-radius: 20px;
display: block;
margin-left: auto;
margin-right: auto;
width: 100%;">
</a>
<div class="container">
<a target="_blank" :href="image.url">
<h3 align="center">{{image.title}}</h3>
</a>
<!--<h1>{{image.kind}}</h1>
<h1>{{image.color}}</h1>
<h1>{{image.shape}}</h1>
<h1>{{image.id}}</h1>-->
</div>
</div>
</isotope>
<h2 align="center">
<button #click="reset">Show all</button>
</h2>
</div>
<script src='https://unpkg.com/vue/dist/vue.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js'></script>
<script src='https://npmcdn.com/isotope-layout#3.0.6/dist/isotope.pkgd.min.js'></script>
<script src='https://rawgit.com/David-Desmaisons/Vue.Isotope/master/src/vue_isotope.js'></script>
<script src='https://unpkg.com/axios/dist/axios.min.js'></script>
<script>
let currentKind = null;
let currentColor = null;
let currentShape = null;
let imageSearchString = null;
var vm = new Vue({
el: '#vue',
data() {
return {
currentKind:'',
currentColor:'',
currentShape:'',
options: {
itemSelector: ".imageBlock",
getSortData: {
id: "id"
},
sortBy : "id",
getFilterData: {
Finder: function(itemElem) {
let kindSearch = currentKind ? itemElem.kind.indexOf(currentKind) !== -1 : true;
let colorSearch = currentColor ? itemElem.color.indexOf(currentColor) !== -1 : true;
let shapeSearch = currentShape ? itemElem.shape.indexOf(currentShape) !== -1 : true;
return kindSearch && colorSearch && shapeSearch
},
},
},
images: '',
};
},
computed: {
kinds(){
let allTags = _.flatten(this.images.map(image => image.kind))
return [''].concat(_.uniq(allTags))
},
colors(){
let allTags = _.flatten(this.images.map(image => image.color))
return [''].concat(_.uniq(allTags))
},
shapes(){
let allTags = _.flatten(this.images.map(image => image.shape))
return [''].concat(_.uniq(allTags))
},
},
mounted(){
setTimeout(()=>{
this.onChange()
}, 200)
},
created: function () {
this.loadImages();
},
methods: {
onChange: function() {
currentColor = this.currentColor;
currentShape = this.currentShape;
currentKind = this.currentKind;
this.$refs.isotope.filter('Finder');
this.$refs.cpt.layout('packery');
},
reset(){
currentColor = '';
currentShape = '';
currentKind = '';
this.currentColor = '';
this.currentShape = '';
this.currentKind = '';
this.onChange()
},
// THIS IS THE PART OF THE CODE IN QUESTION I THINK
loadImages: function () {
var vm = this;
axios.get('myimagedata.json')
.then(function (response) {
vm.images = response.data.images;
})
.catch(function (error) {
vm.images = 'An Error occured.' + error;
});
}
},
});
</script>
</body>
</html>
And this is the external JSON file "myimagedata.json" I try to load with axios:
{
"images": [
{
"id": 1,
"kind": ["A"],
"color": ["Green", "Blue"],
"shape": ["Square"],
"pic": "http://r.ddmcdn.com/s_f/o_1/cx_462/cy_245/cw_1349/ch_1349/w_720/APL/uploads/2015/06/caturday-shutterstock_149320799.jpg",
"url": "http://r.ddmcdn.com/s_f/o_1/cx_462/cy_245/cw_1349/ch_1349/w_720/APL/uploads/2015/06/caturday-shutterstock_149320799.jpg",
"title": "A"
},
{
"id": 2,
"kind": ["B"],
"color": ["Green", "Red"],
"shape": ["Circle"],
"pic": "https://www.kimballstock.com/pix/DOG/05/DOG-05-JE0078-01P.JPG",
"url": "https://www.kimballstock.com/pix/DOG/05/DOG-05-JE0078-01P.JPG",
"title": "B"
}
]
}
In axios you should be able to do something like is below. You may need to write a var self = this. External libs rewrite this as their own so to access the vue this variable you will need to set a variable beforehand and use the new variable to set your data. In the future please show your code in question like your loadImages() and the error if any you were getting.
var self = this
axios.get('/myimagedata.json')
.then(function (response) {
self.images = response.data.images
})
.catch(function (err) {
console.error(err)
})
With your json response here
{
"images": [{
"id": 1,
"kind": ["A"],
"color": ["Green", "Blue"],
"shape": ["Square"],
"pic": "http://r.ddmcdn.com/s_f/o_1/cx_462/cy_245/cw_1349/ch_1349/w_720/APL/uploads/2015/06/caturday-shutterstock_149320799.jpg",
"url": "http://r.ddmcdn.com/s_f/o_1/cx_462/cy_245/cw_1349/ch_1349/w_720/APL/uploads/2015/06/caturday-shutterstock_149320799.jpg",
"title": "A"
},
{
"id": 2,
"kind": ["B"],
"color": ["Green", "Red"],
"shape": ["Circle"],
"pic": "https://www.kimballstock.com/pix/DOG/05/DOG-05-JE0078-01P.JPG",
"url": "https://www.kimballstock.com/pix/DOG/05/DOG-05-JE0078-01P.JPG",
"title": "B"
}
]
}
Related
A common need for data binding is manipulating an element's class list and inline styles. Since class and style are both attributes, we can use v-bind to assign them a string value dynamically, much like with other attributes.
I want to have 2d array with turned on and off dates checked in component by v-if
interesting variable is dir.
<html>
<body>
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div class="container">
<h4>
Vue.js Expandable Tree Menu<br />
<small>(Recursive Components)</small>
</h4>
<div id="app">
<tree-menu :nodes="tree.nodes" :depth="0" :label="tree.label" :dir="dir"></tree-menu>
</div>
</div>
<script>
let tree = {
label: "root",
nodes: [
{
label: "item1",
nodes: [
{
label: "item1.1",
},
{
label: "item1.2",
nodes: [
{
label: "item1.2.1",
},
],
},
],
},
{
label: "item2",
},
],
};
Vue.component("tree-menu", {
props: ["nodes", "label", "depth", "dir"],
template: `
<div >
<div class="label-wrapper" #click="toggleChildren">
<div :style="indent" :class="labelClasses">
<i v-if="nodes" class="fa" :class="iconClasses"></i>
{{ label }}
</div>
</div>
<tree-menu
v-if="dir[0][0]"
v-for="node in nodes"
:nodes="node.nodes"
:label="node.label"
:depth="depth + 1"
:dir="dir"
>
</tree-menu>
</div>`,
data() {
return {
showChildren: false,
};
},
computed: {
iconClasses() {
return {
"fa-plus-square-o": !this.showChildren,
"fa-minus-square-o": this.showChildren,
};
},
labelClasses() {
return { "has-children": this.nodes };
},
indent() {
return { transform: `translate(${this.depth * 50}px)` };
},
},
methods: {
toggleChildren() {
this.dir[0][0] = !this.dir[0][0];
alert(this.dir[0][0]);
},
},
});
new Vue({
el: "#app",
data: {
tree,
dir: [
[1, 1, 1, 1, 1],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
],
},
});
</script>
<style>
body {
font-family: "Open Sans", sans-serif;
font-size: 18px;
font-weight: 300;
line-height: 1em;
}
.container {
width: 300px;
margin: 0 auto;
}
.tree-menu {
.label-wrapper {
padding-bottom: 10px;
margin-bottom: 10px;
border-bottom: 1px solid #ccc;
.has-children {
cursor: pointer;
}
}
}
</style>
</body>
</html>
I want to have 2d array with turned on and off dates that are checked by v-if.
I'm developing simple TodoList app using Laravle 9, VueJS 3, Vite bundler - all this built in tools
when creating Laravel fresh installation.
In app user can make CRUD operations with TodoItem and all user data saved on server, so
data preserved on page refresh.
Application almost finished, unless some strange bug: when I run app on local machine - all works perfectly, but when I deploy it on Heroku and open in browser - I see no todos in UI, although during installation some example todo rows already seeded in db.
I examined API - it returns data as expected:
[
{
"id": 67,
"text": "Thing1",
"is_done": false,
"is_urgent": false,
"created_at": "2022-08-24T09:16:37.000000Z",
"updated_at": "2022-08-24T09:16:37.000000Z"
},
{
"id": 68,
"text": "Buy milk",
"is_done": false,
"is_urgent": false,
"created_at": "2022-08-24T09:16:37.000000Z",
"updated_at": "2022-08-24T09:16:37.000000Z"
},
{
"id": 69,
"text": "Thing2",
"is_done": true,
"is_urgent": false,
"created_at": "2022-08-24T09:16:37.000000Z",
"updated_at": "2022-08-24T09:16:37.000000Z"
},
{
"id": 70,
"text": "Thing3",
"is_done": true,
"is_urgent": false,
"created_at": "2022-08-24T09:16:37.000000Z",
"updated_at": "2022-08-24T09:16:37.000000Z"
}
]
When I create new Todo in textbox request sends to server, and data saved on remote server - but on page refresh - I again get empty data in UI, althout i see in that data loaded
This is my App.vue
<template>
<div class="container mt-5" style="padding-left: 0 !important;">
<h3><span class="fw-bold text-warning">Simple</span> TodoList</h3>
</div>
<div class="container mt-4">
<div class="row">
<!-- Simple todos -->
<div class="col-md-6 py-3" style="border: 1px solid #ddd">
<p>Todos ({{ simpleTodos.length }})</p>
<ul>
<li :id="todo.id"
:key="todo.id"
:class="{ 'text-decoration-line-through': todo['is_done'], 'todo-item__link': true }"
v-for="todo in simpleTodos"
#click="contentVisible === todo.id ? contentVisible = false : contentVisible = todo.id">
{{ todo.text }}
</li>
</ul>
<input type="text" name="todo" id="todo.new" #keydown.enter="addTodo" placeholder="Type todo and press Enter" />
</div>
<!-- Urgent todos -->
<div class="col-md-6 py-3" style="border: 1px solid #ddd">
<p>Todos <span :class="{ 'text-danger': urgentTodos.length >= 3}">({{ urgentTodos.length }})</span></p>
<ul>
<li :id="todo.id"
:key="todo.id"
:class="{ 'text-decoration-line-through': todo['is_done'], 'todo-item__link': true }"
v-for="todo in urgentTodos"
#click="contentVisible === todo.id ? contentVisible = false : contentVisible = todo.id">
{{ todo.text }}
</li>
</ul>
</div>
</div>
</div>
</template>
<script>
import {getAllTodos, createTodo, removeTodo, toggleTodoCompleteStatus, toggleTodoUrgentStatus} from '../services/TodoService'
export default {
name: "App",
data() {
return {
allTodos: [],
contentVisible: false
}
},
mounted() {
this.getAllTodos();
},
computed: {
simpleTodos() {
return this.allTodos.filter(todo => todo['is_urgent'] === 0);
},
urgentTodos() {
return this.allTodos.filter(todo => todo['is_urgent'] === 1);
}
},
methods: {
getAllTodos()
{
getAllTodos()
.then(todos => {
console.log(todos)
this.allTodos = todos
})
.catch(err => {
alert('Error happened while fetching todos!');
console.error(err)
});
},
addTodo(e)
{
// return if value is empty
if(e.target.value.trim().length === 0)
return false;
const clientTodo = { text: e.target.value, is_done: 0, is_urgent: 0 }
createTodo(clientTodo).then(({ todo }) => {
this.allTodos.push(todo);
e.target.value = "";
});
},
}
}
</script>
<style scoped>
.todo-item__link {
cursor: pointer;
position: relative;
}
.todo-item__link .text-primary {
position: absolute;
padding-left: 10px;
}
.todo-item__link:hover {
text-decoration: underline;
}
</style>
I tring to use Vue Debug Tools - it shows empty allTodos list.
I don't unsderstand why this.getAllTodos() doesn't update state on mount
The problem is the is_done and is_urgent properties are Booleans in your API resonse, but your component is incorrectly comparing them to 0 and 1:
export default {
computed: {
simpleTodos() {
//return this.allTodos.filter(todo => todo['is_urgent'] === 0); ❌ Boolean is never a number
return this.allTodos.filter(todo => todo['is_urgent'] === false); ✅
// or
return this.allTodos.filter(todo => !todo.is_urgent); ✅
},
urgentTodos() {
//return this.allTodos.filter(todo => todo['is_urgent'] === 1); ❌ Boolean is never a number
return this.allTodos.filter(todo => todo['is_urgent'] === true); ✅
// or
return this.allTodos.filter(todo => todo.is_urgent); ✅
}
},
methods: {
addTodo(e) {
// const clientTodo = { text: e.target.value, is_done: 0, is_urgent: 0 } ❌ is_done and is_urgent should be Boolean
const clientTodo = { text: e.target.value, is_done: false, is_urgent: false } ✅
}
}
}
demo
I am trying to add multiple product in the cart. I am using vuejs and django rest framework. My problem is: When I add a product into the cart it added successfully But when I add another product it doesnt add. It adds the same product again and again.
For example:
I have three products named "A" and "B" and "C". I added "A". Then i try to add "C" in the cart. But it stills adds "A" in the cart. I cleared the session and tried again still add the "A" product if I try to add "C" product first. It always add "A" product.
Here is my store/index.js:
import { createStore } from 'vuex'
export default createStore({
state: {
cart: {
items: []
},
isAuthenticated: false,
token: '',
isLoading: false,
},
mutations: {
initializeStore(state){
if(localStorage.getItem('cart')){
state.cart = JSON.parse(localStorage.getItem('cart'))
}
else{
localStorage.setItem('cart', JSON.stringify(state.cart))
}
},
addToCart(state, item) {
let exists = state.cart.items.filter(i => i.product.id === item.product.id)
if (exists.length){
exists[0].quantity = parseInt(exists[0].quantity) + parseInt(item.quantity)
}
else{
state.cart.items.push(item)
}
localStorage.setItem('cart', JSON.stringify(state.cart))
}
},
actions: {
},
modules: {
}
})
Here is my add to cart page and code:
<template>
<br />
<div class="col">
<div class="col1">
<img v-bind:src="product.get_image" alt="">
</div>
<div class="col2">
<div class="product__title">
<p>PRODUCT TITLE</p>
<h2>{{ product.name }}</h2>
<small>{{ product.short_description }}</small>
</div>
<div class="product__price">
<p>Price: $ {{ product.price }}</p>
</div>
<div class="product__button">
<input type="hidden" v-model="quantity" min="1">
<button type="submit" class="button__primary" #click="addToCart">Add To Cart</button>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
import {toast} from 'bulma-toast'
export default {
name: "ProductDetail",
data () {
return {
product: {},
quantity: 1
}
},
mounted() {
this.getProduct()
},
methods: {
getProduct() {
const categorySlug = this.$route.params.category_slug
const productSlug = this.$route.params.product_slug
axios.get(`/api/product-details/${categorySlug}/${productSlug}/`)
.then(response => {
this.product = response.data
})
.catch(error => {
console.log(error)
})
},
addToCart() {
if(isNaN(this.quantity) || this.quantity < 1){
this.quantity = 1
}
const item = {
product: this.product,
quantity: this.quantity
}
this.$store.commit("addToCart", item)
toast({
message: "Product has been added to cart" + item.product.name,
type: "is-success",
pauseOnHover: true,
duration: 2000,
position: "bottom-right",
dismissible: true,
})
}
}
}
</script>
<style scoped>
.col {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 5rem;
height: 50vh;
padding: 60px;
}
.col1 {
height: 520px;
width: 100%;
}
.col1 img{
object-fit: fill;
height: 520px;
width: 100%;
}
.col2 {
display: grid;
grid-auto-rows: 1fr 1fr 1fr 1fr;
background: #fff;
padding: 12px;
}
.product__button button{
height: 40px;
width: 100%;
border: none;
background: #007bc4;
color: #fff;
border-radius: 3px;
}
.product__price p {
color: #007bc4;
font-size: 18px;
}
</style>
Here is the cartitem component:
<template>
<tr class="is-fullwidth">
<td>{{ item.product.name }}</td>
<td>$ {{ item.product.price }}</td>
<td>
<button #click="increment(item)" class="plusButton">+</button>
{{ item.quantity }}
<button #click="decrement(item)" class="minusButton">-</button>
</td>
<td>{{ getTotal(item).toFixed(2) }}</td>
<td><button class="delete"></button></td>
</tr>
</template>
<script>
export default {
name: "Cartitem",
props: {
initialItem: Object
},
data() {
return {
item: this.initialItem
}
},
methods: {
getTotal(item) {
return item.quantity * item.product.price
},
increment(item){
item.quantity += 1
this.updateCart()
},
decrement(item) {
item.quantity -= 1
if(item.quantity === 0){
this.$emit('removeFromCart', item)
}
this.updateCart()
},
updateCart() {
localStorage.setItem('cart', JSON.stringify(this.$store.state.cart))
},
removeFromCart(item) {
this.$emit('removeFromCart', item)
this.updateCart()
}
}
}
</script>
<style scoped>
.plusButton{
border: none;
background: #fff;
font-size: 19px;
}
.minusButton{
border: none;
background: #fff;
font-size: 19px;
}
</style>
I am new in vue js. I am trying to build this projetc so that i can learn. But this issue is eating my brain. I tried to use find function in sotre/index.js. It solved my problem though but if i clear the cookies and try to add product it gives me error.
is there any solution for me?
Thanks in advance.
I have a table in a component, which I render into another component however, when I render the component inside of another component, it is not appearing, and due to the complete lack of errors I can't even proceed. I've checked how I've imported etc and it seems correct. But perhaps someone can spot something I haven't. I'm very new to VueJs so apologies for the untrimmed code, I'm not 100% on what could be relevant yet.
File I'm Importing Into.vue
<template>
<div>
<b-table
:striped="striped"
:bordered="false"
:data="participants"
detailed
class="participant-table"
:row-class="() => 'participant-row'"
>
<InternalTable></InternalTable>
<b-table-column field="columnValue" v-slot="props2" class="attr-column">
<b-table
:bordered="false"
class="attr-table"
:striped="true"
:data="props2.row.columnValues"
>
<b-table-column field="columnName" v-slot="itemProps">
<SelectableAttribute
:attr-name="props2.row.fieldClass"
:attr-id="itemProps.row.id"
:model-id="itemProps.row.id"
model-name="NewParticipant"
>
{{ itemProps.row.value }}
</SelectableAttribute>
</b-table-column>
</b-table>
</b-table-column>
</b-table>
</div>
</template>
<script>
import { snakeCase } from "snake-case";
import InternalTable from './InternalTable'
import SelectableAttribute from '../groups/SelectableAttribute'
export default {
props: {
bordered: true,
striped: true,
participants: [
{
primaryAlias: '',
primaryEmail: '',
primaryAddress: '',
primaryPhone: '',
}
]
},
},
components: {
SelectableAttribute,
InternalTable
},
methods: {
tableDataToDataValueCells(participant) {
const fields = [
{ fieldName: 'companyNames', fieldClass: 'CompanyName' },
{ fieldName: 'aliases', fieldClass: 'Alias' },
{ fieldName: 'addresses', fieldClass: 'Address' },
{ fieldName: 'phones', fieldClass: 'Phone' },
{ fieldName: 'emails', fieldClass: 'Email' },
{ fieldName: 'birthdates', fieldClass: 'Birthdate' },
{ fieldName: 'customerNumbers', fieldClass: 'CustomerNumber' },
{ fieldName: 'ibans', fieldClass: 'BankAccount' },
];
let result = [];
fields.forEach(field => {
if (participant[field.fieldName].length > 0) {
result.push({
attributeName: field.fieldName,
columnName: I18n.t(`ccenter.participant.table.${snakeCase(field.fieldName)}`),
columnValues: participant[field.fieldName],
fieldClass: field.fieldClass,
})
}
});
return result;
}
}
}
</script>
<style>
.table tbody tr.detail:last-child td {
border-width: 1px !important;
}
.participant-table .participant-row td {
word-break: break-word;
font-size: 13px;
padding: 10px 5px;
}
.cell-action {
padding-left: 0px !important;
padding-right: 0px !important;
}
.cell-action .b-radio {
margin: 0px;
}
.attr-table table thead {
display: none;
}
.attr-table table td {
border: none;
}
.attrs-detail-container table tr td:nth-child(2) {
padding: 0 !important;
}
.attrs-detail-container table thead {
display: none;
}
</style>
InternalTable.Vue
<template>
<b-table :data="participants" detailed class="participant-table" :row-class="() => 'participant-row'">
<b-table-column field="primaryAlias" :label="t('participant.table.primary_alias')" v-slot="props">
<template v-if="props.row.primaryAlias">{{ props.row.primaryAlias.value }}</template>
<template v-else>-</template>
</b-table-column>
<b-table-column field="primaryEmail" :label="t('participant.table.primary_email')" v-slot="props">
<template v-if="props.row.primaryEmail">{{ props.row.primaryEmail.value }}</template>
<template v-else>-</template>
</b-table-column>
<b-table-column field="primaryAddress" :label="t('participant.table.primary_address')" v-slot="props">
<template v-if="props.row.primaryAddress">{{ props.row.primaryAddress.value }}</template>
<template v-else>-</template>
</b-table-column>
<b-table-column field="primaryPhone" :label="t('participant.table.primary_phone')" v-slot="props">
<template v-if="props.row.primaryPhone">{{ props.row.primaryPhone.value }}</template>
<template v-else>-</template>
</b-table-column>
<b-table-column v-slot="props" cell-class="cell-action">
<slot v-bind="props.row">
</slot>
</b-table-column>
<template slot="detail" slot-scope="props">
<b-table class="attrs-detail-container" :data="tableDataToDataValueCells(props.row)" cell-class="with-bottom-border">
<b-table-column field="columnName" v-slot="props">
<b>{{ props.row.columnName }}</b>
</b-table-column>
</b-table>
</template>
</b-table>
</template>
<script>
import { snakeCase } from "snake-case"
export default {
props: {
participants: {
type: Array,
}
},
methods: {
tableDataToDataValueCells(participant) {
const fields = [
{ fieldName: 'companyNames', fieldClass: 'CompanyName' },
{ fieldName: 'aliases', fieldClass: 'Alias' },
{ fieldName: 'addresses', fieldClass: 'Address' },
{ fieldName: 'phones', fieldClass: 'Phone' },
{ fieldName: 'emails', fieldClass: 'Email' },
{ fieldName: 'birthdates', fieldClass: 'Birthdate' },
{ fieldName: 'customerNumbers', fieldClass: 'CustomerNumber' },
{ fieldName: 'ibans', fieldClass: 'BankAccount' },
];
let result = [];
fields.forEach(field => {
if (participant[field.fieldName].length > 0) {
result.push({
attributeName: field.fieldName,
columnName: I18n.t(`ccenter.participant.table.${snakeCase(field.fieldName)}`),
columnValues: participant[field.fieldName],
fieldClass: field.fieldClass,
})
}
});
return result;
}
}
};
</script>
<style scoped>
.table tbody tr.detail:last-child td {
border-width: 1px !important;
}
.participant-table .participant-row td {
word-break: break-word;
font-size: 13px;
padding: 10px 5px;
}
.cell-action {
padding-left: 0px !important;
padding-right: 0px !important;
}
.cell-action .b-radio {
margin: 0px;
}
.attr-table table thead {
display: none;
}
.attr-table table td {
border: none;
}
.attrs-detail-container table tr td:nth-child(2) {
padding: 0 !important;
}
.attrs-detail-container table thead {
display: none;
}
</style>
What I see is that you trying to use props in your InternalTable.vue, which you used like this:
props: {
participants: {
type: Array,
}
}
In your Into.vue, you just call your component without providing these props. You should change:
<InternalTable></InternalTable>
to
<InternalTable :participants="participants"></InternalTable>
Looks like your b-table isn´t rendering because you didn´t provide data.
EDIT: Your data needs to be filled first
Currently, your array participants is empty, it just consists of:
participants: {
type: Array,
default: null,
}
In your InternalTable.vue you refer to primaryAlias, primaryEmail, primaryAddress and primaryPhone at your b-table-column´s. This data isn´t provided yet, thats why the table renders without data. You need to provide an array with a minimum structure of:
participants: [
{
primaryAlias: '',
primaryEmail: '',
primaryAddress: '',
primaryPhone: ''
}
]
I'm using Vuejs and dataTable for one of my project. I make an Ajax call and push data into an array. After that I use v-for to loop the data in the <tr> tag. Most of the time it doesn't work. The table loads as soon as the page has finished loading.. it takes a bit of time to receive the ajax data. Here is the output. It says no data available in the table
So the serch option doesn't work properly. I thought to use a setTimeout function (which was a bad idea) to load the table after a bit of time. What would be the proper way to do it? Sharing the code :
new Vue({
el: '#app',
data: {
entries: [],
},
methods:{
getData(){
var route = '/admin/temporary-enrolled-students';
this.$http.get(route).then((response)=>{
for(var i = 0; i< response.data.length;i++)
{
this.entries.push({
scId: response.data[i].id,
name: response.data[i].user.name,
phone: response.data[i].user.phone,
email: response.data[i].user.email,
courseId: response.data[i].course.id,
courseName: response.data[i].course.course_title,
expiryDate: response.data[i].expiry_date,
shares: response.data[i].number_of_shares,
expired: (response.data[i].expired == 1),
enrollDate: response.data[i].created_at
})
}
})
},
},
mounted(){
this.getData();
},
});
//data table
$(function () {
setTimeout(()=> {
$("#temp-enroll").DataTable({
"paging": true,
"ordering": false,
"info": true,
"autoWidth": false
});
},1000);
});
in blade:
Ok I tried this and working exactly what I have wanted. Thanks everyone for supporting.
new Vue({
el: '#app',
data: {
entries: [],
},
methods:{
getData(){
var route = '/admin/temporary-enrolled-students';
this.$http.get(route).then((response)=>{
for(var i = 0; i< response.data.length;i++)
{
this.entries.push({
scId: response.data[i].id,
name: response.data[i].user.name,
............................
......................
enrollDate: response.data[i].created_at
})
}
}).then(()=>{
$("#temp-enroll").DataTable({
"paging": true,
"ordering": false,
"info": true,
"autoWidth": false
});
});
},
},
mounted(){
this.getData();
},
});
I think someone mentioned that a computed property is the way to go, and that is what I would recommend as well.
The reason why is that as soon as your template makes a reference to the computed property, this triggers your ajax call. The page will then render any other available elements, and when your ajax call returns, it will then render the data it received. No special action in code is required.
Anyway, here is what it would look like...
In your html, as an example...
<table>
<tr v-for="item in serverData">
<td>{{item.name}}</td>
<td>{{item.someOtherValue}}</td>
</tr>
</table>
export default {
name: 'pets',
data () {
return {
}
},
computed: {
serverData: function() {
// ajax call using axios - returns a json array []
axios.get("http://localhost:8080/getSomeData")
.success(function(data) {
return data;
};
}
}
}
Notice the return in the success promise returned from the ajax call - there is no need to store the data to another variable (and you should definitely not have to loop through it like the noob coder example above shows. Do that on the server, return an array ready to render - if it isn't your web service, then write your own that calls the original and do the data manipulation there).
The parts of your template that reference the computed value will render after the data arrives - there is no need to watch it.
Hope this helps!
Vue is the bomb!
<template>
<div class="panel panel-default tablecontainer">
<div class="panel-heading">ChartBookin Import</div>
<br>
<div class='col-md-12'>
<div class='col-md-3'></div>
<div class='col-md-3'>
<div class="panel panel-default">
<div class="panel-body">
<commitChart :width="150"
:height="150"></commitChart>
</div>
</div>
</div>
<div class='col-md-3'>
<div class="panel panel-default">
<div class="panel-body">
<InboxMessage :width="150"
:height="150"></InboxMessage>
</div>
</div>
</div>
</div>
<div class="panel-body">
<div class='col-md-3'>
<label> by Account </label>
<select v-model="teamId" class="form-control" rows="3">
<option VALUE="" disabled> CHOISIR UN TEAM</option>
<option v-for="option in options" v-bind:value="option.id">{{option.name}}</option>
</select>
</div>
<div class='col-md-3'>
<label> by Date</label>
<div class="form-group">
<input type="text" class="form-control" name="daterange"
value="01/01/2017-01/31/2017"/>
</div>
</div>
<div class='col-md-5'></div>
<div class='col-md-1'>
<label>Records</label>
<div class="form-group">
<select v-model="elementsPerPage" class="form-control">
<option v-for="option in filtre" v-bind:value="option">
{{ option }}
</option>
</select>
</div>
</div>
<div id="sixthTable">
<table class="table-bordered table-striped table-bordered table-hover">
<thead>
<tr>
<th v-for=" (key,value) in rows[0]" v-on:click="sortTable(value)">{{value}}
<div class="arrow" v-if="value == sortColumn"
v-bind:class="[ascending ? 'arrow_up' : 'arrow_down']"></div>
</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-if=" rows.length > 0" v-for="row in rows">
<td v-for="(key, value) in row">{{ key }}</td>
<td>
<a :href="'/stat_booking_import/' + row.Id">
<span class="glyphicon glyphicon-eye-open"></span>
</a>
</td>
</tr>
<tr v-else> No Result Founded</tr>
</tbody>
</table>
<div class="pagination">
<div id="paginatebutton">
«
<a class="" v-for="i in num_pages()"
v-bind:class="[i == currentPage ? 'active' : '']"
v-on:click="change_page(i)">{{i}}
</a>
»
</div>
<div class="col-md-12" id="paginatetexte">
<p v-if="pages > (elementsPerPage*currentPage) ">
Showing 1 to {{elementsPerPage * currentPage }} of {{ pages }} records
</p>
<p v-else>
Showing 1 to {{pages}} of {{ pages }} records
</p>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Vue from 'vue';
import axios from 'axios';
import CommitChart from './Mail';
import InboxMessage from './Inbox';
export default {
components: {
CommitChart,
InboxMessage
},
data() {
return {
filtre: [10, 25, 50, 100],
option: 0,
options: [],
currentPage: 1,
elementsPerPage: 10,
pages: 0,
ascending: false,
sortColumn: '',
startdate: null,
enddate: null,
options: [],
teamId: null,
columns: [],
messages: [],
date: 0,
rows: {},
}
},
created() {
this.getData();
this.getTeams();
this.getMailInbox();
},
mounted() {
let vm = this;
$(document).ready(function () {
$('input[name="daterange"]').daterangepicker({
ranges: {
'Today': [moment(), moment()],
'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
'Last 7 Days': [moment().subtract(6, 'days'), moment()],
'This Month': [moment().startOf('month'), moment().endOf('month')]
},
locale: {
format: 'YYYY-MM-DD'
},
});
$('.applyBtn').click(function () {
vm.startdate = $("input[name=daterangepicker_start]").val();
vm.enddate = $("input[name=daterangepicker_end]").val();
vm.getData();
});
$('input[name="daterange"]').on('apply.daterangepicker', function (ev, picker) {
vm.startdate = $("input[name=daterangepicker_start]").val();
vm.enddate = $("input[name=daterangepicker_end]").val();
vm.getData();
});
});
},
watch: {
date: function () {
this.getData();
},
teamId: function () {
this.getData();
},
elementsPerPage: function () {
this.getData();
}
},
methods: {
getData() {
axios.get(`/admin/stat_booking_import.json/` + this.startdate + `/` + this.teamId + `/` + this.enddate + `/` + this.elementsPerPage + `?page=` + this.currentPage)
.then(response => {
this.rows = response.data.elements.data;
this.columns = Object.keys(this.rows[0]);
this.pages = response.data.elements.total_element;
})
.catch(e => {
this.errors.push(e)
})
},
getTeams() {
axios.get('/admin/team.json')
.then(response => {
this.options = response.data.data;
this.errors = [];
})
.catch(e => {
e.message = "aucun resultat trouvé essayer de choisir une autre date";
this.errors.push(e)
})
},
getMailInbox() {
axios.get(`/mailstorage.json`)
.then(response => {
this.messages = response.data.data;
console.log(this.messages);
})
.catch(e => {
this.errors.push(e)
});
},
sortTable(col) {
if (this.sortColumn === col) {
this.ascending = !this.ascending;
} else {
this.ascending = true;
this.sortColumn = col;
}
var ascending = this.ascending;
this.rows.sort(function (a, b) {
if (a[col] > b[col]) {
return ascending ? 1 : -1
} else if (a[col] < b[col]) {
return ascending ? -1 : 1
}
return 0;
})
},
num_pages() {
return Math.ceil(this.pages / this.elementsPerPage);
},
get_rows() {
var start = (this.currentPage - 1) * this.elementsPerPage;
var end = start + this.elementsPerPage;
return this.rows.slice(start, end);
},
change_page(page) {
this.currentPage = page;
this.getData();
}
},
}
</script>
<style type="text/css">
table {
width: 100%;
}
table td {
text-align: center;
}
table td {
text-align: center;
padding: 8px;
}
table td:last-child {
border-right: none;
}
.pagination {
display: inline-block;
}
.pagination a {
color: #3097D1;
float: left;
padding: 8px 16px;
text-decoration: none;
transition: background-color .3s;
border: 1px solid #ddd;
}
.pagination a.active {
background-color: #3097D1;
color: white;
border: 1px solid #3097D1;
}
.arrow_down {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB8AAAAaCAYAAABPY4eKAAAAAXNSR0IArs4c6QAAAvlJREFUSA29Vk1PGlEUHQaiiewslpUJiyYs2yb9AyRuJGm7c0VJoFXSX9A0sSZN04ULF12YEBQDhMCuSZOm1FhTiLY2Rky0QPlQBLRUsICoIN/0PCsGyox26NC3eTNn3r3n3TvnvvsE1PkwGo3yUqkkEQqFgw2Mz7lWqwng7ztN06mxsTEv8U0Aam5u7r5EInkplUol/f391wAJCc7nEAgE9Uwmkzo4OPiJMa1Wq6cFs7Ozt0H6RqlUDmJXfPIx+qrX69Ti4mIyHA5r6Wq1egND+j+IyW6QAUoul18XiUTDNHaSyGazKcZtdgk8wqhUKh9o/OMvsVgsfHJy0iWqVrcQNRUMBnd6enqc9MjISAmRP3e73T9al3XnbWNjIw2+KY1Gc3imsNHR0YV4PP5+d3e32h3K316TySQFoX2WyWR2glzIO5fLTSD6IElLNwbqnFpbWyO/96lCoai0cZjN5kfYQAYi5H34fL6cxWIZbya9iJyAhULBHAqFVlMpfsV/fHxMeb3er+Vy+VUzeduzwWC45XA4dlD/vEXvdDrj8DvURsYEWK3WF4FA4JQP9mg0WrHZbEYmnpa0NxYgPVObm5teiLABdTQT8a6vrwdRWhOcHMzMzCiXlpb2/yV6qDttMpkeshEzRk4Wo/bfoe4X9vb2amzGl+HoXNT29vZqsVi0sK1jJScG+Xx+HGkL4Tew2TPi5zUdQQt9otPpuBk3e0TaHmMDh1zS7/f780S0zX6Yni+NnBj09fUZUfvudDrNZN+GkQbl8Xi8RLRtHzsB9Hr9nfn5+SjSeWUCXC7XPq5kw53wsNogjZNohYXL2EljstvtrAL70/mVaW8Y4OidRO1/gwgbUMvcqGmcDc9aPvD1gnTeQ+0nmaInokRj0nHh+uvIiVOtVvt2a2vLv7Ky0tL3cRTXIcpPAwMDpq6R4/JXE4vFQ5FI5CN+QTaRSFCYc8vLy1l0rge4ARe5kJ/d27kYkLXoy2Jo4C7K8CZOsEBvb+9rlUp1xNXPL7v3IDwxvPD6AAAAAElFTkSuQmCC')
}
.arrow_up {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAaCAYAAACgoey0AAAAAXNSR0IArs4c6QAAAwpJREFUSA21Vt1PUmEYP4dvkQ8JFMwtBRocWAkDbiqXrUWXzU1rrTt0bdVqXbb1tbW16C9IBUSmm27cODdneoXjputa6069qwuW6IIBIdLvdaF4OAcOiGeDc87zPs/vd57P96WpFq7p6enbGo1mjKZpeTabjU1MTCRagGnOZHFxcXxtbe1XKpUq7+zslJeXl//Mz8+Hy+Uy3RxSE9qTk5M3otFooVQqgef4Wl9f343FYoEmoISrxuNxFX5f9vb2jhn/PxUKhfLS0tIPfFifUESRUMV8Pv/M6XReRm5rTGQyGeXxeGxYe1ezeBpBOBx2rKysbO7v79d4Wy3Y2Nj4GQqFbgnhaugxwiuGJx99Pp9FLBbXxYTXvTqd7v3MzIy6riIWGxJnMpl7AwMD14xGYyMsSq1WUyQdUqn0eSPlusQIsbGrq+vl4OCgvhFQZd1utyv1en0gEolcqsi47nWJlUrlG5fLZVcoFFy2nDKSDpIWlUoVTCQSEk4lCHmJMZ2GTCbTiMVikfIZ88l7enoos9l8dXt7+z6fDicxSJUokqDX6xXcl2wCROoc0vQCWL3sNfLOSdzR0fHY4XC4tVotl40gmVwup9xuN4OQv+UyqCFGH9rg7SOGYVRcBs3IEG4J0nVnamrqOtvuBDGGgQg9+wHFcVEi4a0LNkbdd6TrPKo8ODc311mteIIYjT/a398/jK+s1jnVM0kXoufCFvq0GuiIGEVgQIhfoygM1QrteEa9dAL7ITiYCt4RMabOK5AyKKzKWtvupLcRciu8D5J0EuDDPyT/Snd39yh6VtY2NhYQSR9G79Ds7OxdskRjEyAufvb7/cPoO5Z6e1+xtVKrq6vfcFzyi/A3ZrPZ3GdNSlwgo5ekE4X2RIQGf2C1WlufFE0GBeGWYQ8YERWLxQtnUVB830MKLZfL9RHir8lkssCn2G751tZWEWe03zTKm15YWPiEiXXTYDB0Ig/t7yd8PRws4EicwWHxO4jHD8/C5HiTTqd1BwcHFozKU89origB+y/kmzgYpgOBQP4fGmUiZmJ+WNgAAAAASUVORK5CYII=')
}
.arrow {
float: right;
width: 12px;
height: 15px;
background-repeat: no-repeat;
background-size: contain;
background-position-y: bottom;
}
.number {
display: inline-block;
padding: 4px 10px;
margin: 0px 5px;
cursor: pointer;
}
.number:hover,
.number.active {
background-color: #3097D1;
border-color: #3097D1;
}
#paginatetexte {
padding-top: 6%;
import Vue from 'vue'
new Vue({
el: '#statistique',
render: h => h(require('./StatBookingImport.vue'))
});
<style type="text/css">
table {
width: 100%;
}
table td {
text-align: center;
}
table td {
text-align: center;
padding: 8px;
}
table td:last-child {
border-right: none;
}
.pagination {
display: inline-block;
}
.pagination a {
color: #3097D1;
float: left;
padding: 8px 16px;
text-decoration: none;
transition: background-color .3s;
border: 1px solid #ddd;
}
.pagination a.active {
background-color: #3097D1;
color: white;
border: 1px solid #3097D1;
}
.arrow_down {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB8AAAAaCAYAAABPY4eKAAAAAXNSR0IArs4c6QAAAvlJREFUSA29Vk1PGlEUHQaiiewslpUJiyYs2yb9AyRuJGm7c0VJoFXSX9A0sSZN04ULF12YEBQDhMCuSZOm1FhTiLY2Rky0QPlQBLRUsICoIN/0PCsGyox26NC3eTNn3r3n3TvnvvsE1PkwGo3yUqkkEQqFgw2Mz7lWqwng7ztN06mxsTEv8U0Aam5u7r5EInkplUol/f391wAJCc7nEAgE9Uwmkzo4OPiJMa1Wq6cFs7Ozt0H6RqlUDmJXfPIx+qrX69Ti4mIyHA5r6Wq1egND+j+IyW6QAUoul18XiUTDNHaSyGazKcZtdgk8wqhUKh9o/OMvsVgsfHJy0iWqVrcQNRUMBnd6enqc9MjISAmRP3e73T9al3XnbWNjIw2+KY1Gc3imsNHR0YV4PP5+d3e32h3K316TySQFoX2WyWR2glzIO5fLTSD6IElLNwbqnFpbWyO/96lCoai0cZjN5kfYQAYi5H34fL6cxWIZbya9iJyAhULBHAqFVlMpfsV/fHxMeb3er+Vy+VUzeduzwWC45XA4dlD/vEXvdDrj8DvURsYEWK3WF4FA4JQP9mg0WrHZbEYmnpa0NxYgPVObm5teiLABdTQT8a6vrwdRWhOcHMzMzCiXlpb2/yV6qDttMpkeshEzRk4Wo/bfoe4X9vb2amzGl+HoXNT29vZqsVi0sK1jJScG+Xx+HGkL4Tew2TPi5zUdQQt9otPpuBk3e0TaHmMDh1zS7/f780S0zX6Yni+NnBj09fUZUfvudDrNZN+GkQbl8Xi8RLRtHzsB9Hr9nfn5+SjSeWUCXC7XPq5kw53wsNogjZNohYXL2EljstvtrAL70/mVaW8Y4OidRO1/gwgbUMvcqGmcDc9aPvD1gnTeQ+0nmaInokRj0nHh+uvIiVOtVvt2a2vLv7Ky0tL3cRTXIcpPAwMDpq6R4/JXE4vFQ5FI5CN+QTaRSFCYc8vLy1l0rge4ARe5kJ/d27kYkLXoy2Jo4C7K8CZOsEBvb+9rlUp1xNXPL7v3IDwxvPD6AAAAAElFTkSuQmCC')
}
.arrow_up {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAaCAYAAACgoey0AAAAAXNSR0IArs4c6QAAAwpJREFUSA21Vt1PUmEYP4dvkQ8JFMwtBRocWAkDbiqXrUWXzU1rrTt0bdVqXbb1tbW16C9IBUSmm27cODdneoXjputa6069qwuW6IIBIdLvdaF4OAcOiGeDc87zPs/vd57P96WpFq7p6enbGo1mjKZpeTabjU1MTCRagGnOZHFxcXxtbe1XKpUq7+zslJeXl//Mz8+Hy+Uy3RxSE9qTk5M3otFooVQqgef4Wl9f343FYoEmoISrxuNxFX5f9vb2jhn/PxUKhfLS0tIPfFifUESRUMV8Pv/M6XReRm5rTGQyGeXxeGxYe1ezeBpBOBx2rKysbO7v79d4Wy3Y2Nj4GQqFbgnhaugxwiuGJx99Pp9FLBbXxYTXvTqd7v3MzIy6riIWGxJnMpl7AwMD14xGYyMsSq1WUyQdUqn0eSPlusQIsbGrq+vl4OCgvhFQZd1utyv1en0gEolcqsi47nWJlUrlG5fLZVcoFFy2nDKSDpIWlUoVTCQSEk4lCHmJMZ2GTCbTiMVikfIZ88l7enoos9l8dXt7+z6fDicxSJUokqDX6xXcl2wCROoc0vQCWL3sNfLOSdzR0fHY4XC4tVotl40gmVwup9xuN4OQv+UyqCFGH9rg7SOGYVRcBs3IEG4J0nVnamrqOtvuBDGGgQg9+wHFcVEi4a0LNkbdd6TrPKo8ODc311mteIIYjT/a398/jK+s1jnVM0kXoufCFvq0GuiIGEVgQIhfoygM1QrteEa9dAL7ITiYCt4RMabOK5AyKKzKWtvupLcRciu8D5J0EuDDPyT/Snd39yh6VtY2NhYQSR9G79Ds7OxdskRjEyAufvb7/cPoO5Z6e1+xtVKrq6vfcFzyi/A3ZrPZ3GdNSlwgo5ekE4X2RIQGf2C1WlufFE0GBeGWYQ8YERWLxQtnUVB830MKLZfL9RHir8lkssCn2G751tZWEWe03zTKm15YWPiEiXXTYDB0Ig/t7yd8PRws4EicwWHxO4jHD8/C5HiTTqd1BwcHFozKU89origB+y/kmzgYpgOBQP4fGmUiZmJ+WNgAAAAASUVORK5CYII=')
}
.arrow {
float: right;
width: 12px;
height: 15px;
background-repeat: no-repeat;
background-size: contain;
background-position-y: bottom;
}
.number {
display: inline-block;
padding: 4px 10px;
margin: 0px 5px;
cursor: pointer;
}
.number:hover,
.number.active {
background-color: #3097D1;
border-color: #3097D1;
}
#paginatetexte {
padding-top: 6%;
}
#paginatebutton {
border-radius: 1px;
}
.tablecontainer {
margin-right: 2%;
margin-left: 2%;
}
.mailinbox {
margin-left: 1%;
}
</style>
<template>
<div class="panel panel-default tablecontainer">
<div class="panel-heading">ChartBookin Import</div>
<br>
<div class='col-md-12'>
<div class='col-md-3'></div>
<div class='col-md-3'>
<div class="panel panel-default">
<div class="panel-body">
<commitChart :width="150"
:height="150"></commitChart>
</div>
</div>
</div>
<div class='col-md-3'>
<div class="panel panel-default">
<div class="panel-body">
<InboxMessage :width="150"
:height="150"></InboxMessage>
</div>
</div>
</div>
</div>
<div class="panel-body">
<div class='col-md-3'>
<label> by Account </label>
<select v-model="teamId" class="form-control" rows="3">
<option VALUE="" disabled> CHOISIR UN TEAM</option>
<option v-for="option in options" v-bind:value="option.id">{{option.name}}</option>
</select>
</div>
<div class='col-md-3'>
<label> by Date</label>
<div class="form-group">
<input type="text" class="form-control" name="daterange"
value="01/01/2017-01/31/2017"/>
</div>
</div>
<div class='col-md-5'></div>
<div class='col-md-1'>
<label>Records</label>
<div class="form-group">
<select v-model="elementsPerPage" class="form-control">
<option v-for="option in filtre" v-bind:value="option">
{{ option }}
</option>
</select>
</div>
</div>
<div id="sixthTable">
<table class="table-bordered table-striped table-bordered table-hover">
<thead>
<tr>
<th v-for=" (key,value) in rows[0]" v-on:click="sortTable(value)">{{value}}
<div class="arrow" v-if="value == sortColumn"
v-bind:class="[ascending ? 'arrow_up' : 'arrow_down']"></div>
</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-if=" rows.length > 0" v-for="row in rows">
<td v-for="(key, value) in row">{{ key }}</td>
<td>
<a :href="'/stat_booking_import/' + row.Id">
<span class="glyphicon glyphicon-eye-open"></span>
</a>
</td>
</tr>
<tr v-else> No Result Founded</tr>
</tbody>
</table>
<div class="pagination">
<div id="paginatebutton">
«
<a class="" v-for="i in num_pages()"
v-bind:class="[i == currentPage ? 'active' : '']"
v-on:click="change_page(i)">{{i}}
</a>
»
</div>
<div class="col-md-12" id="paginatetexte">
<p v-if="pages > (elementsPerPage*currentPage) ">
Showing 1 to {{elementsPerPage * currentPage }} of {{ pages }} records
</p>
<p v-else>
Showing 1 to {{pages}} of {{ pages }} records
</p>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Vue from 'vue';
import axios from 'axios';
import CommitChart from './Mail';
import InboxMessage from './Inbox';
export default {
components: {
CommitChart,
InboxMessage
},
data() {
return {
filtre: [10, 25, 50, 100],
option: 0,
options: [],
currentPage: 1,
elementsPerPage: 10,
pages: 0,
ascending: false,
sortColumn: '',
startdate: null,
enddate: null,
options: [],
teamId: null,
columns: [],
messages: [],
date: 0,
rows: {},
}
},
created() {
this.getData();
this.getTeams();
this.getMailInbox();
},
mounted() {
let vm = this;
$(document).ready(function () {
$('input[name="daterange"]').daterangepicker({
ranges: {
'Today': [moment(), moment()],
'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
'Last 7 Days': [moment().subtract(6, 'days'), moment()],
'This Month': [moment().startOf('month'), moment().endOf('month')]
},
locale: {
format: 'YYYY-MM-DD'
},
});
$('.applyBtn').click(function () {
vm.startdate = $("input[name=daterangepicker_start]").val();
vm.enddate = $("input[name=daterangepicker_end]").val();
vm.getData();
});
$('input[name="daterange"]').on('apply.daterangepicker', function (ev, picker) {
vm.startdate = $("input[name=daterangepicker_start]").val();
vm.enddate = $("input[name=daterangepicker_end]").val();
vm.getData();
});
});
},
watch: {
date: function () {
this.getData();
},
teamId: function () {
this.getData();
},
elementsPerPage: function () {
this.getData();
}
},
methods: {
getData() {
axios.get(`/admin/stat_booking_import.json/` + this.startdate + `/` + this.teamId + `/` + this.enddate + `/` + this.elementsPerPage + `?page=` + this.currentPage)
.then(response => {
this.rows = response.data.elements.data;
this.columns = Object.keys(this.rows[0]);
this.pages = response.data.elements.total_element;
})
.catch(e => {
this.errors.push(e)
})
},
getTeams() {
axios.get('/admin/team.json')
.then(response => {
this.options = response.data.data;
this.errors = [];
})
.catch(e => {
e.message = "aucun resultat trouvé essayer de choisir une autre date";
this.errors.push(e)
})
},
getMailInbox() {
axios.get(`/mailstorage.json`)
.then(response => {
this.messages = response.data.data;
console.log(this.messages);
})
.catch(e => {
this.errors.push(e)
});
},
sortTable(col) {
if (this.sortColumn === col) {
this.ascending = !this.ascending;
} else {
this.ascending = true;
this.sortColumn = col;
}
var ascending = this.ascending;
this.rows.sort(function (a, b) {
if (a[col] > b[col]) {
return ascending ? 1 : -1
} else if (a[col] < b[col]) {
return ascending ? -1 : 1
}
return 0;
})
},
num_pages() {
return Math.ceil(this.pages / this.elementsPerPage);
},
get_rows() {
var start = (this.currentPage - 1) * this.elementsPerPage;
var end = start + this.elementsPerPage;
return this.rows.slice(start, end);
},
change_page(page) {
this.currentPage = page;
this.getData();
}
},
}
</script>
}
#paginatebutton {
border-radius: 1px;
}
.tablecontainer {
margin-right: 2%;
margin-left: 2%;
}
.mailinbox {
margin-left: 1%;
}
</style>
You could try watch property https://v2.vuejs.org/v2/guide/computed.html#Watchers. From the doc:
While computed properties are more appropriate in most cases, there
are times when a custom watcher is necessary. That’s why Vue provides
a more generic way to react to data changes through the watch option.
This is most useful when you want to perform asynchronous or expensive
operations in response to changing data.