How to get DOM events triggered by jquery using observables - javascript

I am little confused,
I am using bootstrap theme in angular. Some one has written tab implementation as provided by bootstrap. But there is problem, it is in JavaScript. so events such as bs.tab.show are not captured by using observables. Observable.fromEvent does not run on subscription. The method used to trigger DOM event in bootstrap library is $(element).trigger('bs.tab.show', ...)
My basic understanding is whenever any event such as click, hover or in my case bs.tab.show is triggered from DOM, event goes in event stack, and observables is using same event stack to read events.
Could anyone point out difference?

It appears you may have the name of the events wrong.
If I use fromEvent with show.bs.tab instead, the event is triggered.
fromEvent(elem, 'show.bs.tab').subscribe(() => {
console.log("Heard")
})
Here is a StackBlitz demo

Related

Approaches in javascript of "Attributes directives" in Angular

I am learning Angular5. And I am reading the official documentation about Attribute Directeve
In particular, I read that in the section Respond to user-initiated events:
Of course you could reach into the DOM with standard JavaScript and attach event listeners manually. There are at least three problems with that approach:
1. You have to write the listeners correctly.
2. The code must detach the listener when the directive is destroyed to avoid memory leaks.
3. Talking to DOM API directly isn't a best practice.
Can you give me an example of this in javascript in order to compare the two approaches?
Angular
// html
<button (click)="onClick()">Click Me</button>
// ts
onClick(){
// run some code on click
}
Native js
<button id="my-button">Click Me</button>
// js
// attach click event
document.getElementById('my-button').addEventListener('click', onClick);
// remove click event on component destroy
document.getElementById('my-button').removeEventListener('click', onClick);
As the docs are saying
In native js, you have to grab the element you want to bind the event to then attach the click listener. You can see angular binds the click event to the element for you since you use the attribute directive.
In native js, when the component is destroyed you would have to detach/remove the event listener manually to avoid any memory leaks. Angular does this for you automatically.
Talking to DOM API directly isn't best practice. This is because angular is set up to run in other environments. For example using angular universal you can pre-render your code on the server. In this case the server does not have a window object. So talking to the DOM API directly would cause things to break in universal.

jQuery trigger() method

Could someone explain to me what exactly this means
trigger executes the code for the event handler but not actually executes the event itself?
Consider the following code:
$('#parent').on('click',function (event){
console.log(event);
});
$('#parent').trigger('click');
trigger does produce an Event object since it consoles it. So, in which way it does not execute the event?
jQuery has a rather nice event system, that handles events in a more complex way than the basic event bubbling. For instance it allows multiple events, of the same type, on an element.
That means that jQuery events sit on top of the browser events and add features. When you trigger a jQuery event it just send messages up the jQuery DOM tree, which causes things to respond, but it does not necessarily generate the native browser events.
You can still hit the native event generation by using the underlying DOM elements and methods that jQuery wraps:
// This will generate a click event "for jQuery to hear"
$('#parent').trigger('click');
or this does exactly the same as above:
$('#parent').click();
Whereas this will fire the native DOM click event "actually clicks the button/link":
$('#parent')[0].click();
Update (from A. Wolff):
Some jQuery click events are passed on to the native click event. An exception being anchor links (which do not). I would have to test it to see if native clicks are generated or not for buttons and other inputs.

Material Design Lite + React - Issues with Tooltips

Recently, I have been integrating Material Design Lite into my React web application. For the most part, everything has worked out just fine, but currently I am having some issues with React's event handling, which doesn't seem to play nice with some MDL components.
In particular, I have a DOM element with an onClick handler, which works perfectly fine, until a MDL Tooltip is added, which causes the onClick to no longer fire. I've tried pretty much every variation possible (put the tooltip somewhere else in the DOM, attach the onClick handler to a container div which has the tooltip as a child, etc), and I just can't seem to get it to work.
Here's a JSBin that demonstrates the issue (I've also included an example that uses jQuery to bind a click handler to the element after the component mounts, which actually DOES work):
http://jsbin.com/sewimi/3/edit?js,output
I have some theories as to why this isn't working, but I don't know enough about either React or MDL to verify any of them.
I believe it has something to do with the way React handles events, and for some reason, MDL seems to be clashing with it. From the documentation:
React doesn't actually attach event handlers to the nodes themselves.
When React starts up, it starts listening for all events at the top
level using a single event listener. When a component is mounted or
unmounted, the event handlers are simply added or removed from an
internal mapping. When an event occurs, React knows how to dispatch it
using this mapping. When there are no event handlers left in the
mapping, React's event handlers are simple no-ops
This makes it seem like MDL might be messing with React's internal mapping of events, which causes my click on the element to become a no-op. But again, this is just a complete guess.
Does anyone have any ideas about this? I would prefer not to have to manually bind an event listener in componentDidMount for each of my components that use MDL Tooltips (like I did in the example JSBin I provided), but that's the solution I'm going with for now.
Also, since I was not sure if this was an MDL specific bug, I opted to post this question here instead of on their issues page. If anyone thinks I should post it there as well, let me know, and I can do that.
Thanks!
I faced this same issue too. I was trying to capture event clicks on a mdl-menu__item. And you are right in that React's synthetic event system is clashing.
What happens is that if an event happens inside your React component, your component will be the last to hear of the event. My work around was circumvent reacts event and use a react component which helps to attach native events react-native-listener.
<NativeListener onClickCapture={this.onListClick}>
<li className='mdl-menu__item' >
{...}
</li>
</NativeListener>
// This will be called by the native event system not react,
// this is in order to catch mdl-menu events and stop the menu from closing
// allowing multiple fields to be clicked
onListClick(field, event) {
event.stopImmediatePropagation();
// console.log('click');
}
My solution was for the mdl-menu but I'm sure it applies to the tooltip too.
A little late but
componentHandler.upgradeAllRegistered();
gets dynamically loaded elements working.
Note: that if you move the target element via CSS position the tooltip does not render to the new position automagically, you will need to id it and position it too.

SAPUI5: How to bind a click event to horizontal layout?

Hi I'm developing my view in JS and I'm stuck in binding a click handler for my horizontal layout element. I've tried using Jquery
$("#myHorizontalLayout").bind("click",function(){window.alert()});
Which didn't work then I tried using attachPress with the element which obviously didn't exist. Please help.
Update:
The JS view is the default view of the application.
When on/bind does not work, it could be that the HTML of the control has actually not been created yet at this point in time. But even if you delay the binding, the re-rendering (re-creation of the HTML after changes) would remove your listener, at least when bound on the control itself.
A proper way of doing this is using the generic attachBrowserEvent function available on every control (here: on the layout) which internally handles all the rendering/rerendering stuff, see this example:
http://jsbin.com/hijutunefi/1/edit?html,output
attachBrowserEvent works for any browser event, as it attaches a new browser event listener to the root node of the control. For the most common browser events UI5 does event delegation, so for the "click" event and several others addEventDelegate can also be used, as pointed out by aborjinik.
Alternatively, listening on the <body> level with normal jQuery mechanisms should in general also work.
Which didn't work then I tried using attachPress with the element which obviously didn't exist. Please help.
Does this means that the element on which you are attaching event handler doesn't exists at this point? If this is the case you can hook the handler to some container, upper in the DOM hierarchy which you are sure that exists and filter the click events.
Example:
$("body").on("click", "#myHorizontalLayout", function(){
alert("Hey, you!");
});
As of jQuery 1.7, the .on() method is the preferred method for
attaching event handlers to a document. For earlier versions, the
.bind() method is used for attaching an event handler directly to
elements. Handlers are attached to the currently selected elements in
the jQuery object, so those elements must exist at the point the call
to .bind() occurs.
Reference here
So try replacing bind with on and let me know if it works or not.

Trigger Real Event with jQuery

It seems that jQuery's trigger() only runs event handlers that were bound with jQuery. I have some modules that use native browser event binding. Using the code from https://stackoverflow.com/a/2676527 works for me, but I'm wondering if there's something built in to jQuery that will do this?
Update from comments: apparently it works for click events on buttons. But not for change events on select boxes: http://jsfiddle.net/qxpXV/2/
For the record: hacking the other library to do its bindings with jQuery does make trigger() work, but I don't really want to do that.
You can do this by manually firing/dispatching an event (depending on the browser, fireEvent/dispatchEvent) directly on the DOM element. Code from this answer will handle the event dispatching, you'll just need to execute it against a DOM element and not the jQuery wrapper.

Categories

Resources