(jQuery to Vue.js) Dynamic element event handling - javascript

Found out about vue.js and would like to rewrite some part of my jQuery code to vue. My problem is about handling the elements that are dynamically created.
If it was being written on jQuery, .on() on a parent element would work. Unfortunately, this doesn't work on Vue.js
I found a similar case here: http://forum.vuejs.org/topic/151/vue-js-not-listening-to-dynamically-created-elements/4
evan the creator replied:
You can't, because Vue doesn't work this way. Use v-if and components, don't add HTML on the fly.
I did not get it and can't find any help regarding this. Rewriting everything to vue would take a lot of time. Would like jQuery and vue to work together.
Again, How do I handle events of elements that are being created dynamically?

Related

Angular: best way to access component properties & functions in click handler of child element of <svg>

I am having the same error as this person:
Add onclick event to SVG element
But I am having it in Angular which makes it even harder to deal with.
I want single SVGPathElement to be clickable & access component properties and functions in this click handler. But this is giving me the error 'property undefined' or 'function doesn't exist'.
According to this answer:
Add onclick event to SVG element
It's because all of the JavaScript must be included inside of the SVG for it to run.
But I cannot even do what the mentioned answer Add onclick event to SVG element suggested, since I get an error probably because Angular cannot create the component when parsing the html.
I also looked at http://xn--dahlstrm-t4a.net/svg/html/from-svg-to-parent-html-script.html (mentioned in the comments of the above answer) but that gave me the same error as in the picture above.
Now the second requirement to the solution to my question:
I am planning on having many different svgs and interacting differently with them. So manually pasting some <script> into the svg won't be a scalable nor maintainable solution for me. So actually I would prefer not doing this over the html with <script> tags at all.
If anyone has a good solution to solve both of my inquries in angular I would be greatful.
Additional Info:
I am using the ionic framework but I don't think it matters in this case
One possible alternative solution:
One could use ReactJS instead of Angular.
SVGPathElement<->Component interaction works in ReactJS without doing anything manually. I have no idea why but there is no such errors maybe because the component is not a class but rather a function. This would be great to know why exactly! I don't want to use ReactJS since I am not familiar with it. But maybe it's my best option to just switch frameworks since SvgPathElement<->Component interaction is a key part of my mobile app (it's like the seterra mobile app (https://play.google.com/store/apps/details?id=com.seterra&hl=en&gl=US)).
I found the culprit:
Don't do this (Angular doesn't allow it for some reason):
ngOnInit() {
document.querySelectorAll('.area').forEach((element: Element) => {
element.addEventListener('click', this.clickHandler);
}
);
}
Instead you have to add the click handlers manually like this:
<svg id="svgroot">
<path ... (click)="clickHandler()">
If anyone knows how to make this work by adding click handlers programmatically then this would make the solution a lot more automated/scalable/maintainable.
Adding click handlers programmatically to the SvgPathElement works in ReactJS for some reason, probably due to some internal differences between how the frameworks generate components.

Integrating jQuery plugin with React

I'm using jQuery nestable plugin https://dbushell.com/Nestable/ in my React App. I know that there will be problems when we use jQuery in React.
jQuery nestable solves my business needs, can't find the exact requirements in react drag/nestable components. So I have used this jQuery plugin.
The real problem is : while dragging an element by using this jQuery plugin, it clones the DOM, apart from this everything is in react.
Initialized the jQuery nestable functionality like below:
componentDidMount() {
this.$node = $(this.nestable); // this.nestable is a ref
this.$node.nestable({
group: 1,
maxDepth: 4,
expandBtnHTML:"",
collapseBtnHTML:""
});
}
the above code will let me drag the group2 among all other DOM elements like below image:
group2 is the draggable element here.
after dragged, I can see that group2 apperaed twice and I guess jQuery plugin clones the dragged element like below:
and in developer tools :
But In react developer tools, I can see that DOM is correct.
I don't know, how to rectify this problem. I'm unable to update the full code here because the code base is large.
In react developer tools, I can see that DOM is correct, and in native DOM is not !!
Is it possible to replace native DOM by virtual DOM after setState or is it possible for react to trace DOM handled by jQuery ?
I accept # Patrick Evans comments, I'm looking for a solution here or suitable react based component like jQuery nestable.
Any help on this will be helpful.
React-nestable seems to have the same behavior as that jQuery plugin and could save you a lot of trouble. Mixing jQuery with React is super easy to cause trouble in my experience.
There is one hacky solution here:
In Nestable you have on change event. So you keep order of list as a state of component and while you drag and drop an element you can update the state and list should be re-rendered.
Please see that you can use key in list elements to optimize it a bit.
I am sure this will solve your issue.

Attaching jQuery events to angular components when they load

I'm coding a website using Angular JS 1.5 and making heavy use of the new component directive; So far, it is great. I love the components system.
But I'm having a bit of trouble getting jQuery 3.0 and angular components to talk to each other. Take this code, for instance;
(function($){
$(document).ready(function() {
$('[animate-bounce]').velocity({
translateY: '10px'
}, {
loop: true
}).velocity('reverse');
});
})(jQuery);
This works fine on a normal page, but because of the nature of how component works, it doesn't apply to components that are instantiated after $(document).ready. That makes sense, of course. They don't exist, so it can't wire up to them.
I know about the component lifecycle; Specifically, the $onInit function. I know that I can hook the jQuery into that. But I'm wanting certain jQuery code to apply to any component that gets activated, and I wanted to try and keep the activation of it out of the component code.
Is this possible to do? Is there a 'global' $onInit for component that will let it run jQuery bindings when any component loads? Or is there a replacement for the old live() binding in jQuery that will trigger when new DOM is added?
Ciel, your are attempting jQuery in Angular app where entire angular life cycle does not allow jQuery to interfere. Though it is not impossible to achieve but I will recommend to not use it due to following reasons.
jQuery events and data bindings will not handled by Angular so forget about events and data removal.
Handling JQ events extensively will kill the purpose of using Angular as framework.
-Workaround -
Try using Angular component as much as possible, you may give a hand using link and compile functions while creating an Angular component.
Hope this will hep

How to use jQuery plugin that modify the DOM with Reactjs?

I have a question following this post:
issue
How should I use a jQuery plugin that modify the DOM with react. Like jimfb kindly answered to me on GH, React shoud return a pre-rendered component. So my question is, how exaclty call a function like remodal() in my example, during the lifecycle of a component?
I suggest you to read my answer here:
Why should addChangeListener be in componentDidMount instead of componentWillMount?
But basically, when you need to integrate some existing plugin or code with React, the painless way is to generally call that code on the componentDidMount method and do the event listening the old way. If you are with jQuery, that means you should use something like
$(this.getDOMNode()).find('.some-child').on('click', this.onChildClick)
By doing it this way, you will miss some of the most important features regarding event delegation in React (see https://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#under-the-hood-autobinding-and-event-delegation) but that should not be a problem unless you wanted to create hundreds of event listeners.

use templates but keep jquery bindings?

I currently have a LARGE single-page application, with each html "view" being built purely with jQuery DOM creation/manipulation. The javascript files are ridiculously large, and adding or changing a view is a very complex process. I started thinking about using backbone.js and templating. However, if I use templating, will I lose the ability to bind jQuery events and data to elements?
No, you can still apply all your jQuery magic to your resulting DOM elements. Templating will simplify the process of creating DOM elements, but the result is the same and can be used identically.
Why would you lose any capability if you are using templates with jQuery? You can instantiate elements via templates, and bind away as you always have - at template time or via preset .live() handlers.
Although I would take a look to make sure Backbone.Router doesn't give you a more elegant way to handle your interactions.
If performance is a bottleneck issue, inline your events in your template.
<input type="button" onclick="doit(this);">

Categories