Vue 2 Prop value not rendering in the template - javascript

I have this code where I am trying to render a value from prop in the template but getting a
Uncaught ReferenceError: channel is not defined
<script>
Vue.component('itemstable', {
template: `<div>${channel}</div>`, // this is where the error occurs.
props: ['channel'],
data() {
return {
}
}
})
new Vue({
el: '#items_app',
data: {
selectedChannel: 'pos',
channels: JSON.parse(`["pos","kiosk"]`)
}
})
</script>
and here is the markup:
<div id="items_app">
<itemstable
:channel="selectedChannel"
></itemstable>
</div>
I have tried changing the name of the prop thinking 'channel' might be a reserve word, but the
same thing happens.

Change the javascript interpolation ${} to vue expression {{}}
template: `<div>{{channel}}</div>`,

Related

Vue.delete warning to avoid using JavaScript unary operator as property name on click

I get the following warning when using Vue.delete:
[Vue warn]: Error compiling template: avoid using JavaScript unary operator as property name: "delete(testObj,)" in expression #click="Vue.delete(testObj,'label')"
I can use Vue.delete anywhere else and it seems fine. Am I using it wrong?
new Vue({
el: '#app',
data() {
return {
testObj: {
label: "The label"
}
};
}
});
<div id="app">
{{testObj.label}}
<button #click="Vue.delete(testObj,'label')">Delete</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.11/dist/vue.js"></script>
The global Vue will not be available inside your template. Everything in a template is scoped to the current Vue instance, so you're effectively trying to access this.Vue. Trying to access any of the properties of the global Vue won't work.
You can use $delete instead of Vue.delete inside a template.
https://v2.vuejs.org/v2/api/#vm-delete
new Vue({
el: '#app',
data() {
return {
testObj: {
label: "The label"
}
};
}
});
<div id="app">
{{testObj.label}}
<button #click="$delete(testObj, 'label')">Delete</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.11/dist/vue.js"></script>
I would add that the specific error message you're seeing relates more generally to trying to use any property called delete but that's something of a moot point as you should be using $delete anyway.

How to pass data into Vue instance so that subsequent updates are reflected?

I'm trying to dynamically update a Vue JS prop after the view has been loaded and the custom has been initialised. I'm building a custom Vue plugin and am using props to pass options, one of which is a object which I need to dynamically update the value passed after the component has loaded, e.g:
<div id="app">
<script>
var seedData = {
percent: 50,
name: 'Smith'
}
setInterval(() => {
seedData = {
percent: Math.random(),
name: 'Smith'
}
}, 1000)
</script>
<offers :parent-data="seedData"></offers>
</div>
Vue.component('offers', {
template: '<h1>Parent Data: {{ parentData.percent }}</h1>',
props: {
parentData: {
default: () => ({
percent: 0,
name: 'John'
}),
type: Object
},
}
});
// create a new Vue instance and mount it to our div element above with the id of app
var vm = new Vue({
el: '#app'
});
This will load the initial name/values from offersData, however, the new values on the setInterval doesn't get passed through.
I've tried adding a watcher inside of my custom Vue plugin that gets loaded through <offers> but this doesn't seem to work either:
watch: {
parentData: function (newVal) {
this.parentData = newVal
}
}
UPDATE
The following is my implementation:
Code Pen -> https://codepen.io/sts-ryan-holton/pen/VwYNzdZ
There are multiple problems with your code
Everything inside <div id="app"> is treated by the Vue as a template and compiled - see the docs
If neither render function nor template option is present, the in-DOM HTML of the mounting DOM element will be extracted as the template. In this case, Runtime + Compiler build of Vue should be used.
Including <script> tag there is wrong. Just try to include vue.js (debug build) instead of vue.min.js (minified production build of Vue) and you will see bunch of errors (btw its always good idea to use debug build for development as it gives you lots of useful errors and warnings)
The fact that it "somehow works" in prod build (ie the initial values are shown on the page) doesn't mean it's supported...
So the inside of <div id="app"> is template for Vue. As I said before in the comments, all data referenced by template must be in the context of Vue instance. You cannot pass some global variable into props. So moving <script> outside of <div id="app"> won't help
[Vue warn]: Property or method "seedData" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initialising the property.
What you can do is to pass seedData object into root Vue instance like this:
var vm = new Vue({
el: '#app',
data: {
seedData: seedData
}
});
Now the errors are gone but data changes is not reflected still. Reason for that is not Vue specific. Its simple JavaScript. Object are passed by reference in JS. Look at this code:
var a = { name: 'John' }
var b = a
a = { name: 'Smith' }
// b is still pointing to "John" object
To workaround it, don't replace whole object. Just mutate it's properties (beware of Vue reactivity caveats)
setInterval(function() {
seedData.name = 'John';
seedData.percent = Math.random();
}, 1000)
Whole solution:
Vue.component('offers', {
template: '<h1>{{ parentData.name }}: {{ parentData.percent }}</h1>',
props: {
parentData: {
default: () => ({
percent: 0,
name: 'John'
}),
type: Object
},
}
});
// create a new Vue instance and mount it to our div element above with the id of app
var vm = new Vue({
el: '#app',
data: {
seedData: seedData
}
});
<script>
var seedData = {
percent: 60,
name: 'Smith'
}
setInterval(function() {
seedData.name = 'John';
seedData.percent = Math.random();
}, 1000)
</script>
<div id="app">
<offers :parent-data="seedData"></offers>
</div>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>

Why am I getting a "Property or Method is not defined" for the variable value instead of the variable name?

I have a VueJS component that works if I pass through static text, but if I try to bind a variable value, I get a "Property or method is not defined on this instance". But instead of saying it's the prop that's not defined, it's the prop's variable value that is "not defined".
HTML:
<section class="reflectionPage" id="reflectionPage">
<div class="header">
<h1>Independent Learner & International Citizen</h1>
<h3>Character, Collaboration, Learning Goals</h3>
</div>
<reflection-box type="student" imgurl="https://placeimg.com/640/480/tech/sepia"></reflection-box>
<reflection-box type="teacher" v-bind:textbox="teacherComment"></reflection-box>
</section>
VueJS:
// Define a new component called reflection-box
Vue.component('reflection-box', {
props: ['type', 'imgurl', 'textbox'],
template: '<div :class="`${type}Reflection`" class="reflection">\
<h4 v-if="imgurl">{{ type.charAt(0).toUpperCase() + type.slice(1) }} Reflection</h4>\
<h4 v-else>{{ type.charAt(0).toUpperCase() + type.slice(1) }} Comment</h4>\
<div class="reflectionBox" :class="`${type}ReflectionBox`"><img v-if="imgurl" :src="imgurl" alt="Reflection Box Image"><p v-if="textbox" v-html="textbox"></p></div>\
</div>'
})
new Vue({
el: '#reflectionPage'
})
If anything, I would expect there to be an error saying that "textbox" is undefined. I don't understand why it's teacherComment that is "undefined"?
Screenshot of error
It says that the variable teacherComment doesn't exist. If we look at your Vue instance you can see that the only thing it has is the el attribute, there is never a teacherComment defined. To fix it you need to add it as a data attribute.
new Vue({
el: '#reflectionPage',
data () {
return {
teacherComment: 'The value you wish to give it'
};
}
})

VueJs Async loading templates

I Am building my first VueJs App and I want to asynchronous load my template. In our framework we have our templates stored in a database, that's why.
It is working until I have some nested dom-elements in my template without any data bound to it. So my my Vuejs is like:
var app = new Vue({
el: '#app',
data: {
finish: false,
template: null
},
render: function(createElement) {
if (!this.template) {
return createElement('div', 'loading...');
} else {
return this.template();
}
},
mounted() {
var self = this;
$.post('myUrl', {foo:'bar'}, function(response){
var tpl = response.data.template;
self.template = Vue.compile(tpl).render;
})
}
})
This is working when my template is like:
<div v-show="!finish">
<p>Test</p>
</div>
But when it's like this:
<div v-show="!finish">
<p>
<span>Test</span>
</p>
</div>
I get
[Vue warn]: Error in render: "TypeError: Cannot read property '0' of
undefined" (found in < Root >)
But when it's like this:
<div v-show="!finish">
<p v-show="!finish">
<span>Test</span>
</p>
</div>
It's working again.
Can anyone explain what is happening here? And is this the right way to do it or should I do it an other way?
My guess would be that you should try v-if instead of v-show. What v-show does is changing display property, vue is trying to render the element anyway.
docs

Vue.js 2.0 filters in text interpolations

I'm using vue.js 2.0 (standalone) build.
HTML:
<div id="app">
<p> ${ number | results_found } </p>
</div>
JS:
<script>
var app = new Vue({
delimiters: ['${', '}'],
el: '#app',
data: {
number: 0,
},
filters: {
results_found: function(value) {
console.log(value + " results found!");
return value + " results found!";
}
}
})
</script>
I changed the delimiters (see above) so that they would not conflict with Django's templating syntax.
When I run this I see in the console:
[Vue warn]: Failed to resolve filter: results_found (found in anonymous component - use the "name" option for better debugging messages.)
0 results found!
Yet in the HTML all I see is:
0
What am I doing wrong? All new to Vue.js, by the way.
EDIT: Also how do I "name" components for better debugging? My filter is on my instance, not a component...

Categories

Resources