Concatenating variable with querySelector VueJS - vue.js

I am trying to concatenate a Vue variable with an id in querySelector, and for some reason it is not targeting any element.
I am currently using:
document.querySelectorAll(".container:not(#`${this.id}`"));
this.id is just a string, and doesn't include the '#', which is why I am adding it to the querySelector here
What I have in the DOM is:
<div id="header-1" class="container">
.......
</div>
<div id="header-2" class="container">
.......
</div>
<div id="header-3" class="container">
.......
</div>

You should look at using 'refs' to select a DOM directly instead of native javascript and CSS selectors.
For example this.$refs[this.id]
https://v2.vuejs.org/v2/api/#ref

Related

v-on:click not working - dynamically added html element

I am trying to get all images for a category using Vue
<div class="col-md-12 col-sm-2 p-2">
<a v-on:click="onCategoryManageImageClick($event)" data-target="#location-
category-images">
</span>
</a>
</div>
So the event onCategoryManageImageClick ($event) does not work, if I am adding a html block and then click on get image button.
this is index.js
methods:{
onImagesTabClick(){
this.$root.$emit('activated-tab:location-images');
},
onCategoriesTabClick(){
window.j1App.eventBus.$emit("j1-location-image-list:shown");
},
onCategoryManageImageClick: function(event) {console.log('working event..');
event.preventDefault();
window.j1App.eventBus.$emit("j1-location-category-image-
list:shown",event.currentTarget.id);
}
}
So basically it need to to work like we do in jQuery
$(document).on('click',function{
})
So it works either page load or if adding any new html element on DOM. same I want in Vue.
You cannot alter the Vue template outside of Vue. That won't work. Vue compiles the template once when starting up and adds the event listeners to the rendered elements. If you add elements afterwards, Vue will not know about them.
The correct way of doing this would be to add those new elements in Vue.
<div
class="col-md-12 col-sm-2 p-2"
v-for="item in items"
:key="item.id"
>
<a
v-on:click="onCategoryManageImageClick($event, item)"
data-target="#location-category-images"
>
</a>
</div>
See https://v2.vuejs.org/v2/guide/list.html for documentation. In this case you need the items array variable in data and add more array elements to it, if you need more links.
Try raplacing your a tag with p
<div class="col-md-12 col-sm-2 p-2">
<p v-on:click="onCategoryManageImageClick" data-target="#location-
category-images">
</p>
</div>

Vue how to use id in components?

how to use id in components, the code as below:
The components code as below:Profilelist.js
<template>
<div class="col col-m-12 col-t-6 col-d-6 box-item f-software">
<div class="item animated">
<div class="desc">
<div class="image">
<a href="#popup-{{id}}" class="has-
popup"><img src="{{workpic}}" alt="" /></a>
</div>
<div class="category">{{category}}</div>
<div class="name">
<a href="#popup-{{id}}" class="has-
popup">{{project_name}}</a>
</div>
</div>
</div>
<div id="popup-{{id}}" class="popup-box mfp-fade mfp-hide">
<div class="content">
<div class="image">
<img src="{{workpic}}" alt="">
</div>
<div class="desc">
<div class="category">{{category}}</div>
<h4>{{project_name}}</h4>
<p>
{{project_content}}。
</p>
<a href="{{project_link}}"
class="btn">View Project</a>
</div>
</div>
</div>
</div>
</template>
The index file code as below:
<div class="row box-items">
<ProfileList
v-for="profile in loadedProfiles"
:key="profile.id"
v-bind:id="profile.id"
:workpic="profile.workpic"
:category="profile.category"
:project_name="profile.project_name"
:project_content="profile.project_content"
v-bind:project_link="profile.project_link"
/>
</div>
And it outcome an error code as below:
href="#popup-{{id}}": Interpolation inside attributes has been removed. Use v-bind or the colon shorthand instead. For example, instead of , use .
src="{{workpic}}": Interpolation inside attributes has been removed. Use v-bind or the colon shorthand instead. For example, instead of , use .
href="#popup-{{id}}": Interpolation inside attributes has been removed. Use v-bind or the colon shorthand instead. For example, instead of , use .
id="popup-{{id}}": Interpolation inside attributes has been removed. Use v-bind or the colon shorthand instead. For example, instead of , use .
src="{{workpic}}": Interpolation inside attributes has been removed. Use v-bind or the colon shorthand instead. For example, instead of , use .
href="{{project_link}}": Interpolation inside attributes has been removed. Use v-bind or the colon shorthand instead. For example, instead of , use .
You have to bind the data to your attributes and do the proper concatenation using template literals, replace your attributes following the examples
:href="`#popup-${id}`"
:src="workpic"
:id="`popup-${id}`"
:href="project_link":

Vue.js can template without no root element or vue el specify for two div

HTML:
<div class="a">
Some HTML ...
</div>
<div class="b">
Some HTML
</div>
Javascript:
new Vue({
el: "#item_info",
....
....
(Other Config)
....
....
})
The two div above need to show the information from vue,
I tried using <template></template> like:
<template>
(my two div)
</template>
but it does not work because both divs need to be inside a root element.
I know that if I modify my html to:
<div id="item_info">
<div class="a"></div>
<div class="b"></div>
</div>
It can work, but I have no authorization to modify the base Html structure
Is there any other way that could help me solve it?
Maybe you should try to split those div's in two components and then add them to parent.
One.vue
<template>
<div class="a">
Some HTML ...
</div>
</template>
Two.vue
<template>
<div class="b">
Some HTML
</div>
</template>
Three.vue
<template>
<One></One>
<Two></Two>
</template>
If you have no authorization then I think you can't put that <template></template> either. Vue JS doesn't allow selecting multiple elements. But you can use Vue Component, please refer to this official link of Vue JS: https://v2.vuejs.org/v2/guide/components.html.
But remember Component also requires one root element.

Vue named slots do not work when wrapped

I have a responsive-menu component which I want to use named slots inside of this up my template markup:
<template>
<div class="responsive-menu">
<div class="menu-header">
<slot name="header"></slot>
</div>
</div>
</template>
Whenever I try my named slot like this it work perfectly fine:
<responsive-menu>
<h3 slot="header">Responsive menu header</h3>
</responsive-menu>
However as soon as I wrap it with a class nothing shows up anymore.
<responsive-menu>
<div class="container">
<h3 slot="header">Responsive menu header</h3>
</div>
</responsive-menu>
What is going on here? Shouldn't I just be able to wrap the named component? Which does it appear that my named slots need to be direct children of my Vue component?
It does not work because your "wrapped slot" isn't direct child of responsive-menu tag.
try something like that:
<responsive-menu>
<div class="container" slot="header">
<h3>Responsive menu header</h3>
</div>
</responsive-menu>
jsfiddle
It works with Vue >= 2.6. Just upgrade vue and vue-template-compiler.

VueJS render once into an element

Is it possible to just render once into an element?
Suppose I have a contenteditable div, and only want to render the first value, then stop rerendering as the model changes. Here only the initial value of variable will be rendered.
<div contenteditable="true"> {{variable}} </div>
Use v-once
<div contenteditable="true" v-once> {{variable}} </div>
You can also wrap it with a <span>:
<div contenteditable="true">
<span v-once> {{variable}} </span>
</div>
refs:
https://v2.vuejs.org/v2/guide/components.html#Cheap-Static-Components-with-v-once
https://v2.vuejs.org/v2/api/#v-once
Or another solution is simply clone the variable and just don't modify it, for example if you call it readOnlyVariable:
<div contenteditable="true"> {{readOnlyVariable}} </div>