Parent component should be active when angular material dialog is open - html

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.

Related

Custom HTMLElement not bubbling click event

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....

How to close parent dialog from child in angular?

I have one parent dialog inside which there is one child dialog box resides.
In child dialog box there is a close button .
On click of this close button, I want to close both parent and child dialog box. How can we do it in angular6 ?
In my case works :
Parent:
const dialogRef = this.dialog.open(AssignResourcePageComponent);
dialogRef.componentInstance.modal_principal_parent.on('CLOSE_PARENT_MODAL',()=>{
dialogRef.close();
});
Child
#Output() public modal_principal_parent = new EventEmitter();
in the method close:
this.modal_principal_parent.emit('CLOSE_PARENT_MODAL');
You have to just pass the MatDialogRef of Parent dialog to the child dialog component in dialog data and close the same in child component code.
Please find below code
This is code of Parent Component dialog which opens Child dialog and sends parent MatDialogRef to child dialog component in Data :
#Component({
selector: 'confirmation-dialog',
templateUrl: 'confirmation-dialog.html',
})
export class ConfirmationDialog {
childDilogRef = null;
message: string = "Are you sure?"
confirmButtonText = "Yes"
cancelButtonText = "Cancel"
constructor(
public dialog: MatDialog,
#Inject(MAT_DIALOG_DATA) private data: any,
private parentDilogRef: MatDialogRef<ConfirmationDialog>) {
if(data){
this.message = data.message || this.message;
if (data.buttonText) {
this.confirmButtonText = data.buttonText.ok || this.confirmButtonText;
this.cancelButtonText = data.buttonText.cancel || this.cancelButtonText;
}
}
}
onConfirmClick(): void {
this.parentDilogRef.close(true);
}
// this method is used for opening child dialog
OpenChild(){
if (this.childDilogRef === null) {
this.childDilogRef = this.dialog.open(MyChildComponent, {
data: this.parentDilogRef, // parent dialog sent as data to child dialog component
});
this.childDilogRef.afterClosed().subscribe(result => {
this.childDilogRef = null;
});
}
}
}
This is code of child component which initializes provided ParentDialogRef to local dialogRef variable. and we close both the dialog ref on click of button on child dialog.
#Component({
selector: "child-dialog",
template: `<mat-dialog-content>
<p>
Click on button to close both dialogs
</p>
</mat-dialog-content>
<mat-dialog-actions align="center">
<button (click)="closeBoth()">close both dialogs</button>
</mat-dialog-actions>`,
})
export class MyChildComponent {
constructor(
public childDialogRef: MatDialogRef<MyChildComponent>,
public parentDialogRef : MatDialogRef<ConfirmationDialog>,
#Inject(MAT_DIALOG_DATA) public data: MatDialogRef<ConfirmationDialog>
) {
if(data){
this.parentDialogRef = data
}
}
// close the about dialog
onNoClick(): void {
this.childDialogRef.close();
}
closeBoth():void{
this.childDialogRef.close();
this.parentDialogRef.close();
}
}

Angular material input number spinner scrolling problem

In Chrome, when the mouse is in the input number field in Material, I can scroll the value with my mouse.
I uploaded the code to stackblitz: https://stackblitz.com/edit/angular-bpj321, and I found in Chrome I cannot scroll when the mouse is in the field, but in Firefox, I can scroll.
I do not want to scroll, so how can I prevent this?
I've added these lines in my app.component.ts
#HostListener('mousewheel', ['$event']) onMouseWheelChrome(event: any) {
this.disableScroll(event);
}
#HostListener('DOMMouseScroll', ['$event']) onMouseWheelFirefox(event: any) {
this.disableScroll(event);
}
#HostListener('onmousewheel', ['$event']) onMouseWheelIE(event: any) {
this.disableScroll(event);
}
disableScroll(event: any) {
if (event.srcElement.type === "number")
event.preventDefault();
}
It works.
You could disable the scrolling event on the input manually:
Find the input element:
const input = document.getElementById("your-input");
And disable the wheel default functionality:
input.addEventListener("wheel", function(event) {
event.preventDefault();
});

How to assign angular directive to html element by using ElementRef and Renderer2?

I am developing the drag and drop application in Angular 6 and on drop operation, I am creating the new HTML element (elements like 'DIV', 'textarea' etc.), dynamically and assign styles, attributes, default x and y coordinates to it by using ElementRef and Renderer2 features of application and adding the newly created HTML element to parent element on which drop operation is being performed.
I also have an angular directive created which attaches draggable behavior to the newly created HTML element so user can move it anywhere on the parent element. The partial code for directive is given below:
#Directive({
selector: '[appMovable]'
})
export class MovableDirective {
#HostBinding('style.transform') get transform(): SafeStyle {
return this.sanitizer.bypassSecurityTrustStyle(
`translateX(${this.position.x}px) translateY(${this.position.y}px)`);
}
private position = {x: 100, y: 0};
constructor(private sanitizer: DomSanitizer) {
}
#HostListener('dragStart') onDragStart() {
console.log('drag start');
// Code to calculate the start position of the control being dragged....
}
#HostListener('dragMove') onDragMove() {
console.log('drag move');
// Code to calculate the current position of the control while it is being dragged....
}
#HostListener('dragEnd') onDragEnd() {
console.log('drag end');
// Code to calculate the end position of the control being dragged and the the position of the control properly.....
}
}
While I am able to assign the styles, attributes and default x and y coordinates to the newly created element but I am not able to bind the 'appMovable' directive to newly created HTML element. The code to create the HTML element and assigning different attributes to it is as below:
#Directive({
selector: '[appDroppable]'
})
export class DroppableDirective {
constructor(private elementRef: ElementRef, private renderer: Renderer2) {
}
#HostListener('dragover', ['$event'])
public onDragOver(evt) {
evt.preventDefault();
evt.stopPropagation();
}
#HostListener('dragleave', ['$event'])
public onDragLeave(evt) {
evt.preventDefault();
evt.stopPropagation();
}
#HostListener('drop', ['$event'])
public onDrop(evt) {
evt.preventDefault();
evt.stopPropagation();
// Since text element is being dragged so create new textarea html control
const textareaElement = this.renderer.createElement('textarea');
this.renderer.setAttribute(textareaElement, 'placeholder', 'click to add content...');
this.renderer.setAttribute(textareaElement, 'class', 'proInput editing');
this.renderer.setAttribute(textareaElement, 'draggable', 'true');
//Assign the appMovable directive to element
this.renderer.setAttribute(textareaElement, 'appMovable', '');
// this.renderer.appendChild(newDivElement, textareaElement);
this.renderer.appendChild(this.elementRef.nativeElement, textareaElement);
}
}
When I inspect the newly created HTML element in the browser debugger tool, I can see the appMovable directive getting assigned to the HTML element but element does not behave as per the directive assigned to it.
Is there anything else needs to be done or there is any alternate option to get directive work properly with dynamically created HTML elements?

How to recognise which reactjs component I am clicking on?

I am trying to trigger an event for my reactjs component when it is outside it. Currently I have a collapsible div (blue background) that I want to close once the user clicks outside of it. I have an method pageClick in it to log the event but I can't find a property to use:
componentDidMount() {
window.addEventListener('mousedown', this.pageClick, false)
}
pageClick(e) {
console.log('testing=pageClick', e)
}
How can I detect whether I am on the component with the collapseclass or not so I can change the state of it?
codepen here
You can check the class of the clicked element to know if it belongs to your collapsible element
componentDidMount() {
window.addEventListener('mousedown', this.pageClick.bind(this), false)
// ^^^^^^^^^^
// bind your function pageClick to this so you can call setState inside
}
pageClick(e) {
const el = e.target;
if (e.target.classList.contains('blue')) {
this.setState({ open: false });
}
}
But this is a poor solution because if you have many different DOM nodes in your collapsible element e.target will be the element below the mouse, not the parent .collapse element.
So I suggest you to use a library to detect the click outside your element : react-onclickoutside do the job perfectly.
You can see an implementation of your use case using react-click-outside in this fiddle.
You can listen for click event on the document like this -
document.addEventListener("click", this.closeComponent);
As an example you can define your collapsible component like this -
import React, { Component } from 'react';
export default class CollapsibleComponent extends Component {
constructor(props) {
super(props);
this.state = {
style : {
width : 350
}
};
this.showComponent = this.showComponent.bind(this);
this.closeComponent = this.closeComponent.bind(this);
}
componentDidMount() {
document.addEventListener("click", this.closeComponent);
}
componentWillUnmount() {
document.removeEventListener("click", this.closeComponent);
}
showComponent() {
const style = { width : 350 };
this.setState({ style });
document.body.style.backgroundColor = "rgba(0,0,0,0.4)";
document.addEventListener("click", this.closeComponent);
}
closeComponent() {
document.removeEventListener("click", this.closeComponent);
const style = { width : 0 };
this.setState({ style });
}
render() {
return (
<div
id = "myCollapsibleComp"
ref = "ccomp"
style = {this.state.style}
>
<div className = "comp-container">
<a
href = "javascript:void(0)"
className = "closebtn"
onClick = {this.closeComponent}
>
×
</a>
</div>
</div>
);
}
}