I'm trying to use this code hosting on Firebase, but it doesn't work. {{Item.name}} appears instead of the value :(
I already tested the same code on Codepen and it worked. Does the firebase accept vue.min.js?
When deploying, the site displays the {{var}} instead of the table value in Google Sheets.
I'm trying to use this code hosting on Firebase, but it doesn't work. {{Item.name}} appears instead of the value :(
I already tested the same code on Codepen and it worked. Does the firebase accept vue.min.js?
When deploying, the site displays the {{var}} instead of the table value in Google Sheets.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<script>
var app = new Vue({
el: '#app',
mounted() {
let vm = this
axios
.get(
'https://sheets.googleapis.com/v4/spreadsheets/{sheetsID}/values/A2:C20?key={apiKey}'
)
.then(function (response) {
let specials = response.data.values
for (let index = 0; index < specials.length; index++) {
const element = specials[index]
let mitem = {
name: element[0],
description: element[1],
price: element[2]
}
if (vm.isEven(index)) {
vm.menuItems_L = vm.menuItems_L.concat(mitem)
} else {
vm.menuItems_R = vm.menuItems_R.concat(mitem)
}
}
console.log(response)
})
},
data: {
menuItems_L: [],
menuItems_R: [],
menuStyle: {
background: '#f2f2f2',
color: '#000'
}
},
computed: {},
methods: {
isEven: function (n) {
return n % 2 == 0
}
}
});
</script>
<body>:
<div id="app">
<section id="specialssection" class="specials-container" v-if="menuItems_L" :style="menuStyle">
<div id="special_component" :style="menuStyle">
<div class="specials-table-container">
<table>
<tbody v-for="item in menuItems_L" :key="item.name">
<tr class="nameandprice">
<td>
<span :style="menuStyle">{{item.name}}</span>
</td>
<td>
<span :style="menuStyle">R${{item.price}}</span>
</td>
</tr>
<tr class="description">
<td colspan="2">{{item.description}}</td>
</tr>
</tbody>
</table>
<table>
<tbody v-for="item in menuItems_R" :key="`specialmenu-${item.name}`">
<tr class="nameandprice">
<td>
<span :style="menuStyle">{{item.name}}</span>
</td>
<td>
<span :style="menuStyle">${{item.price}}</span>
</td>
</tr>
<tr class="description">
<td colspan="2">{{item.description}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
</div>
It looks like the only thing wrong is the order of the tags.
You just need to run the vue code after the <div id="app"> tag is loaded into the DOM. Here's an example:
<html>
<head>
<!-- Include all CDN scripts here -->
</head>
<body>
<div id="app" >
</div>
<script>
// Needs to be called after the <div id="app"> tag is loaded into the DOM
var app = new Vue({
el: '#app',
...
})
</script>
</body>
</html>
Related
I am developing an e-commerce window and it was working perfectly until the part where I needed to add items to the cart. the browser console showed an error when I wanted to display the items in the cart. However, the strange thing is that it works perfectly in the incognito window. What could be the issue?
Below are my two files:
Code for the cart.vue file:
<template>
<div class="page-cart">
<div class="columns is-multiline">
<div class="column is-12">
<h1 class="title">Cart</h1>
</div>
<div class="column is-12 box">
<table class="table is-fullwidth" v-if="cartTotalLength">
<thead>
<tr>
<th>Product</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
<th></th>
</tr>
</thead>
<tbody>
<CartItem
v-for="item in cart.items"
v-bind:key="item.product.id"
v-bind:initialItem="item"
v-on:removeFromCart="removeFromCart"/>
</tbody>
</table>
<p v-else>Are you gonna stay hungry?...😕</p>
</div>
<div class="column is-12 box">
<h2 class="subtitle">Summary</h2>
<strong>Ksh{{ cartTotalPrice.toFixed(2) }}</strong>, {{ cartTotalLength }} items
<hr>
<router-link to="/cart/checkout" class="button is-dark">Proceed to checkout</router-link>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
import CartItem from '#/components/CartItem.vue'
export default {
name: 'Cart',
components: {
CartItem
},
data() {
return {
cart: {
items: []
}
}
},
mounted() {
this.cart = this.$store.state.cart
},
methods: {
removeFromCart(item) {
this.cart.items = this.cart.items.filter(i => i.product.id !== item.productid)
}
},
computed: {
cartTotalLength() {
return this.cart.items.reduce((acc, curVal) => {
return acc += curVal.quantity
}, 0)
},
cartTotalPrice() {
return this.cart.items.reduce((acc, curVal) => {
return acc += curVal.product.price * curVal.quantity
}, 0)
},
}
}
</script>
The following code is for a component, cartItem.vue:
<template>
<tr>
<td><router-link :to="item.product.get_absolute_url">{{ item.product.name }}</router-link></td>
<td>Ksh{{ item.product.price }}</td>
<td>
{{ item.quantity }}
<a #click="decrementQuantity(item)">-</a>
<a #click="incrementQuantity(item)">+</a>
</td>
<td>Ksh{{ getItemTotal(item).toFixed() }}</td>
<td><button class="delete" #click="removeFromCart(item)"></button></td>
</tr>
</template>
<script>
export default {
name: 'CartItem',
props: {
initialItem: Object
},
data() {
return {
item: this.initialItem
}
},
methods: {
getItemTotal(item) {
return item.quantity * item.product.price
},
decrementQuantity(item) {
item.quantity -= 1
if (item.quantity === 0) {
this.$emit('removeFromCart', item)
}
this.updateCart()
},
incrementQuantity(item) {
item.quantity += 1
this.updateCart()
},
updateCart() {
localStorage.setItem('cart', JSON.stringify(this.$store.state.cart))
},
removeFromCart(item) {
this.$emit('removeFromCart', item)
this.updateCart()
},
},
}
</script>
I also noted that the phone browser could not open some contents of the website on the network. Especially the contents from the server are not opened in my phone's browser. I am using Bulma CSS framework.
As I don't know the error from the console, I could only guess the problem.
You should try to use a different browser, or at least remove the data (cookies, storage) for your site, and see what happens. Perhaps there is some old previous data that would lead to a problem.
I am new to coding. I'm trying to make a simple website that pulls the data from my google spreadsheet. I am using Vue.js as it seems to be reasonably easy to cycle through my data to create a table. However, now I have a mix of code that honestly... I don't quite understand... created by me going through about 500 youtube and stackoverflow tutorials/responses.
But for some reason I can't get the data to pull from my spreadsheet. If someone can point me in the right direction on what exactly I'm doing wrong... I would be so grateful. =)
<template>
<div class="container">
<tbody>
<table style="width:100%">
<tr>
<th v-for="header in headers" :key="header">{{ header }}</th>
</tr>
<tr v-for="row in s" :key="row.a">
<td> {{ row.b}} </td>
<td> {{ row.c}} </td>
<td> {{ row.d}} </td>
<td> {{ row.e}} </td>
</tr>
</table>
<br>
<div v-for="item in items" :key="item.value">
<p>{{ item }}</p>
</div>
</tbody>
</div>
</template>
<style>
const { GoogleSpreadsheet } = require('google-spreadsheet');
const creds = require('creds.json');
import { vueGsheets } from 'vue-gsheets'
import axios from 'axios';
export default {
mixins: [vueGsheets],
data() {
return {
rows:[],
api: {
baseUrl: "https://sheets.googleapis.com/v4/spreadsheets/spreadsheetId/values:ranges=A!B1:F1?key=<key-here>",
"spreadsheetId": '<myid>',
get return() {
return this.return;
},
},
}
},
methods: {
getData(apiUrl) {
axios.get(apiUrl).then((res) => {
this.rows = res.data.valueRanges;
console.log(this.rows);
const { baseUrl } = this.api;
});
}
}
};
</script>
The problem is, that you try to enclose your JavaScript code in a <style> tag and close it with a <script> tag. That doesn´t work.
You have to use this structure:
<template>
// Your HTML
</template>
<script>
// Your Javsscript code
</script>
<style scoped>
// Your CSS
</style>
You can read more about the structure of Vue.js components here: Single File Components
I have a modal in my vue component, which is working well if I just put static text in it, so I know it's perfectly functional
However, trying to pass data from the table cell being clicked into the modal is failing and saying that name is undefined.
What am I doing wrong trying to pass data for each cell into this modal?
<div id="app">
<table>
<tbody>
<tr>
<td v-for="name in names" #click="showDetailModal = true"></td>
<td>#{{ name }}</td>
</tr>
</tbody>
</table>
<div class="modal-vue">
<!-- overlay to help with readability of modal -->
<div class="overlay" v-if="showDetailModal" #click="showDetailModal = false"></div>
<!-- Modal for detail on table cell click event -->
<div class="modal" v-if="showDetailModal">
<button class="close" #click="showDetailModal = false">x</button>
<h3>#{{ name.age }}</h3>
</div>
</div>
</div>
new Vue({
el: "#app",
props: {
},
data: {
showDetailModal: false,
names: [
{
"name":"Amy",
"age":37
},
{
"name":"James",
"age":39
}
]
}
})
Create another data property called currentItem then assign the click item to it when you click on the table row :
<div id="app">
<table>
<tbody>
<tr>
<td v-for="name in names" #click="showModal(name )"></td>
<td>#{{ name }}</td>
</tr>
</tbody>
</table>
<div class="modal-vue">
<!-- overlay to help with readability of modal -->
<div class="overlay" v-if="showDetailModal" #click="showDetailModal = false"></div>
<!-- Modal for detail on table cell click event -->
<div class="modal" v-if="showDetailModal">
<button class="close" #click="showDetailModal = false">x</button>
<h3>#{{ currentItem.age }}</h3>
</div>
</div>
</div>
new Vue({
el: "#app",
props: {
},
data: {
showDetailModal: false,
names: [
{
"name":"Amy",
"age":37
},
{
"name":"James",
"age":39
}
],
currentItem:{name:'',age:''}
},
methods:{
showModal(item){
this.showDetailModal = true;
this.currentItem=item
}
}
})
The reason for name resulting undefined is because it lives only inside the v-for loop.
For this reason, when the table gets clicked, you need to store which user has been clicked. This way, the modal can show the selected user based on that value.
The solution suggested from Boussadjra Brahim works great, however maybe it could be a little cleaner by removing showDetailModal data.
<div id="app">
<table>
<tbody>
<tr>
<td v-for="name in names" #click="showModal(name )"></td>
<td>#{{ name }}</td>
</tr>
</tbody>
</table>
<div class="modal-vue">
<!-- overlay to help with readability of modal -->
<div class="overlay" v-if="currentItem" #click="currentItem = false"></div>
<!-- Modal for detail on table cell click event -->
<div class="modal" v-if="currentItem">
<button class="close" #click="currentItem = false">x</button>
<h3>#{{ currentItem.age }}</h3>
</div>
</div>
</div>
new Vue({
el: "#app",
props: {
},
data: {
names: [
{
"name":"Amy",
"age":37
},
{
"name":"James",
"age":39
}
],
currentItem: false
},
methods:{
showModal(item){
this.currentItem=item
}
}
})
I have a problem making my iframe changing dynamically depending on what I hover.
I have the following code made in vue:
<template>
<div>
<div class="row">
<h2> Ad performance </h2>
</div>
<div class="row">
<div class="col-sm-6">
<table class="table table-hover">
<thead>
<tr>
<th scope="col">Client</th>
<th scope="col">Ad</th>
<th scope="col">Impressions</th>
</tr>
</thead>
<tbody>
<tr v-for="(ad, name) in adPerformance.slice(0,15)" :key="ad.adID">
<td>{{ad.client}}</td>
<td #mouseover="mouseEnter">{{ad.ad}}</td>
<td>{{ad.impressions}}</td>
</tr>
</tbody>
</table>
</div>
<div class="col-sm-6">
<h4> Desktop preview </h4>
<iframe src= "!!!Change this dynamically!!!"
v-show="toShowOnHover" #mouseleave="mouseLeave"
width="800" height="700">
</iframe>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
toShowOnHover: false,
};
},
props: ['adPerformance'],
components: {
},
methods: {
mouseEnter: function(){
this.toShowOnHover = !this.toShowOnHover;
},
mouseLeave: function(){
this.toShowOnHover = false;
}
},
created() {
},
};
</script>
On my local host server, I have tons of ad preview urls, that I want to dynamically change the src in the iframe depending on what Ad you hover.
The type of data on my local host look like this:
Can anyone help making a code to getting these previewURL's into the iframe?
Any help is appreciated!
First, bind the src attribute of the iframe to a variable. Then change the mouseover handler so that it can get the previewURL and set the variable you have chosen to this url.
On mouse leaves set the variable to null.
<template>
<div>
<div class="row">
<h2>Ad performance</h2>
</div>
<div class="row">
<div class="col-sm-6">
<table class="table table-hover">
<thead>
<tr>
<th scope="col">Client</th>
<th scope="col">Ad</th>
<th scope="col">Impressions</th>
</tr>
</thead>
<tbody>
<tr v-for="(ad) in adPerformance.slice(0,15)" :key="ad.adID">
<td>{{ad.client}}</td>
<td #mouseover="mouseEnter(ad.previewURL)">{{ad.ad}}</td>
<td>{{ad.impressions}}</td>
</tr>
</tbody>
</table>
</div>
<div class="col-sm-6">
<h4>Desktop preview</h4>
<iframe
:src="iframeURL"
v-show="toShowOnHover"
#mouseleave="mouseLeave"
width="800"
height="700"
></iframe>
</div>
</div>
</div>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
toShowOnHover: false,
iframeURL: null
};
},
props: ["adPerformance"],
components: {},
methods: {
mouseEnter: function(url) {
this.toShowOnHover = true;
this.iframeURL = url;
},
mouseLeave: function() {
this.toShowOnHover = false;
this.iframeURL = null;
}
},
created() {}
};
</script>
I think asking from people to make you your piece of code is not a good way of learning from problems, so I will just explain you what you could do and if you have any question just shoot!!
You can send into the #mouseover the previewURL as #mouseover="() => mouseEnter(ad.previewURL)"
You can create a local variable as previewURL, and in the mouseEnter function you can assign previewUrl with the parameter you are receiving.
So <iframe :src="previewURL" .../>
This previewURL variable is reactive so if you change it the iframe src will change as well.
I have several components on a page, and I find that updates to a parent object are reflected in one of the components, but not in the other.
The main page, PatientEditor.vue includes these components:
<notes-editor v-model="pt" />
<chart-completion v-model="pt" arrange="horiz" />
and has this script:
module.exports = {
props: ["pt"]
};
So, the pt object is in the parent, and it is passed to several components as a v-model
The component ChartCompletion.vue works well. It has these in it.
module.exports = {
props: ["value", "arrange"],
computed: {
completed_notes: function() {
return this.value.notes.filter(function(note) {
return note.signed_at;
}).length;
},
My problem child, however is the NotesEditor.vue template which contains the following:
module.exports = {
props: ["value"],
computed: {
completed_notes: function() {
return this.value.notes.filter(function(note) {
return note.signed_at;
}).length;
}
},
Not sure if it's important, but the notes object is populated from an ajax call in another component like this:
this.value.notes.splice(0, this.value.notes.length, ...response.body.notes);
this.$emit("input", this.value);
Sooooo, here's the problem.
When this.value.notes is updated, the results are seen in the ChartCompletion component, but they are not seen in the NotesEditor component. When I use the Vue debugger in chrome, I can see that the notes object is changed, but, for some reason, the computed property doesn't re-fire, even though it has the identical definition in the ChartCompletion component. Also, I have a v-for in NotesEditor that doesn't change either.
What is the best way to debug this?
EDIT 1 -- including the NotesEditor component
<template>
<span>
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Status</th>
<th>Audio</th>
<th>Text</th>
</tr>
</thead>
<tbody>
<tr v-for="n in value.notes" :key="n.id">
<th>{{n.created_at}}</th>
<td>{{n.note_status_id}}</td>
<td>
<span v-if="n.audio_length > 0">
<audio controls="controls" preload="none">
<source :src="audioURL(n.id)" type="audio/webm"> Your browser does not support the audio element.
</audio>
({{n.audio_length}}s)
</span>
<span v-else>
None
</span>
</td>
<td>
<span v-if="n.note_text">
<button data-toggle="tooltip" :title="n.note_text" class="btn btn-outline-primary btn-sm" #click.prevent="openChartEditor(n.id)">
<span class="glyphicon glyphicon-edit"></span> Edit Note ({{ n.note_text.length }} chars)
</button>
</span>
<span v-else>
<button class="btn btn-primary btn-sm" #click.prevent="openChartEditor(n.id)">
<span class="glyphicon glyphicon-pencil"></span> Create Note
</button>
</span>
</td>
</tr>
<tr>
<td colspan="3">
<record v-model="value" />
</td>
<td>
<button class="btn btn-primary" #click.prevent="openChartEditor(0)">
<span class="glyphicon glyphicon-pencil"></span> Create Note
</button>
</td>
</tr>
</tbody>
</table>
</span>
</template>
<script>
module.exports = {
props: ["value"],
data: function() {
return {
sendFaxWorking: false
};
},
computed: {
completed_notes: function() {
return this.value.notes.filter(function(note) {
return note.signed_at;
}).length;
}
},
methods: {
audioURL: function(id) {
return "/notes/getAudio/" + id;
},
openChartEditor: function(id) {
this.$root.$emit("showEditor", id);
}
}
};
</script>
<style>
audio {
vertical-align: middle;
border: 0;
margin: 0;
}
</style>
I don't think this is a good answer, but it does work. I added a watcher function that calls $forceUpdate()
mounted: function() {
this.$watch("value.notes", this.$forceUpdate);
},