Equivalent of $(this) reference of jquery, in vue.js - javascript

In jquery , I can use $(this) reference to access an element without using any class or id. What is the way to achieve similar result in vue.js?

I assume you want to get an element which triggered event. Then it should be event.target.
For example:
<div #click="sayHi"></div>
methods: {
sayHi(event) {
console.log(event.target)
}
}

The prior answer refers to this.$el which grabs the root element of a given Vue component (Vue documentation on .el), however, if you want to grab an arbitrary element within a given component, you can use this.$refs (Vue documentation on .refs):
<template>
<div>
<h1 ref="myHeader">Hello</h1>
<div>
<template>

this.$el within a Vue component

Related

How to remove attribute entirely from child in React

I need to remove the attribute "data-processed" from a child div of a component. I cant just set it to null or false, it needs to be removed.
In classic JS, I'd need something like:
$('#mermaid').html(node.data.graph).removeAttr('data-processed');
But that will not seem to work here. I have used useRef to specify the ref to the div, but I cannot find any documentation on how to remove the attribute from the element at the ref. Is this at all possible to do in react?
You can use vanilla removeAttribute method on the DOM node using useRef. https://developer.mozilla.org/en-US/docs/Web/API/Element/removeAttribute
const domRef = useRef();
domRef.current.removeAttribute('data-processed');
You have 2 options.
Using removeAttribute method on element:
document.getElementById('mermaid').removeAttribute('data-processed')
Using ref (which is better):
elementRef.current.removeAttribute('data-processed');

Vue template: How to automatically add custom attribute to elements that have a v-on:click directive

We are using single file vue components and in a mousemove event handler we'd like to be able to detect if the target element is clickable.
In our Vue templates we are using v-on directives: v-on:click="someCallback".
Unfortunately there doesn't seem to be an easy way to tell for a given element if an event listener was registered for it (i.e. via v-on directive).
For this we'd like to add a custom attribute to those elements with a v-on:click directve - i.e. "clickable". But this should happen automatically.
So we'd have to either wrap Vue's own "on"-directive into a custom one or somehow hook into Vue's rendering cycle - but this seems not very straight-forward: Couldn't find the directive on the Vue instance or the Vue component object.
What we have tried:
retrieving the information about registered listeners from the target element provided by the event object passed to the event handler. But apparently browsers don't provide this information.
searching the Vue component object for some object that stores information about which event listener has been registered for which element with which handler. We were not able to find this information - but it should be somewhere, right?
Hope anyone has a nice idea on how to accomplish adding a custom attribute to elements with v-on:click directive automatically.
Thanks!
EDIT:
So we have i.e.
<div id="x" #click="someMethod" />
in our template.
But we want to add a custom attribute automatically (we dont want to add it manually for all the trillion cases):
<div id="x" clickable #click="someMethod" />
Then in the event handler for addEventListener('mousemove', handler) we would check for this attribute: if (e.target.hasAttribute('clickable'))
But any other way of accomplishing this (so being able to tell inside the handler for mousemove if the element is clickable) would be fine too.
You could create a container component and import it into all your other vue components, ensuring it's the first component in your template, like:
<template>
<v-container>
// your template here
</v-container>
</template>
<script>
// Obviously replace the path and point to your location of the component
import ComponentContainer from './common/ComponentContainer.vue'
export default {
name: 'MyClientComponent',
components: {
'v-container': ComponentContainer
}
}
</script>
And this is the container component that looks for click events and adds the clickable class:
<template>
<div class="component-container">
<slot></slot>
</div>
</template>
<script>
export default {
name: 'ComponentContainer',
mounted() {
this.$slots.default.forEach(vn => {
this.addClickableClassNames(vn);
});
},
methods: {
addClickableClassNames(vnode) {
if (vnode) {
let data = vnode.data;
if (data && data.on) {
// Check for click events and add a
// clickable class if one exists
if (data.on.click && vnode.elm && vnode.elm.classList) {
vnode.elm.classList.add('clickable');
}
}
// Now recursively check children
if (vnode.children) {
vnode.children.forEach(vn => {
this.addClickableClassNames(vn);
});
}
}
}
}
}
</script>
This works, but I wouldn't like to comment on the performance of a large dom. And you, and other devs, need to remember to import into all components, which isn't ideal. But, it's a solution that might give you other ideas on improving and making more scalable.
I can't think of a way to "automatically" add this clickable attribute. I think unfortunately you will still need to "tag" your clickable elements one by one.
I would have a directive which you can add to any element in your templates.
Directive
Vue.directive('myDirective', {
inserted(el, bindings) {
el.addEventListener('mouseover', () => {
alert(bindings.value);
})
}
});
Usage
<span v-my-directive="true">Element 1</span>
<span v-my-directive="false">Element 2</span>
You will notice that in the template when using the directive a value is being passed to it. This is then read via bindings.value. Of course based on this value you can do whatever functionality you need.
JSFiddle: https://jsfiddle.net/tc45xf82/2/
Vue Docs: https://v2.vuejs.org/v2/guide/custom-directive.html

Vue - when and why using $el

I've found this answer here:
https://stackoverflow.com/a/50431015/11735826
and i wonder why .$el was used here, and also why does it not work without the el element?
when you use ref attribute on the html tag, the DOM-element is returned by this.$refs.modal.
when you use ref attribute on the template tag, the component instance is returned, so this.$refs.modal.$el returns directly the DOM element. See https://v2.vuejs.org/v2/api/#vm-el
$el returns the HTML element to which a given Vue instance (be it a main instance or a component) is bound. By using this.$refs.modal.$el the answer gets the underlying HTML element for the this.$refs.modal, and then encapsulates it in a jQuery object to call the modal method.

Polymer 2.0 access a parent component from child component

I have a nested component, what is the Polymer way to travel up the DOM or component tree in this case.
<parent-component>
<some-component>
<component-i-am-starting-from></<component-i-am-starting-from>
</some-component>
<some-other-component>
</some-other-component>
</parent-component>
I'd like to be at a deep nested component and reference any of the parent components and their models or trigger an event inside one of them. Bonus if I can access sibling components, etc.
Traveling down was easy enough with
this.$.idOfChildComponent.event()
I have tried dispatchEvent, domHost, shadowRoot, can't seem to get any further up the component tree then the direct parent or get an error back that something is undefined, is not a function, etc.
Is there a way like React to pass a reference down as a property. The docs do not seem to be helpful nor scouring the internet.
Thanks!
update
So I am not sure if this is the correct way but it works ok calling a parent function from a child function.
<parent-component id="parentComponent">
<some-component>
<component-i-am-starting-from></<component-i-am-starting-from>
</some-component>
<some-other-component>
</some-other-component>
</parent-component>
componentIAmStartingFromFunc(){
document.getElementById('parentElement').parentElementFunc()
}
However does not seem to work for siblings?
** Update **
I essentially did the same the to call the sibling event by calling the parent from one of its children, and then sent out a trigger to the sibling which is also a child component.
Calling a parent function from child ;
child-component.html (polymer 2.x)
this.dispatchEvent(new CustomEvent('upway-func', {detail: {op:"Optionally I can send some data"}}));
child-component.html (polymer 1.x)
this.fire('upway-func', {detail: {op:"Optionally I can send some data"}});
parent-component.html
...
<child-component on-upway-func='_someFunction'></child-component>
...
_someFunction(d){
console.log(d.detail.op); // "Optionally I can send some data"
}
Here this link for more detail
Have you tried using this.parentElement?
Ask yourself: if I were a span in a div, how would I get to the div?
If you want to find a particular element in the ancestor chain by selector, you can use .closest() in good browsers or https://github.com/jonathantneal/closest
The message system mentioned in another answer can work but doesn't help you with positional relationship traversing which I assume your question was requiring. Passing ids and/or objects down can be used with messages in some cases.

Can't target method inside other component

How to target method inside other component?
I'm working on a project where I want to target a method inside another component. I press a button inside the dashboard component and I want to change the data inside my line-chart component (which uses vue-chartjs). How can I target this method?
Well you could target it over $refs however, this is pretty dirty, as it prodvides a pretty strict binding of your componentes.
A better solution would be to trigger an event (eventbus) or over an prop.
You can call children's method by referencing them through refs
In your example, your dashboard's template should looks like this :
<template>
<div>
<button #click="$refs.chart.yourMethod()">Call child method</button>
<line-chart ref="chart"></line-chart>
</div>
</template>

Categories