How can I solve "Interpolation inside attributes has been removed. Use v-bind or the colon shorthand"? Vue.js 2 - vue.js

My Vue.js component is like this:
<template>
<div>
<div class="panel-group" v-for="item in list">
...
<div class="panel-body">
<a role="button" data-toggle="collapse" href="#purchase-{{ item.id }}" class="pull-right" aria-expanded="false" aria-controls="collapseOne">
Show
</a>
</div>
<div id="purchase-{{ item.id }}" class="table-responsive panel-collapse collapse" role="tabpanel">
...
</div>
</div>
</div>
</template>
<script>
export default {
...
computed: {
list: function() {
return this.$store.state.transaction.list
},
...
}
}
</script>
When executed, there exists an error like this:
Vue template syntax error:
id="purchase-{{ item.id }}": Interpolation inside attributes has
been removed. Use v-bind or the colon shorthand instead.
How can I solve it?

Use JavaScript code inside v-bind (or shortcut ":"):
:href="'#purchase-' + item.id"
and
:id="'purchase-' + item.id"
Or if using ES6 or later:
:id="`purchase-${item.id}`"

Use v-bind or shortcut syntax ':' to bind the attribute.
Example:
<input v-bind:placeholder="title">
<input :placeholder="title">

Just use
:src="`img/profile/${item.photo}`"

If you're pulling data from an array of objects, you need to include require('assets/path/image.jpeg') in your object like I did below.
Working example:
people: [
{
name: "Name",
description: "Your Description.",
closeup: require("../assets/something/absolute-black/image.jpeg"),
},
Using require(objectName.propName.urlPath) in the v-img element did not work for me.
<v-img :src="require(people.closeup.urlPath)"></v-img>

The easiest way is too require the file address:
<img v-bind:src="require('../image-address/' + image_name)" />
The complete example below shows ../assets/logo.png:
<template>
<img v-bind:src="require('../assets/' + img)" />
</template>
<script>
export default {
name: "component_name",
data: function() {
return {
img: "logo.png"
};
}
};
</script>

The most elegant solution is save images outside Webpack. By default, Webpack compress images in Base64, so if you save images in your assets folder, that doesn't work because Webpack will compress images in base64, and that isn’t a reactive variable.
To solve your problem, you need to save your images in your public path. Usually the public path is in "public" folder or "statics".
Finally, you can do this:
data(){
return {
image: 1,
publicPath: process.env.BASE_URL
}
}
And your HTML you can do this:
<img :src="publicPath+'../statics/img/p'+image+'.png'" alt="HANGOUT PHOTO">
When to use the public folder
You need a file with a specific name in the build output
File depends on a reactive variable that can change in execution time
You have images and need to dynamically reference their paths
Some library may be incompatible with Webpack and you have no other option but to include it as a <script> tag.
More information: "HTML and Static Assets" in Vue.js documentation

Related

vue.js "TypeError: Cannot read property 'path' of undefined"

I know this is a common question, but I have been going through my files now so many times without being able to the locate the error.
I am getting this error when I try to route to my components in my navigation menu.
My app.vue file:
<template>
<div id="app">
<Navbar
:nav-links="navLinks"
/>
<router-view/>
</div>
</template>
<script>
import Navbar from '#/components/Navbar'
export default {
components: {
Navbar
},
data: () => ({
navLinks: [
{
text: 'Home',
path: '/home'
},
{
text: 'About',
path: '/about'
},
{
text: 'Contact',
path: '/contact'
}
]
})
}
</script>
My Navbar component (This is where the error happens)
<template>
<nav>
<ul>
<li v-for="{link, index} in navLinks" :key="index"
#mouseover="hover = true"
#mouseleave="hover = false">
<router-link :to="link.path">
{{ link.text }}
</router-link>
</li>
</ul>
</nav>
</template>
<script>
export default {
props: ['navLinks'],
data(){
return {
hover: false,
}
}
}
</script>
How do I fix this?
<li v-for="{link, index} in navLinks" :key="index"...
should be
<li v-for="(link, index) in navLinks" :key="index"...
As it's now (destructured), link refers to a link property inside the object, not the object itself. Additionally, index is probably undefined, since the navLinks objects probably don't have an explicit property index. Therefore Vue might also complain about using invalid indexes in v-for.
Since you're only using the path prop, you could actually use destructuring, like this:
<li v-for="({ path }, index) in navLinks" :key="index"
#mouseover="hover = true"
#mouseleave="hover = false">
<router-link :to="path">
</li>
Another, unrelated note: hover property is currently being shared across all navLinks. If you expect it to somehow be related to the currently hovered element, yo uhave to save that separately (probably inside the navLink itself).
As for :nav-links="navLinks", what you've done is not only perfectly legal, but the recommended way of doing it (it's according to the HTML spec). Using :navLinks="navLinks" relies on Vue's HTML parser, which converts it to nav-links behind the scenes - inspect the HTML element and you'll notice it).
If you want to get into the details, you could have a look at this discussion on the subject. The result was: use either, but if you use camelCase it will be inconsistent with the rendered markup. If you use kebab-case, it will be consistent with rendered markup, so you won't have to deal with this difference when writing tests, for example, should you ever need to select elements by their attributes (jest converts camelCase to lowercase - hence it's inconsistent with the rendered markup, so the tests start passing/failing based on whether mount or shallowMount is used. Goes without saying, that's not really a good testing setup. )
The same exact discussion goes for using <SomeComponent /> vs <some-component />. While both work, using first needs to be addressed when writing tests if you need to select stubbed subcomponents.
Besides, vue/attribute-hyphenation (the way you did it) is part of the following vue linting presets:
plugin:vue/strongly-recommended
plugin:vue/vue3-recommended
plugin:vue/recommended
A prop in the Navbar component is named navLinks but you access it outside as nav-links.
This should work:
:navLinks="navLinks"
Incorrect syntax for v-for with {}. Use ():
li v-for="(link, index) in navLinks
You have done two mistakes here.
one is:
<template>
<div id="app">
<Navbar
:nav-links="navLinks"
/>
<router-view/>
</div>
Here you are binding with different name(nav-links), you should keep same name with which you are binding data and the name inside the props(navLinks).
Both names should be same.
Second one:
v-for="{link, index} in navLinks"
The syntax is wrong, the correct syntax should be
v-for="(link, index) in navLinks"

Can't get image to load in Vue

Can't get a simple image file to load using Vue (using a single-file component with a .vue extension). Here's the code, which I put inside template:
<div><img :src="london.jpg"></div>
What am I doing wrong?
I'm used to put all images into the public folder, so I don't need webpack to load images.
The path of the image is '/public/assets/img/london.jpg'
So, in any Vue component I can render the image using
<div>
<a href="#">
<img src="/assets/img/london.jpg" alt="london"/>
</a>
</div>
You can also directly require in your template.
<div>
<a href="#">
<img :src="require(`#/assets/img/london.jpg`)"/>
</a>
</div>
Note that the # is your src/ folder.
When binding properties, the model or data type must be correct.
To bind :src, it must be a string or data model.
<div> <img :src="'london.jpg'"></div>
or
<div> <img src="img"></div>
or
export default {
data () {
return {
img: require('london.jpg')
}
}
}
<div> <img :src="img"></div>

Passing data from PHP/HTML to .vue Component

What I'm trying to do is seemingly simple, but I can't seem to figure it out. Basically, I have 2 files:
A PHP file with the following:
...
<user-panel v-if="user.id && loaded" v-bind:user="user" v-bind:name="theUserName"></user-panel>
...
A .Vue component file with the following (that gets compiled into another file):
<template>
<span id="userPanel" class="d-flex align-items-center">
<a href="#" role="button" class="user-dropdown-toggle">
<div class="logged-in d-flex align-items-center">
<span class="d-flex align-items-center justify-contnet-center"></span>
{{name}}
</div>
</a>
</span>
</template>
<script>
export default {
name: "UserPanel",
props: ['user'],
created () {
console.log(this.$refs.myTestField.value)
}
}
</script>
All I'd like to do is pass data from the PHP to Vue into {{name}}. I've tried v-bind, a data-attribute, a hidden input, etc. Any help would be greatly appreciated.
My intention is to transfer data from my .php file to the .js file where the VUE code resides. Here I show you my code. In the proposed example I would like to import a simple string, subsequently I would like to import a JSON. Thank you so much.
File PHP
<div id='app'> <App v-bind:import='Value Import'> C'è QUALCHE PROBLEMA </App> </div>"
File .js
var App = Vue.component("App", {
template: `
<div class="container">
<div>
<h2>{{ titolo }}</h2>
<h3>{{ import }}</h3>
</div>
</div>
`,
props: ['import'],
data() {
return {
color: "color: red",
titolo: "Inizio Container",
};
}
});
new Vue({
el: "#app",
});
Quanto sopra purtroppo non funziona.
Vue single file components are processed on client side.
There are SSR, however, since you have php on your server, you must set up a REST service so you can use fetch or axios to consume server data and present it to the client side.
Let's say you have a php variable that contains string. $phpString
PHP file
...
<my-component v-bind:myProperty="<?php echo $phpString ?>"></my-component>
...
Don't forget to escape $phpString before echoing it.
In your Vue define a property called myProperty:
<template>
<span>
{{ myProperty }}
</span>
</template>
<script>
export default {
props: ['myProperty']
}
</script>

Passing an image location dynamically to Bootstrap-Vue's b-card doesn't seem to work?

In my project, I have to display a series of images, and I have stored their paths in a configuration object ìmg`:
data() {
return {
el: "#about",
img: {
'buy': '../assets/buy.svg',
}
}
}
I am using Bootstrap-Vue components in my template, and I try to create a b-card for each image.
My problem is, that if I pass the path directly to the img-srcproperty, it is displayed. However, if I try to read it from my img object, the image is not displayed.
Any hints of how to resolve this?
The following template code snippet illustrates the problem:
<div id="lifecycle">
<!-- prints correct path -->
<p>{{img['buy']}}</p>
<!-- shows the picture -->
<b-card :title="img['buy']"
img-src="../assets/buy.svg">
</b-card>
<!-- can not display the picture :( -->
<b-card :title="img['buy']"
:img-src="img['buy']">
</b-card>
</div>
When I inspect the DOM, I can see that in the case where the image path is a string literal, it is resolved into /static/img/buy.62e6a38.svg, while when I pass in an expression, it is the non-resolved path, that is passed to the component, ../assets/buy.svg:
<div class="card">
<img src="/static/img/buy.62e6a38.svg" class="card-img">
<div class="card-body">
<h4 class="card-title">../assets/buy.svg</h4>
</div>
</div>
<div class="card">
<img src="../assets/buy.svg" class="card-img">
<div class="card-body">
<h4 class="card-title">../assets/buy.svg</h4>
</div>
</div>
Is this some kind of loader issue?
Any ideas for, what I am doing wrong here?
When you use img path directly in template it will be correctly resolved with vue-loader to require("path/to/image.png"), also it translates your asset path to something production related to make it work correctly after build.
If you want to bind path property from code you should help loader to resolve path with require or import:
import buy from "../assets/buy.svg"
//... in component
data() {
return {
el: "#about",
img: {
buy
}
}
}
Or with require:
data() {
return {
el: "#about",
img: {
buy: require('../assets/buy.svg')
}
}
}
Related source: Vue CLI 3 Docs

VueJS attach a static string to v-bind

My use case is something like this.
I stored images names in an array called imagesFolder
then I retrieve names from that array and display on my vue component.
This is my code
<template lang="html">
<div class="">
<div class="" v-for="image in imagesFolder">
<img v-bind:src="image" alt="" height="100px" width="auto"><br>
</div>
</div>
</template>
<script>
export default {
data(){
return{
imagesFolder:['src/assets/mickey.png','src/assets/logo.png']
}
}
}
</script>
My question is every time I have to store the static location part src/assets/ instead of doing this. Is there a way to attach this src/assets/ part to the img tag. I hope you understand my question.
You can provide just the filename of the images in an array in your data.
<script>
export default {
data() {
return{
images: ['mickey', 'logo']
}
}
}
</script>
Then, you can loop through and use only the filename of the image as the dynamic value.
<div class="" v-for="image in images">
<img :src="`src/assets/${image}.png`" alt="" height="100px" width="auto"><br>
</div>
You can use a directive:
Vue.directive('src', function (el, binding) {
el.src = 'src/assets/' + binding.value
})
Then you can use v-src:
<img v-src="image"
Now, you are safe to use just file name:
imagesFolder:['mickey.png','logo.png']