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

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.

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.

Is the inline event listener in JSX bad design? [duplicate]

I would like to ask a question about event handlers when used in HTML and React.
In the book Javascript and Jquery written by Jon Duckett, the author mentioned that using HTML event handler attribute is considered bad practice
for instance something like the following:
<button onClick="hide()">click me</button>
But recently I am starting to learn React and when a component is defined, there are many examples of event handlers used as an attribute and it seems common to do so, not getting criticism for doing so,
<button onClick={doSomething}>
xxxyyyzzz
</button>
Is there a reason to this? is it because this is the only way to bind a event handler in React?, from the way I see it React is essentially building the component element via HTML but uses the event handler attribute to assign an event to it,
so why is React bringing back a concept that is considered bad practice?
Why are inline event listeners bad practice?
HTML describes the content and structure of a document, CSS describes the appearance and JavaScript is about the logic or behavior. These things should be kept separately. HTML and JavaScript code shouldn't be mixed. Your example for that was:
<button onClick="hide()">click me</button>
This, however, does not apply to React: we don't have one HTML file. Instead, we have modularized components, which have their own structure, style and behavior.
In React, we don't want the separation of presentation and logic, but self-contained components. That's what sets it apart from an application using just "Vanilla JavaScript" / the DOM API.
In the previous era of Javascript, this is considered as bad practice because we want to seperate HTML and JS as much as possible for better code management. You cannot quickly navigate to your onClick within an HTML page with another bunch of button.
And here in React, you manage your application code through the component tree. I think the power of React are:
Modularity
Composition
DRY (don't repeat yourself)
Back to your simple example, the onClick handler will be easily managed inside your component. Maybe with some other handler as well but it still be convenient within the scope of 1 component. Depend on which level of your component hierachy, everything you want to do lies on the same page, same class, same function.

(jQuery to Vue.js) Dynamic element event handling

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?

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

KnockoutJS bind event after template render

I've been searching for a while, and I'm pretty confident this is a new question, and not a repeat like the title suggests. :)
Basically, I'm trying to find out if there is a subscribe-able event that KnockoutJS creates after a template render when using something like jQuery templates.
I'd use the built-in "afterRender" but I found out that it doesn't fire if the observable array is cleared. I built this demo to illustrate that problem: http://jsfiddle.net/farina/YWfV8/1/.
Also, I'm aware that I could write a custom handler...but that seems really unnecessary for what I need.
I just want one event that fires after the template finishes rendering.
My colleague actually solved this last night using something we were playing with before I went home.
So the whole "problem" with the events “afterRender”, “afterAdd”, and “beforeRemove” is that they act differently in conjunction with a "foreach" binding. KnockoutJS is nice enough to tell you this on their page, but for whatever reason it didn't actually sink in for me until I saw it in practice.
What really works is to scrap the whole "foreach" binding and use Knockout's native "data" bind like this:
data-bind="template: { name: 'item-template', data: items, afterRender: caller }"
Then "afterRender" works exactly as the name suggests.
I was under the impression that you couldn't iterate the collection and render new UI without foreach, but these examples illustrate that it does work.
http://jsfiddle.net/farina/kuFx2/1/ (Using object array style ViewModel)
http://jsfiddle.net/farina/QtZm2/1/ (Using function style ViewModel)
I made an example for both ViewModel styles because I sometimes need one or the other.
Thanks for the help Dan!!
Is beforeRemove is what you are looking for? I am not sure what behaviour you want to achieve. Please checkout this sample: http://jsfiddle.net/romanych/YWfV8/8/
Is it what you want or not?

Categories