Custom HTMLElement not bubbling click event - dom-events

I am dabbling with customerElements:
customElements.define('state-button',
class extends HTMLElement {
constructor(...args) {
super(...args);
this.state = 0;
let o=this;
this.t = {
0:"<button class='btn btn-info'>"+(o.innerHTML)+"</button>",
1:"<button class='btn btn-warning'>Are you sure???</button>",
2:"<button class='btn btn-danger'>Last chance....</button>"
};
this.addEventListener("click", this.handleClick,{capture:false});
}
connectedCallback() {
this.setAttribute("data-toggle", "modal");
this.setAttribute("data-target", "#confirmModal");
this.setAttribute("data-jc_id", this.getAttribute("data-id"));
this.render();
}
render() {
console.debug("state", this.state);
this.innerHTML=this.t[this.state];
}
handleClick(event) {
this.state = (this.state+1) % 3;
this.render();
}
setState(state) {
this.state = state;
this.render();
}
}
);
This is just me testing how it works. The button is supposed to change state AND open modal Bootstrap4 window. But the modal never gets triggered.
If I add super.click(); inside handleClick() it will change state twice (as the event is triggered again).
If I do not addEventListener the Bootstrap 4 modal window triggers just fine. So it appears my event is stopping other events.
return true; at the end of handleClick has no effect.
What am I missing?

I found a way around it to the same effect. But I am sure it is not the correct way of doing it.
When I add the eventlistener this.addEventListener("click", this.handleClick,{once:true}); it will be removed once triggered. This will cause the bootstrap 4 modal window to trigger as well.
Then at the end of handleClick I just add the click event as above again.
As I said - it is a workaround.
I am still interested in why my event stops other click events....

Related

Parent component should be active when angular material dialog is open

I have implemented angular material dialog in my project , I also made the dialog draggable. Everything is working fine. Now I have a new requirement where I should keep parent component active when I open the dialog . Anyone have any idea on how to achieve this ?
you can add a class to disable the particular part based on the dialog.
In your component, you can add a variable to identify the dialog state.
openDialog(): void {
this.dialogActive = true;
const dialogRef = this.dialog.open(DialogOverviewExampleDialog, {
width: '250px',
data: {name: this.name, animal: this.animal},
hasBackdrop: false
});
dialogRef.afterClosed().subscribe(result => {
this.dialogActive = false;
console.log('The dialog was closed');
this.animal = result;
});
}
}
and you can add a class to HTML based on the dialog state.
<div [class.modal-page-disable]="dialogActive"> disable part </div>
<div> enable part </div>
Then finally add the style to disable the part.
.modal-page-disable {
pointer-events: none;
background: transparent;
opacity: 0.5;
}
you can refer the sample code here.

AngularJs - My ui-sref anchor tag can't be cancelled by event.preventDefault()

I have this tag:
<a ui-sref="MyModule">My Module</a>
When I click on the link, this will be executed:
$scope.$on("$locationChangeStart", function (event) {
if (!confirm('You have unsaved changes, continue?')) {
event.preventDefault();
}
});
But still my view will switch to MyModule interface.
try using this:-
$scope.$on("$stateChangeStart", function (event) {
if (!confirm('You have unsaved changes, continue?')) {
event.preventDefault();
}
});
You are using UI-router. which is state based.

How to remove loader when entering escape in react?

I need to come out from page after entering escape button , when the page takes much time for loading. I need to exit that loading when it takes longer time
For loading I am using
dispatcher.dispatch({
type:'Loader',
showLoader: true
})
You will have to add an event listener i.e. keyup or keydown. When any key is pressed, just compare its keyCode with escape button's keycode i.e. 27.
In react, event listener should be added in componentDidMount and removed in componentWillUnmount.
Here is an example. You can modify logic according to your requirements.
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
loading: true,
}
this.onKeyUp = this.onKeyUp.bind(this)
}
componentDidMount() {
document.body.addEventListener('keyup', this.onKeyUp)
}
componentWillUnmount() {
document.body.removeEventListener('keyup', this.onKeyUp)
}
onKeyUp(e) {
if (/27/.test(e.keyCode)) {
this.setState({ loading: false })
}
}
render() {
if (this.state.loading) {
return <div>Loading</div>
}
return <div>Loaded</div>
}
}
Hope it helps.

How to get on scroll events?

I need to get scroll events from a div with overflow: scroll in my Angular 2 app.
It seems onscroll event do not works on Angular 2.
How could I achieve that?
// #HostListener('scroll', ['$event']) // for scroll events of the current element
#HostListener('window:scroll', ['$event']) // for window scroll events
onScroll(event) {
...
}
or
<div (scroll)="onScroll($event)"></div>
You could use a #HostListener decorator. Works with Angular 4 and up.
import { HostListener } from '#angular/core';
#HostListener("window:scroll", []) onWindowScroll() {
// do some stuff here when the window is scrolled
const verticalOffset = window.pageYOffset
|| document.documentElement.scrollTop
|| document.body.scrollTop || 0;
}
for angular 4, the working solution was to do inside the component
#HostListener('window:scroll', ['$event']) onScrollEvent($event){
console.log($event);
console.log("scrolling");
}
Listen to window:scroll event for window/document level scrolling and element's scroll event for element level scrolling.
window:scroll
#HostListener('window:scroll', ['$event'])
onWindowScroll($event) {
}
or
<div (window:scroll)="onWindowScroll($event)">
scroll
#HostListener('scroll', ['$event'])
onElementScroll($event) {
}
or
<div (scroll)="onElementScroll($event)">
#HostListener('scroll', ['$event']) won't work if the host element itself is not scroll-able.
Examples
Using Event Binding
Using HostListener
Alternative to #HostListener and scroll output on the element I would suggest using fromEvent from RxJS since you can chain it with filter() and distinctUntilChanges() and can easily skip flood of potentially redundant events (and change detections).
Here is a simple example:
// {static: true} can be omitted if you don't need this element/listener in ngOnInit
#ViewChild('elementId', {static: true}) el: ElementRef;
// ...
fromEvent(this.el.nativeElement, 'scroll')
.pipe(
// Is elementId scrolled for more than 50 from top?
map((e: Event) => (e.srcElement as Element).scrollTop > 50),
// Dispatch change only if result from map above is different from previous result
distinctUntilChanged());
To capture scroll events and see which of the scroll event is being called, you have to use host listener who will observe the scroll behavior and then this thing will be detected in the function below the host listener.
currentPosition = window.pageYOffset;
#HostListener('window:scroll', ['$event.target']) // for window scroll events
scroll(e) {
let scroll = e.scrollingElement.scrollTop;
console.log("this is the scroll position", scroll)
if (scroll > this.currentPosition) {
console.log("scrollDown");
} else {
console.log("scrollUp");
}
this.currentPosition = scroll;
}
Check the multiple examples as mention on this URL.
I will recommend the method 3,
https://itnext.io/4-ways-to-listen-to-page-scrolling-for-dynamic-ui-in-angular-ft-rxjs-5a83f91ee487
#Component({
selector : 'ngx-root',
templateUrl : './app.component.html',
styleUrls : [ './app.component.scss' ],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent implements OnDestroy {
destroy = new Subject();
destroy$ = this.destroy.asObservable();
constructor() {
fromEvent(window, 'scroll').pipe(takeUntil(this.destroy$))
.subscribe((e: Event) => console.log(this.getYPosition(e)));
}
getYPosition(): number {
return (e.target as Element).scrollTop;
}
ngOnDestroy(): void {
this.destroy.next();
}
}
However Method 4 is not bad.

extjs twinText focus when click on trigger

I have a TextFiled component, where add clear trigger. like this one:
this.config.triggers = {
clear: {
cls : (Ext.baseCSSPrefix + 'form-clear-trigger'),
handler : function() {
this.setValue();
}
}
}
...
So, and I handle an event focus
this.text= Ext.create('TwinText', {
width: 400,
emptyText: 'dddd',
listeners: {
scope: this,
focus: this.show,
},
editable : false
});
Now, when I click on trigger clean, the focus event was fired. How can I suspend this?
You can add the click event to your Textfield component instead of using focus.
Ex. in the TwinText definition add:
initEvents: function () {
this.callParent(arguments);
this.mon(this.inputEl, 'click', this.onClick, this);
},
onClick: function (e) {
this.fireEvent('click', this, e);
}
then listen for the "click" event instead of "focus".