I Have multiple dom elements with same classname , i want to select all elements and using forEach function i want to add click event listener to it.
In vanilla javascript we select all elements using querySelectorAll
classname.forEach((e) => {
e.addEventListener('click', () => {
//logic
}
})
how to do same as above using vue js?
Related
I have a stenciljs component that has a nested stenciljs component:
<c-button-group>
<c-button></c-button>
</c-button-group>
In c-button-group template, I'm not using a slot and instead I'm using #Element() private element: HTMLElement to get all the nested elements after I render them in a loop.
#Component({
tag: 'c-button-group'
})
export class CButtonGroup {
#Element() private element: HTMLElement
render() {
return (
Array.from(this.element.children)
.map((child) => {
const el = child as ButtonInterface
return <c-button variant="grouped">{el.textContent}</c-button>
})
)
}
}
The reason why i use loop because i have to add attribute variant="grouped" for each nested element and i want to add it here, in the template. So this works but i noticed that if i assign a click event handler it doesn't work.
<body>
<c-button-group>
<c-button id="cBtn" #click="btnClickHandler">Years</c-button>
</c-button-group>
<script>
document.querySelector('#cBtn').addEventListener('click', () => {
console.log('Years')
})
</script>
</body>
Click event above doesn't work.
And seems this is obvious because in the render function i create a new 'c-button' based on a nested c-button.
My question is how do I pass all events that were assigned from the nested component to the new component that was created in the render function?
PS:
I noticed that if i use on-click attribute without a value to new c-button element, click event works:
Array.from(this.element.children)
.map((child) => {
const el = child as ButtonInterface
return <c-button
variant="grouped"
on-click
>{el.textContent}</c-button>
})
I just added on-click and it started working but in console i started getting errors:
TypeError: Failed to execute 'addEventListener' on 'EventTarget': parameter 2 is not of type 'Object'.
So at first this is not an option because i am getting that error and at second what if i need not only 'click' event, maybe there will be 5 or 10 events, so in that case i will have to add them all manually, not very comfortable to say the least.
Thank you so much in advance!
You can try using outerHTML and innerHTML
render() {
return (
Array.from(this.element.children)
.map((child) => {
child.setAttribute('variant', 'grouped')
return <div innerHTML={child.outerHTML}></div>
})
)
}
However this will only be able to pass events which are attached by attribute instead of addEventListener, as outerHTML is a string
<c-button-group>
<c-button id="cBtn" onclick="btnClickHandler()">Years</c-button>
</c-button-group>
Here btnClickHandler will work for rendered children elements
So the only way i found myself is to use <slot /> and #Element() private element: HTMLElement together.
#Element() private element: HTMLElement
componentWillLoad() {
Array.from(this.element.children).forEach(el => {
el.setAttribute('variant', 'grouped')
})
}
render() {
return <slot />
}
Using <slot /> allows as to use all events and using this.element.children gives the ability to edit DOM elements before their rendering, we can remove, add any attribute, class, and so on...
What is the alternative to document.getElementById in React Native? I want to access the element in the DOM. I am using a functional component.
You can use refs. Lets say you have a div, and you want to get a DOM reference.
const MyFuncComp = React.memo(() => {
const divRef = React.useRef(null)
/* your other logic here */
/* refer the div node using divRef.current - its the HTML DOM Node.
return (
<div ref={divRef.current}>
// whatever you want to render
</div>
)
})
Resources: https://reactjs.org/docs/refs-and-the-dom.html
I have existing web app in Vue. Now I need to create an event for each input/textarea focus. Is it possible to bind it globally so I don't have to add #focus="function" to each element?
Why wouldn't it be possible?
Get required elements
Assign whatever functionality you want
mounted () {
// Get all input elements with class="CLASS_NAME"
const inputs = document.querySelectorAll('input.CLASS_NAME')
// Iterate over elements and add each one of them a `focus` listener
inputs.forEach(input => {
input.addEventListener('focus', this.inputFocusHandler)
})
},
methods: {
inputFocusHandler (event) {
...
}
}
I currently have a component with a render function, to which I send data using a slot.
In short my component looks as follows:
export default {
render(createElement){
return createElement(
'div', {
'class' : 'className'
},
this.$slots.default
)
}
}
There is a bit more inside the render function that creates multiple elements and puts the slot content in each of the element (which is the reason I'm using a render function), but that's not relevant for this example.
I have another component which has this template:
<Component1>
<div>foo</div>
</Component1>
(component 1 being the component with the render function).
This all works nicely, but the problem is that when the word 'foo' changes, the component doesn't get updated. I can send a prop to the component to check wether the content gets changed (by putting a watcher on the prop), but how can I force the component to run the render function again?
Thanks!
So I'm using Jade (Pug) to render my templates via Node, and I'm trying to use React to interact with various HTML elements. Is there a special way to do this?
React (favourite-item.js)
var FavouriteItemButton = React.createClass({
getInitialState: function () {
return {favourite: false};
},
handleClick: function (event) {
this.setState({favourite: !this.state.favourite});
},
render: function() {
var text = this.state.favourite ? 'like' : 'haven\t liked';
return (
<p onClick={this.handleClick}>
You {text} this. Click to toggle.
</p>
);
}
});
RenderDOM.render(
<FavouriteItemButton />,
document.getElementById('example')
);
I've imported React/React DOM and obviously the file above. I have a HTML element on my Jade (index.jade) template:
p#example like
But nothing is changing on click, I presume it's down to the tags or some special way to render React elements via Jade.
My includes:
script(type='text/javascript' src='js/libs/react.min.js')
script(type='text/javascript' src='js/libs/react-dom.js')
script(type='text/babel' src='js/favourite-item.js')
I'm right in thinking I should include the type as text/babel?