let say i have some divs in my page :
<div id="root">
<div id="content1" v-html="content"></div>
<div id="content2"></div>
<div id="content3"></div>
</div>
and i write script :
cont myapp = new Vue({
el:'#root'
,data:{'content':''}
,methods{
get_content_dom:function(){
return document.getElementById('id_from_content');
}
}
})
how to set method get_content_dom to find the dom where html content is attached,
because maybe sometime i want to move the html content to #content1 or #content2 or #content3.
any way to set the method to get the dom of html content?
=========================================================================
my point exactly is i need to know the dom when click event :
let say i have some divs in my page :
<div id="root">
<div id="content1"></div>
<div id="content2" v-click="fired"></div>
<div id="content3"></div>
</div>
and i write script :
cont myapp = new Vue({
el:'#root'
,data:{'content':''}
,methods{
fired:function(){
console.log('here is my dom and i can get current div id #content2');
}
}
})
I wouldn't recommend using the DOM to control content. Instead, drive the content with your data
data: () => ({
contents: ['content 1', 'content 2', 'content 3']
}),
methods: {
fired (event, content, index) {
console.log('Click event on DOM element', e.target)
console.log('Click event on content index', index)
console.log('Click event on content', content)
}
}
<div id="root">
<div v-for="(content, index) in contents"
:id="`content${index + 1}`"
:key="index"
#click="fired($event, content, index)"
v-html="content"></div>
</div>
Related
I have to change in order to only get the separate preview window to close, not all that is opened at once. Have any tips?
function displayPreview(title, content) {
const previewContainer = document.createElement('div');
previewContainer.classList.add('preview-container');
previewContainer.insertAdjacentHTML('afterbegin',
`<div class="preview-modal">
<div class="preview-content">
<div class="preview-title">
<h3>${title}</h3>
</div>
<div class="preview-text">
<p>${content}</p>
</div>
<div class="preview-close">
<button class="preview-close-button">Close</button>
</div>
</div>
</div>`
);
document.body.appendChild(previewContainer);
const previewCloseButton = document.querySelector('.preview-close-button');
previewCloseButton.addEventListener('click', () => {
previewContainer.remove();
});
}
You need to confine the selector query for previewCloseButton to the appropriate scope rather than querying the entire document. This may work:
const previewCloseButton = previewContainer.querySelector('.preview-close-button');
I have a content editable div that I'm using to retrieve some data.
<div contenteditable="true" ref="test">/*SomeText*/</div>
After running the focus through the ref with this.$refs.test.focus(). It didn't work and I get an error on the console (Cannot read properties of undefined reading focus)
How can I trigger a focus effect on content editable div?
The attribute for content editable should not be content-editable="true", but instead contenteditable="true".
const App = {
el: '#app',
methods: {
focusDiv() {
this.$refs.test.focus()
}
}
}
const app = new Vue(App)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div contenteditable="true" ref="test">My Div</div>
<button #click="focusDiv">Focus on div</button>
</div>
Have seen similar questions but in my case am handling dynamic data from an API. Want when the user clicks the message with only Subject then the body shows and after the user can click again for
the body to hide. it works fine but want to add that functinality
if(data.status == 200){
data.data.forEach(message => {
msg += `
<div id="read">
<p id="header">${message.subject}<span>......</span></span></p>
<p id="body">${message.message_details}</p>
<p>Sent on: ${message.created_on}</p>
</div>
<hr>`
});
document.getElementById("inbox").innerHTML = msg
}```
first, you need to add all of your dynamic blocks inside a wrapper div let's call it articles for example
after that, you need to add eventListener at this wrapper to listen for click event then check if the clicked element is the title toggle the hide class that is predefined in the css like this example below
const wrapperEl = document.querySelector('#articles');
wrapperEl.addEventListener('click', function(e){
if(e.target.id == 'header'){
e.target.nextElementSibling.classList.toggle('hide')
}
});
.hide {
display: none
}
<div id="articles">
<div>
<p id="header">title 1<span>......</span></p>
<p id="body" class="hide">article content here</p>
<p>Sent on: 02/17/2020</p>
</div>
<hr />
<div>
<p id="header">title 2<span>......</span></p>
<p id="body" class="hide">article content here</p>
<p>Sent on: 02/17/2020</p>
</div>
<hr />
<div>
<p id="header">title 3<span>......</span></p>
<p id="body" class="hide">article content here</p>
<p>Sent on: 02/17/2020</p>
</div>
<hr />
<div>
<p id="header">title 4<span>......</span></p>
<p id="body" class="hide">article content here</p>
<p>Sent on: 02/17/2020</p>
</div>
</div>
NOTE: in this example, i just added some hardcoded blocks for testing but in your case, it will become from API in a dynamic way but in booth case, it should be inside a wrapper element
Added the missing code to hide body div, and use class="body" instead of id for paragraph and div element, because these will be repeated.
const data = [
{subject: "test123", message_details: "msg123", created_on: "12-05-2021"},
{subject: "test456", message_details: "msg456", created_on: "02-05-2020"},
{subject: "test789", message_details: "msg789", created_on: "11-07-2011"},
];
let msg = "";
data.forEach(message => {
msg += `
<div class="read">
<p id="header">${message.subject}<span>......</span></span></p>
<p class="body">${message.message_details}</p>
<p>Sent on: ${message.created_on}</p>
</div>
<hr>`
});
document.getElementById("inbox").innerHTML = msg;
const bodyElements = document.querySelectorAll(".read");
bodyElements.forEach(function(bodyEle) {
bodyEle.addEventListener("click", (e) => {
bodyEle.children[1].classList.toggle("hide");
});
});
.hide {
display: none;
}
<html>
<head></head>
<body>
<h1>My title</h1>
<div id="inbox">
</div>
</body>
</html>
First of all, you shouldn't use ids, because you will have the same id multiple times. So, you should make them class.
Let's say you use axios, or fetch API, doesn't matter actually:
axis.get('api-url').then(response => {
// create your HTML outputs here
}).then(() => {
document.querySelectorAll('.header').forEach(x => x.addEventListener('click', toggleBody));
})
const toggleBody = (event) => {
event.closest('.read').querySelector('.body').classList.toggle('is-open')
}
I have the following HTML markup:
<div id="app">
<div class="image">
<div class="overlay">
<p>Some overlay text</p>
</div>
<img src="https://placeimg.com/640/480/any" class="img-fluid">
</div>
<div class="info">
<h6 class="name">Title here</h6>
<p class="meta">Meta here</p>
</div>
<div class="info-button" #mouseover="addParentClass" #mouseout="removeParentClass">
Mouse over here!
</div>
What I would like to do is whenever someone hovers over the div with class "info-button" certain classes get added to the image above and the overlay.
I have got it working with the following Vue.js markup:
let vm = new Vue({
el: "#app",
data:{
isHovering: false
},
methods: {
addParentClass (event) {
event.target.parentElement.children[0].children[1].classList.add('active')
event.target.parentElement.children[0].children[0].classList.add('overlay-active')
},
removeParentClass (event) {
event.target.parentElement.children[0].children[1].classList.remove('active')
event.target.parentElement.children[0].children[0].classList.remove('overlay-active')
},
},
})
However it seems like a lot of redundant JS. I have tried to get it working with:
event.target.parent.closest('.overlay'.).classList.add('overlay-active')
And a lot of similar parent/children/closest selectors, however I can not seem to get the result I want. How can I get the "closest" selector to work here?
Here's a codepen with a very rough working example: Link to codepen
Edit: I want to point out that i want to use this in a loop, so I will have mulitple images and I want to make the overlay only appear on the current image.
VueJS is reactive. This means the data should drive the DOM. You should not play with the DOM yourself.
Add an active property to data;
let vm = new Vue({
el: "#app",
data:{
isHovering: false,
active: false
},
methods: {
addParentClass (event) {
this.active = true;
},
removeParentClass (event) {
this.active = false; },
},
})
And make the DOM reactive by;
<div class="overlay" :class="{'overlay-active': active}" >
<p>Some overlay text</p>
</div>
Here is the updated codepen
https://codepen.io/samialtundag/pen/Jeqooq
I have a page in which I have MCQ Options which looks like this:
This is the HTML Code for the options parts till now:
<div v-for="(option, index) in optionsForFrontend">
<div class="option">
<div class="radio-check-item">
<input type="radio"
name="question"
:value="index"
v-model="picked"
v-if="question.metadata.choices === 'Single'">
<input type="checkbox"
name="question"
:value="index"
v-model="picked"
v-if="question.metadata.choices === 'Multiple'">
</div>
<div class="divider">
</div>
<div class="content-item">
<vue-markdown :source="option.option"></vue-markdown>
</div>
</div>
</div>
I want to select the options by clicking on the option content. So I put a :click="functionToSelectOption" on the outer div ("option") containing checkbox and option content.
The problem is when I select the checkbox, it gets selected and the function "functionToSelectOption" gets called as well since the checkbox is inside the "option" div.
I want to be able to detect a click inside the "option" div but outside radio/checkbox div so I can call the function to toggle the option.
I mostly found similar questions under jquery tags and nothing with VueJS.
I would avoid event.stopPropagation(). All kinds of things might be listening higher up in the tree. For instance, you might want an onclick on the window to close a modal dialog if the user clicks outside the dialog. The much less radical way to do this is to look at event.target. This jsfiddle tests (event.target == event.currentTarget) so it only reacts to clicks on the parent div.
Markup
<div id="ctr">
<div v-for="(option,index) in options"
style="margin:10px;padding:10px;border:solid;border-radius:4px"
#click="parent"
>
<input type="checkbox" :name="'invidiousChoice' + index" #click='child'> {{option.label}}
</div>
</div>
JS
var vm = new Vue({
el:"#ctr",
data : {
options:[{label:'terrible option'},{label:'disastorous option'}]
},
methods: {
parent: function(event) {
if(event.target == event.currentTarget)
alert( 'parent clicked');
}
}
})
You can use event.stopPropagation() in child element.
Here is working JSFiddle Solution: Link
HTML
<div id="app">
<div #click="parent">
Parent
<div>
<input type="checkbox" #click="child">
</div>
</div>
{{message}}
JS
new Vue({
el: '#app',
data: {
message: ''
},
methods: {
parent: function() {
this.message = 'parent clicked';
},
child: function() {
event.stopPropagation()
}
}
});