Error compiling template while trying to make email links in Vue - javascript

I am working on a small application that displays a "users" JSON in an HTML5 table. It uses Bootstrap 3 and Vue.
The code I have so far:
var app = new Vue({
el: '#app',
data () {
return {
users: null,
loading: true,
errored: false
}
},
mounted () {
axios
.get('https://jsonplaceholder.typicode.com/users')
.then(response => {
this.users = response.data
})
.catch(error => {
console.log(error)
this.errored = true
})
.finally(() => this.loading = false)
}
});
Vue.filter('lowercase', function (value) {
return value.toLowerCase();
})
<script src="https://unpkg.com/axios#0.18.0/dist/axios.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app" class="container">
<div class="panel panel-default table-container">
<div class="panel-heading">Users</div>
<div class="panel-body">
<table class="table table-striped table-bordered" id="dataTable">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Email</th>
<th>City</th>
</tr>
</thead>
<tbody>
<tr v-for="(user, index) in users">
<td>{{index + 1}}</td>
<td>{{user.name}}</td>
<td>{{user.email | lowercase}}</td>
<td>{{user.address.city}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
I want to turn the email addresses in the table into email links: <a :href="mailto:user.email | lowercase">{{user.email | lowercase}}.
The line above results in an Error compiling template and prevents the rendering of the table (even though <a :href="user.email | lowercase">{{user.email | lowercase}}does alow rendering.
Where am I wrong? What is a viable solution?

You are mixing up the mailto inside a string with those email addresses.
Try this:
<td><a :href="'mailto:' + user.email | lowercase">{{user.email | lowercase}}</a></td>
var app = new Vue({
el: '#app',
data () {
return {
users: null,
loading: true,
errored: false
}
},
mounted () {
axios
.get('https://jsonplaceholder.typicode.com/users')
.then(response => {
this.users = response.data
})
.catch(error => {
console.log(error)
this.errored = true
})
.finally(() => this.loading = false)
}
});
Vue.filter('lowercase', function (value) {
return value.toLowerCase();
})
<script src="https://unpkg.com/axios#0.18.0/dist/axios.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app" class="container">
<div class="panel panel-default table-container">
<div class="panel-heading">Users</div>
<div class="panel-body">
<table class="table table-striped table-bordered" id="dataTable">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Email</th>
<th>City</th>
</tr>
</thead>
<tbody>
<tr v-for="(user, index) in users">
<td>{{index + 1}}</td>
<td>{{user.name}}</td>
<td><a :href="'mailto:' + user.email | lowercase">{{user.email | lowercase}}</a></td>
<td>{{user.address.city}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>

My guess is that the | lowercase pipe / filter requires one argument and you're attempting to add two strings together ('mailto:' + user.email) immediately before it.
Try replacing with either: :href="('mailto:' + user.email) | lowercase"
or making 'mailto:' + user.email a computed property

Related

How to display data using DataTable fetched data from API?

I have data fetched form API. I want to display it into the DataTable.
The data is fetched from the API and it got displayed into the DataTable but I have problem in displaying the data. The data is displayed but it also give me
No data available in table
below is what I have tried
<div class="nk-block nk-block-lg">
<div class="nk-block-head">
<div class="nk-block-head-content">
<h4 class="nk-block-title">Data </h4>
<div class="nk-block-des">
<p>Policy</p>
</div>
</div>
</div>
<div class="card card-preview">
<div class="card-inner">
<table class="datatable-init table" id="datatable">
<thead>
<tr>
<th>#</th>
<th>Module</th>
<th>Policy & Terms of Services Details</th>
</tr>
</thead>
<tbody id="dataDetails">
</tbody>
</table>
</div>
</div>
<!-- .card-preview -->
</div>
<!-- nk-block -->
< script >
let cnt = 1;
$(document).ready(function() {
getList();
})
const getList = () => {
axios.get(`${url}getList`)
.then(function(res) {
if (res.data.status == 'success') {
res.data.result.map((e) => {
if (e.role_id == '3') {
$("#dataDetails").append(`
<tr>
<td>${cnt++}</td>
<td>${e.name}</td>
<td>${e.title}</td>
</tr>
`
);
}
})
}
})
}
<
/script>
How do I fix the problem ? Because inside the table have data, but it keep displaying the No data available in table
after adding the $("#datatable").DataTable(); inside the const
$("#dataDetails").append(`
<tr>
<td>${cnt++}</td>
<td>${e.name}</td>
<td>${e.title}</td>
</tr>
`
$("#datatable").DataTable();
);
I got error with Uncaught SyntaxError: missing ) after argument list
showing at this line

Vue 3 sorting - this.lists.sort is not a function

Vue 3 front-end template:
<template>
<div class="container">
<router-link to="/user/create" class="btn btn-success mt-5 mb-5">Add New</router-link>
<table class="table">
<thead>
<tr>
<th>#</th>
<th>Username</th>
<th>Email</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<button #click="sortBy('email')">Sort by email</button>
<button #click="sortBy('username')">Sort by Name</button>
<tr v-for="(item, index) in lists" :key="index">
<td scope="row">{{ index }}</td>
<td>{{ item.username}}</td>
<td>{{ item.email}}</td>
My method for sorting.
data() {
return {
lists: [], //filled in firebase by /get route
};
methods: {
sortBy(prop) {
this.lists.sort((a,b) => a[prop] < b[prop] ? -1 : 1)
},
When i try to click on a sort button by email or username i'm receiving the error sorts is not a functions.
You forgot to close the braces you opened for data() {}
data() {
return {
lists: [], //filled in firebase by /get route
};
},
methods: {
sortBy(prop) {
this.lists.sort((a,b) => a[prop] < b[prop] ? -1 : 1)
},

How to share data between two component in vuejs with Event Bus

I am trying to implement a global event bus in order to send a variable from component A to component B.
Here is the component A code:
data () {
return {
commandes: [],
}
},
envoyer() {
this.$eventBus.$emit('commande', this.commandes);
},
Here is the component B code:
<template>
<div class="container">
<div class="row justify-content-center">
<!-- Table row -->
<div class="row">
<div class="col-12 table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Qté</th>
<th>Produit</th>
<th>Subtotal</th>
</tr>
</thead>
<tbody>
<tr v-for="(commande, index) in commandes" :key="index">
<td>{{ commande.quantite }}</td>
<td>{{ commande.produit_id }}</td>
<td>{{ commande.montant }}</td>
</tr>
</tbody>
</table>
</div>
<!-- /.col -->
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
commande: [],
}
},
methods: {
},
mounted() {
this.$eventBus.$on('commande', (commandes) => {
this.commande = commandes;
console.log(commandes);
})
}
}
</script>
I'm getting this error when component B is displayed:
[Vue warn]: Property or method "commandes" is not defined on the instance but referenced during render.
How to solve this?
In your template you are referencing commandes
<tr v-for="(commande, index) in commandes" :key="index">
but your data doesn't return it, it returns commande
data() {
return {
commande: [],
}
}
Update your data and bus listeners:
data() {
return {
commandes: [],
}
}
...
this.$eventBus.$on('commande', (commandes) => {
this.commandes = commandes;
console.log(commandes);
})

not able to vue pass props to component's data

I am trying to pass the props in my component to the same component's data object. However, I am only getting null. Can anyone advise how I should approach this? It seems that my vue component is not able to get the props on initial rendering/load.
const teamInformationTemplate = {
template:
`
<div class="col-lg-6 col-md-12">
<div class="card card">
<!---->
<div class="card-header">
<h6 class="title">
TEAMS
</h6>
<br>
<select id="select_model_version" #change="get_team_information($event.target.value)" class="form-control form-control-sm form-group col-md-4">
<option v-for="team in teams" :value="team.team_id" :key="" :id="team.team_id">
{{ team.team_name }}
</option>
</select>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table tablesorter">
<thead class="text-primary">
<tr>
<th>#</th>
<th>Name</th>
</tr>
</thead>
<tbody class="">
<tr v-if="team_members!=null" v-for="(member, index) in team_members">
<td>{{index+1}}</td>
<td>{{member.firstname}}
</tr>
</tbody>
</table>
</div>
<!---->
<!---->
</div>
</div>
</div>
`,
props: ['teams', 'team_members', 'team_name'],
data() {
return {
template_teams : this.teams,
template_team_name : this.team_members,
template_team_members : this.team_name,
}
},
methods: {
get_team_information : function (team_id) {
$.post(js_local.ajaxurl, {
action: 'abcdefg',
team_id: team_id
}).done((data) => {
let parsed_data = JSON.parse(data)
}).fail(function (data) {
console.log('fail # { action : get_team_information }', data)
})
}
}
}
Try to initialize them inside the updated hook as follows:
data() {
return {
template_teams: [],
template_team_name: [],
template_team_members: [],
}
},
updated() {
this.template_teams = this.teams;
this.template_team_name = this.team_members;
this.template_team_members = this.team_name;
}

How to put content under certain headings

How to put content under certain headings?
I have two methods to load data
first axios.get('/api/get/headers')
second axios.get('api/get/contents')
I have no idea how correctly this will be done, given that the headers can be different and the content is correspondingly too
table example
<thead>
<tr>
<th v-for="header in headers" :data-key="header.name">{{ header.title }}</th>
</tr>
</thead>
<tbody>
<tr v-for="content in contents">
<td :data-key="content.name"> {{content.title}}</td>
</tr>
</tbody>
The global problem is that the content can be an array
Here's a one-page example of a way to use axios with Vue.js to get some simple content on the page. Does this help you get started?
<html>
<head>
<script src="http://unpkg.com/vue"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<div class="header">{{headerText}}</div>
<div class="content">{{contentText}}</div>
</div>
</body>
<script>
var vm = new Vue({
el: "#app",
data: function () {
return {
headerText: '',
contentText: ''
}
},
mounted: function () {
axios.get("/api/get/headers").then(response => {
this.headerText = response;
})
.catch(err => {
console.log(err);
});
axios.get("/api/get/content").then(response => {
this.contentText = response;
})
.catch(err => {
console.log(err);
});
}
});
</script>
</html>
Update:
For your specific example, could you go through the list of headers again and match the name property with the content name property, and then display the content? Like so:
<thead>
<tr>
<th v-for="header in headers" :data-key="header.name">{{ header.title }}</th>
</tr>
</thead>
<tbody>
<tr v-for="header in headers">
<td :data-key="header.name"> {{getContent(header.name).title}}</td>
</tr>
</tbody>
<script>
...
methods: {
getContent(name) {
for (var index in this.contents) {
if (this.contents[index].name === name) {
return this.contents[index];
}
}
}
}
...
</script>

Categories