Vue.js - search sort table with an image field - vue.js

I have a Vue.js component/view that shows the data as follows:
<tbody v-for="item in items">
<tr>
<td width="15%"><img :src="item.image"></td>
<td width="50%">{{item.name}}</td>
<td>{{item.purchasedate | moment(" MMMM Do YYYY") }}</td>
<td>${{item.price}}</td>
<td>Item destination link</td>
</tr>
</tobdy>
The data is powered by a simple axios get call that returns the items array. I need to implement a search and sort function. I have tried several out of box components. Including out of box components available on NPM e.g. vue-good-table, vue-table-component, and grid-component. There are two issues I am facing with these
1. The image cannot be displayed and it only returns the URL
2. Date cannot be formatted - I am using moment.js for that.
I would like to sort by name, price, and purchasedate while displaying the image. Any suggestions?

with vue-good-table,you can set column option like this:
columns: [
{
label: 'photo',
field: 'photo',
html: true
},
{
label: 'Name',
field: 'name',
filterOptions: {
enabled: true,
},
},
{
label: 'Age',
field: 'age',
type: 'number',
},
{
label: 'Created On',
field: 'createdAt',
formatFn: v=>moment(v).format(" MMMM Do YYYY")
},
{
label: 'Percent',
field: 'score',
type: 'percentage',
},
],
and data like this:
rows: [
{ id:1,photo:"/static/logo.png", name:"John", age: 20, createdAt: '201-10-31:9: 35 am',score: 0.03343 },
{ id:2,photo:"/static/logo.png", name:"Jane", age: 24, createdAt: '2011-10-31', score: 0.03343 },
{ id:3,photo:"/static/logo.png", name:"Susan", age: 16, createdAt: '2011-10-30', score: 0.03343 },
{ id:4,photo:"/static/logo.png", name:"Chris", age: 55, createdAt: '2011-10-11', score: 0.03343 },
{ id:5,photo:"/static/logo.png", name:"Dan", age: 40, createdAt: '2011-10-21', score: 0.03343 },
{ id:6,photo:"/static/logo.png", name:"John", age: 20, createdAt: '2011-10-31', score: 0.03343 },
{ id:7,photo:"/static/logo.png", name:"Jane", age: 24, createdAt: '20111031' },
{ id:8,photo:"/static/logo.png", name:"Susan", age: 16, createdAt: '2013-10-31', score: 0.03343 },
].map(o=>({
...o,
photo:`<img width="80" height="80" src="${o.photo}"/>`
}))
and the result is:

Related

VueJS errors when using external components

Let me preface this by saying that I'm new to VueJS and I expect the solution to my problem is something trivial but I can't for the life of me figure it out or find it online so here I am :
I followed Traversy Media's crash course on VueJS and built the task tracker app alongside him and everything was working well. But after the course ended, I decided to play around with Data Tables in the About page, specifically, using tables that have column filtering. Two candidates came up : VueGoodTable and VueBootstrap4Table.
I know for a fact that VueGoodTable works because I had already used it before with Laravel without really understanding how any of it works, but when I tried to import it here, I kept getting this error :
Code:
<template>
<div class="about">
<h1>This is an about page</h1>
<vue-good-table
:columns="columns"
:rows="rows"/>
</div>
</template>
<script>
import 'vue-good-table/dist/vue-good-table.css'
import { VueGoodTable } from 'vue-good-table';
export default {
components: {
VueGoodTable,
},
data(){
return {
columns: [
{
label: 'Name',
field: 'name',
},
{
label: 'Age',
field: 'age',
type: 'number',
},
{
label: 'Created On',
field: 'createdAt',
type: 'date',
dateInputFormat: 'yyyy-MM-dd',
dateOutputFormat: 'MMM do yy',
},
{
label: 'Percent',
field: 'score',
type: 'percentage',
},
],
rows: [
{ id:1, name:"John", age: 20, createdAt: '',score: 0.03343 },
{ id:2, name:"Jane", age: 24, createdAt: '2011-10-31', score: 0.03343 },
{ id:3, name:"Susan", age: 16, createdAt: '2011-10-30', score: 0.03343 },
{ id:4, name:"Chris", age: 55, createdAt: '2011-10-11', score: 0.03343 },
{ id:5, name:"Dan", age: 40, createdAt: '2011-10-21', score: 0.03343 },
{ id:6, name:"John", age: 20, createdAt: '2011-10-31', score: 0.03343 },
],
};
},
}
</script>
This code is literally copy-pasted from the Get Started page of the VueGoodTable documentation.
A different error also happens when I try to use VueBootstrap4Table instead :
Code:
<template>
<div class="about">
<h1>This is an about page</h1>
<vue-bootstrap4-table :rows="rows" :columns="columns" :config="config">
</vue-bootstrap4-table>
</div>
</template>
<script>
import VueBootstrap4Table from 'vue-bootstrap4-table'
export default {
data: function() {
return {
rows: [{
"id": 1,
"name": {
"first_name": "Vladimir",
"last_name": "Nitzsche"
},
"address": {
"country": "Mayotte"
},
"email": "franecki.anastasia#gmail.com",
},
{
"id": 2,
"name": {
"first_name": "Irwin",
"last_name": "Bayer"
},
"age": 23,
"address": {
"country": "Guernsey"
},
"email": "rlittle#macejkovic.biz",
},
{
"id": 3,
"name": {
"first_name": "Don",
"last_name": "Herman"
},
"address": {
"country": "Papua New Guinea"
},
"email": "delia.becker#cormier.com",
}],
columns: [{
label: "id",
name: "id",
filter: {
type: "simple",
placeholder: "id"
},
sort: true,
},
{
label: "First Name",
name: "name.first_name",
filter: {
type: "simple",
placeholder: "Enter first name"
},
sort: true,
},
{
label: "Email",
name: "email",
sort: true,
},
{
label: "Country",
name: "address.country",
filter: {
type: "simple",
placeholder: "Enter country"
},
}],
config: {
checkbox_rows: true,
rows_selectable: true,
card_title: "Vue Bootsrap 4 advanced table"
}
}
},
components: {
VueBootstrap4Table
}
}
</script>
I'm guessing that I'm not importing these components correctly somehow, so I would appreciate any help with this.
Thank you.
The unfortunate fact is that "not so recent" release of Vue v3 has bring some breaking changes from Vue 2 which require some migration
It is safe to say that very little of the existing components and component libraries created for Vue 2 work without any modification in Vue 3
The repo linked to the course shows that you are using Vue 3. But Both the vue-good-table or vue-bootstrap4-table are Vue 2 components and do not have a version for Vue 3 yet
So you need to look for different component and look for explicit support of Vue 3...

Vue Tables 2 custom row style

So I'm using vue tables 2 and found little problem.
Let's assume Im getting list of items and they have column called status, each status is constant and now I need to get translated values so making here relation status=key(constant).
Table with translated values has color which I'd like to use to fill row.
I see in documentation that there is rowClassCallback, but I'd to return inline style like: background-image: $color (for selected status).
Even in this function (rowClassCallback) I can't check value of color because it's in data.
Here in options rowClassCallback is example what I'd to make.
Vue.use(VueTables.ClientTable);
new Vue({
el: "#app",
data: {
columns: ['name', 'code', 'uri'],
data: getData(),
options: {
headings: {
name: 'Country Name',
code: 'Country Code',
uri: 'View Record'
},
editableColumns: ['name'],
sortable: ['name', 'code'],
filterable: ['name', 'code'],
rowClassCallback: row => {
return `background-color: ${this.getProperColor(row.id)}`;
}
}
},
methods: {
getProperColor(id) {
if (id === 245) {
return "#32CD32"
}
}
},
});
function getData() {
return [{
code: "ZW",
name: "Zimbabwe",
created_at: "2015-04-24T01:46:50.459583",
updated_at: "2015-04-24T01:46:50.459593",
uri: "http://api.lobbyfacts.eu/api/1/country/245",
id: 245
}, {
code: "ZM",
name: "Zambia",
created_at: "2015-04-24T01:46:50.457459",
updated_at: "2015-04-24T01:46:50.457468",
uri: "http://api.lobbyfacts.eu/api/1/country/244",
id: 244
}, {
code: "YE",
name: "Yemen",
created_at: "2015-04-24T01:46:50.454731",
updated_at: "2015-04-24T01:46:50.454741",
uri: "http://api.lobbyfacts.eu/api/1/country/243",
id: 243
}, {
code: "EH",
name: "Western Sahara",
created_at: "2015-04-24T01:46:50.452002",
updated_at: "2015-04-24T01:46:50.452011",
uri: "http://api.lobbyfacts.eu/api/1/country/242",
id: 242
}, {
code: "RS",
name: "Serbia",
created_at: "2015-04-24T01:46:50.342496",
updated_at: "2015-04-24T01:46:50.342501",
uri: "http://api.lobbyfacts.eu/api/1/country/196",
id: 196
}];
}
You can use similar method named rowAttributesCallback instead of rowClassCallback to pass your arguments to row.
options: {
editableColumns: ['name'],
sortable: ['name', 'code'],
filterable: ['name', 'code'],
rowAttributesCallback: row => {
return {"style": "color: red"};
}
}

Add router-link to Vuetify treeview

I have a vuetify treeview that I am trying to use for creating a menu. The treeview works fine however I am unable to add a router-link to Vuetify treeview using template. I have created a codepen here. What am I missing?
template:
<div id="app">
<v-app id="inspire">
<v-treeview open-all dense :items="items">
<template v-slot:prepend="{ item }">
<router-link v-bind:to="`{name:item.to, params:{domain:item.domain}`" >{{item.name}}</router-link>
</template>
</v-treeview>
</v-app>
</div>
script:
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
items: [
{
id: 1,
name: 'Applications :',
to:'applications',
domain:'clearcrimson',
children: [
{ id: 2, name: 'Calendar : app', to:'calendar',
domain:'clearcrimson'},
{ id: 3, name: 'Chrome : app', to:'chrome',
domain:'clearcrimson' },
{ id: 4, name: 'Webstorm : app', to:'webstorm',
domain:'clearcrimson' },
],
},
{
id: 5,
name: 'Documents :',
children: [
{
id: 6,
name: 'vuetify :',
children: [
{
id: 7,
name: 'src :',
children: [
{ id: 8, name: 'index : ts' },
{ id: 9, name: 'bootstrap : ts' },
],
},
],
},
{
id: 10,
name: 'material2 :',
children: [
{
id: 11,
name: 'src :',
children: [
{ id: 12, name: 'v-btn : ts' },
{ id: 13, name: 'v-card : ts' },
{ id: 14, name: 'v-window : ts' },
],
},
],
},
],
},
{
id: 15,
name: 'Downloads :',
children: [
{ id: 16, name: 'October : pdf' },
{ id: 17, name: 'November : pdf' },
{ id: 18, name: 'Tutorial : html' },
],
},
{
id: 19,
name: 'Videos :',
children: [
{
id: 20,
name: 'Tutorials :',
children: [
{ id: 21, name: 'Basic layouts : mp4' },
{ id: 22, name: 'Advanced techniques : mp4' },
{ id: 23, name: 'All about app : dir' },
],
},
{ id: 24, name: 'Intro : mov' },
{ id: 25, name: 'Conference introduction : avi' },
],
},
],
}),
})

BTable Filter with a Function

i've been struggling for almost 6 hours with this, but i didn't find a way to accomplish what i need.
the thing is that i need to filter the table of bootstrap vue with a function, but i can't make it work, there is a step that i need, but i can't find it.
here it is a jsfiddle that i grab from the web, that has the simple b-table with property filter.
https://jsfiddle.net/rothariger/oxbrhcqk/1/
now if you check on this example I've replaced the property for a function, but, it just get called in the load, when you change the filter textbox, it doesn't do anything, and here is where i think i'm missing a step.
https://jsfiddle.net/rothariger/oxbrhcqk/3/
new Vue({
el: '#app',
data: {
items: [{
isActive: true,
age: 40,
name: {
first: 'Dickerson',
last: 'Macdonald'
}
}, {
isActive: false,
age: 21,
name: {
first: 'Larsen',
last: 'Shaw'
}
}, {
isActive: false,
age: 9,
state: 'success',
name: {
first: 'Mitzi',
last: 'Navarro'
}
}, {
isActive: false,
age: 89,
name: {
first: 'Geneva',
last: 'Wilson'
}
}, {
isActive: true,
age: 38,
name: {
first: 'Jami',
last: 'Carney'
}
}, {
isActive: false,
age: 27,
name: {
first: 'Essie',
last: 'Dunlap'
}
}, {
isActive: true,
age: 40,
name: {
first: 'Dickerson',
last: 'Macdonald'
}
}, {
isActive: false,
age: 21,
name: {
first: 'Larsen',
last: 'Shaw'
}
}, {
isActive: false,
age: 26,
name: {
first: 'Mitzi',
last: 'Navarro'
}
}, {
isActive: false,
age: 22,
name: {
first: 'Geneva',
last: 'Wilson'
}
}, {
isActive: true,
age: 38,
name: {
first: 'Jami',
last: 'Carney'
}
}, {
isActive: false,
age: 27,
name: {
first: 'Essie',
last: 'Dunlap'
}
}],
fields: {
name: {
label: 'Person Full name',
sortable: true
},
age: {
label: 'Person age',
sortable: true
},
isActive: {
label: 'is Active'
},
actions: {
label: 'Actions'
}
},
currentPage: 1,
perPage: 5,
filter: null
},
methods: {
details(item) {
alert(JSON.stringify(item));
},
filterGrid(val) {
console.log(val);
return true;
}
}
})
any info on what i have to do?
regards.
As Vue Bootstrap introdues:,
The filter prop value can be a string, a RegExp or a function
reference. If a function is provided, the first argument is the
original item record data object. The function should return true if
the record matches your criteria or false if the record is to be
filtered out.
Then look into the source code at Vue Bootstrap Github, you will find Vue Bootstrap only invoke your filter function inside one computed property=computedItems.
So for your case:
filterGrid(val) {
console.log(val);
return true;
}
It does not trigger any reactivity (print then always return true), so it will do nothing (computed property=computedItems will not be re-calculated, so filter function will not be executed either).
so one simple filter function with reactivity will be like:
filterGrid(val){
return !this.filter || JSON.stringify(val).includes(this.filter)
}
Also you can involves other data/prop/computed property, the filter function will be executed also when reactivity is triggered.
The full demo:
new Vue({
el: '#app',
data: {
items: [{
isActive: true,
age: 40,
name: {
first: 'Dickerson',
last: 'Macdonald'
}
}, {
isActive: false,
age: 21,
name: {
first: 'Larsen',
last: 'Shaw'
}
}, {
isActive: false,
age: 9,
state: 'success',
name: {
first: 'Mitzi',
last: 'Navarro'
}
}, {
isActive: false,
age: 89,
name: {
first: 'Geneva',
last: 'Wilson'
}
}, {
isActive: true,
age: 38,
name: {
first: 'Jami',
last: 'Carney'
}
}, {
isActive: false,
age: 27,
name: {
first: 'Essie',
last: 'Dunlap'
}
}, {
isActive: true,
age: 40,
name: {
first: 'Dickerson',
last: 'Macdonald'
}
}, {
isActive: false,
age: 21,
name: {
first: 'Larsen',
last: 'Shaw'
}
}, {
isActive: false,
age: 26,
name: {
first: 'Mitzi',
last: 'Navarro'
}
}, {
isActive: false,
age: 22,
name: {
first: 'Geneva',
last: 'Wilson'
}
}, {
isActive: true,
age: 38,
name: {
first: 'Jami',
last: 'Carney'
}
}, {
isActive: false,
age: 27,
name: {
first: 'Essie',
last: 'Dunlap'
}
}],
fields: {
name: {
label: 'Person Full name',
sortable: true
},
age: {
label: 'Person age',
sortable: true
},
isActive: {
label: 'is Active'
},
actions: {
label: 'Actions'
}
},
currentPage: 1,
perPage: 5,
filter: null
},
methods: {
details(item) {
alert(JSON.stringify(item));
},
filterGrid(val){
return !this.filter || JSON.stringify(val).includes(this.filter)
}
}
})
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css"/>
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.css"/>
<!-- Add this after vue.js -->
<script src="https://unpkg.com/vue#2.5.17/dist/vue.min.js"></script>
<script src="https://unpkg.com/babel-polyfill#latest/dist/polyfill.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.js"></script>
<div id="app">
<div class="justify-content-centermy-1 row">
<b-form-fieldset horizontal label="Rows per page" class="col-6" :label-size="6">
<b-form-select :options="[{text:5,value:5},{text:10,value:10},{text:15,value:15}]" v-model="perPage">
</b-form-select>
</b-form-fieldset>
<b-form-fieldset horizontal label="Filter" class="col-6" :label-size="2">
<b-form-input v-model="filter" placeholder="Type to Search"></b-form-input>
</b-form-fieldset>
</div>
<!-- Main table element -->
<b-table striped hover :items="items" :fields="fields" :current-page="currentPage" :per-page="perPage" :filter="filterGrid">
<template slot="name" scope="item">
{{item.value.first}} {{item.value.last}}
</template>
<template slot="isActive" scope="item">
{{item.value?'Yes :)':'No :('}}
</template>
<template slot="actions" scope="item">
<b-btn size="sm" #click="details(item.item)">Details</b-btn>
</template>
</b-table>
<div class="justify-content-center row my-1">
<b-pagination size="md" :total-rows="this.items.length" :per-page="perPage" v-model="currentPage" />
</div>
</div>

How to configure the datasource for the Kendo Treeview?

This should be an easy one but I'm missing something. I have an MVC application that returns JSON data using this controller method:
public ActionResult GetVenues()
{
ActionResult ar = Json(_VenueRepository.GetData(), JsonRequestBehavior.AllowGet);
return ar;
}
Nothing fancy here. I'm displaying a Kendo treeview on my view using the following code:
var venuetree = function () {
$("#venuetreeview").kendoTreeView({
checkboxes: {
checkChildren: true
},
dataSource: [{ id: 0, text: "Venues", items: [{ id: 1, text: "Venue 1", items: [{ id: 5, text: "Venue 2" }] }, { id: 2, text: "Venue 3", items: [{ id: 14, text: "Venue 4" }] }, { id: 3, text: "Venue 5", items: [{ id: 38, text: "Venue 6" }, { id: 39, text: "Venue 7" }, { id: 25, text: "Venue 8" }, { id: 26, text: "Venue 9" }, { id: 27, text: "Venue 10" }, { id: 28, text: "Venue 11" }] }, { id: 30, text: "Venue 12" }, { id: 40, text: "Venue 13", items: [{ id: 41, text: "Venue 14" }] }, { id: 4, text: "Venue 15", items: [{ id: 29, text: "Venue 16" }] }, { id: 31, text: "Venue 17" }, { id: 32, text: "Venue 18" }] }]
//dataSource: new kendo.data.HierarchicalDataSource({
// transport: {
// read: {
// url: "DataManager/GetVenues",
// dataType: "json",
// contentType: "application/json"
// }
// },
// pageSize: 100,
// requestEnd: function (e) {
// $("#wait").hide();
// },
//})
}).data("kendoTreeView");
};
The hard-coded JSON here renders just fine. I obtained this JSON directly from the ActionResult object in the controller method.
However, when I uncomment the code that returns the HierarchicalDataSource (while commenting out the hard-coded version, of course) The treeview displays a Loading message with a wait animation. Note: same problem using DataSource as HierarchicalDataSource.
Any ideas why its acting this way?
Thanks
Carl
i use this
var dataSource = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: foo,
datatype: "json",
contentType: "application/json"
}
},
schema: {
model: {
children: "items",
id: "id"
},
data: function(data) {
var dataArray = eval(data);
return dataArray;
}
}
});
I think eval(data) is the solution.
I tried many things and after using eval it works :)