Vue.js - Render issue - vue.js

I'm trying to create a component, that can show/hide on click, similar to an accordion.
I have the following error and I don't know why:
[Vue warn]: Property or method "is_open" is not defined on the
instance but referenced during render. Make sure to declare reactive
data properties in the data option. (found in root instance)
<div id="app">
<div is="m-panel" v-show="is_open"></div>
<div is="m-panel" v-show="is_open"></div>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="comp_a.js" ></script>
<!--<script src="app.js" ></script>-->
</html>
Vue.component('m-panel', {
data: function() {
return {
is_open: true
}
},
template: '<p>Lorem Ipsum</p>'
})
new Vue({
el:'#app',
})

Your code seems a little confused, your is_open is in your component but you are trying to access it in the parent. You just need to make sure this logic is contained inside your component. The easiest way is to simply place an event on the relevant element in your component template:
<template>
<div>
<!-- Toggle when button is clicked-->
<button #click="is_open=!is_open">
Open Me!
</button>
<span v-show="is_open">
I'm Open!
</span>
</div>
</template>
Here's the JSFiddle: https://jsfiddle.net/ytw22k3w/

Because u used is_open property in '#app instance' but u didnt declare in it,u decladed in 'm-panel component' which has no relation with it.Try something like this can avoid it.
new Vue({
el:'#app',
data:{
is_open:''
}
})

Related

Component inside `transition-group` is rendered twice (duplicated)

Here is a strange issue i am facing.
<script src="https://unpkg.com/vue#2.6.11/dist/vue.min.js"></script>
<div id="app">
<transition-group name="fadeLeft" tag="ul">
<section key="0">
<testt></testt>
<template v-pre id="myId">
<div>My neighbors: <a v-for="(val,index) in myArray">{{val}}</a></div>
</template>
</section>
</transition-group>
</div>
<script>
Vue.component('testt', {
template: '#myId',
props: {
myArray: {
type: Array,
default: function() {
return ['James', 'Mike'];
}
}
}
})
new Vue({
el: '#app'
})
</script>
transition-group renders the component twice (and the second rendering is done without parsed "{{variable}}").
If you just remove transition-group parent at all, it works as expected and there is no duplicated content. So, definitely the problem seems somewhere there. How to fix that (so, retain transition-group and solve the problem)
Please don't post answers "use component outside of app" or similar offtopic, i described the problem I need to find answer. Also, the aprior is that the template needs to be within transition-group decendants.
The problem:
In the section tack you have the testt tag which was rendered with the parsed HTML and also the template which was rendered as another literal tag (no rendering). And since transition-group elements must be keyed, the template had to be moved out.
The solution:
<script src="https://unpkg.com/vue"></script>
<div id="app">
<transition-group name="fadeLeft" tag="ul">
<section key="0">
<testt></testt>
</section>
</transition-group>
<template v-pre id="myId">
<div>My neighbors: <a v-for="(val,index) in myArray">{{val}} </a></div>
</template>
</div>
<script>
Vue.component('testt', {
template: '#myId',
props: {
myArray : { type:Array, default :function(){ return ['James','Mike'];} }
}
})
new Vue({
el: '#app'
})
</script>

How to reference child elements in a component?

I'm trying to build a parent-child tree in Vue, and I want to pass the parent's DOM/element ID down to the child so that they can append to it. Here is a simple example of what I am trying to achieve as the DOM structure in the browser:
<div id="my-id">
<p>parent-comp header</p>
<div id="my-id-child">
<p id="my-id-child-content">child-comp content</p>
</div>
<p>parent-comp footer</p>
</div>
The only way I have been able to do this so far is to duplicate the id into another property propid and pass them both down the tree. This seems messy. See my sample code:
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<parent-comp id="my-id" propid="my-id"></parent-comp>
<script type="application/javascript">
Vue.component('parent-comp', {
props: {
propid: String
},
template: ` <div>
<p>parent-comp header</p><child-comp :id="propid + '-child'" :propid="propid + '-child'"></child-comp><p>parent-comp footer</p>
</div>`,
});
Vue.component('child-comp', {
props: {
propid: String
},
template: `<div>
<p :id="propid + '-content'">child-comp content</p>
</div>`,
});
new Vue({
el: '#my-id'
});
</script>
</body>
</html>
I'm guessing there must be a better way to achieve this? It seems like it should be a simple task? Thanks.
There are indeed better ways to refer to specific elements within the current component's template: use refs in the template, which would allow your component script to access them via this.$refs:
<template>
<div>
<button ref="myBtn">Click</button>
</div>
</template>
<script>
export default {
methods: {
doFoo() {
console.log(this.$refs.myBtn)
}
}
}
</script>
The scope isolation is maintained. For example, when there are multiple instances of component A on a page, and one of them gets a reference to its button (via this.$refs.myBtn) to disable it, only that instance's button is disabled. All other A instances are unaffected.

cant find colorpicker function from vue template

I am trying to use bootstrap color picker plugin with vue2. I read the following tutorial that shows how to do stuff like that.
Here is my component code:
<template>
<div class="input-group colorpicker-component">
<input type="text" value="#b8c7ce" class="form-control"/>
<span class="input-group-addon"><i></i></span>
</div>
</template>
<script>
export default {
mounted: function() {
$(this.$el).colorpicker()
},
}
</script>
https://itsjavi.com/bootstrap-colorpicker/
Color picker works fine If I call it directly from javascript like this:
$('#sidebar_font_color').colorpicker()
However when I do this
<color-picker></color-picker>
I get this in console:
[Vue warn]: Error in mounted hook: "TypeError: $(...).colorpicker is
not a function"
I am not making a full SPA app just using some vue2 with my application at various points. Any idea why it cant find that function?
Here's a minimal working example. Your error message indicates that you don't have the colorpicker code loaded when mounted runs, or possibly that jQuery is not loaded before the colorpicker code is.
new Vue({
el: '#app',
components: {
colorPicker: {
template: '#cp-template',
mounted() {
$(this.$el).colorpicker()
},
}
}
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-colorpicker/2.5.1/css/bootstrap-colorpicker.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-colorpicker/2.5.1/js/bootstrap-colorpicker.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.min.js"></script>
<div id="app">
<color-picker></color-picker>
</div>
<template id="cp-template">
<div class="input-group colorpicker-component">
<input type="text" value="#b8c7ce" class="form-control"/>
<span class="input-group-addon"><i></i></span>
</div>
</template>

How to get parent of clicked element in Vue.js

How to get parent of clicked (this) element in Vue.js?
In jQuery this looks like:
$(this).parents(':eq(2)').next('.press__news__nav--view').show();
Thanks!
It's not a good practice in Vue when you're trying to manipulate DOM directly. If you want to show/hide an element, you should use v-if or v-show directives.
Anyway, you can access event object like this:
new Vue({
el: '#app',
methods: {
logme: function(event) { // a regular event object is passed by $event in template
console.log(event.target.parentElement) // parent element
}
}
});
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<div class="hello">
<button #click="logme($event)">Click me</button>
</div>
</div>

Vue dynamic component event bindings

I have a dynamic component that is resolved and bound on runtime using the documented dynamic component syntax;
<div class="field">
<component v-if="component" :is="component" #valueUpdated="onUpdate($event)"></component>
</div>
Decided using a prop assigned to on mounting.
For whatever reason, when the child component, rendered dynamically, emits an event this.$emit('eventName', /*someData*/) the parent does not seem to be able to hear it. Is the approach used in standard components applicable to those rendered dynamically? Props seem to work, so maybe I am not doing something correctly?
yeah you can use props with dynamic components it's just you need to use lowercase hyphenated (kebab-case) names for the html attribute, i.e.
<component v-if="component" :is="component" #value-updated="onUpdate"></component>
Vue.component('foo', {
template: `
<div>
<button #click="$emit('value-updated', { bar: 'baz' })">pass data</button
</div>
`
});
new Vue({
el: '#app',
data: {
currentComponent: 'foo',
output: {},
},
methods: {
onUpdate (payload) {
this.output = payload
}
}
})
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<component v-if="currentComponent" :is="currentComponent" #value-updated="onUpdate"></component>
<pre>{{ output }}</pre>
</div>