how to dismiss dropdown when click outside? - reactjs

i am learning react+typescript. i want to implement a control like fluentui dropdown:
basically I draw a div and set its position 'relative' then use absolute layout on the dropdown panel. but there is a problem:
how to dismiss the dropdown when click outside area?
Can you share good practices?

Let's assume dropdown is dom node of your dropdown area
and dismissDropdown function to dismiss it.
Then your code could look like this:
window.addEventListener("click", function (e) {
// if outside of dropdown
if (!dropdown.contains(e.target)) {
dismissDropdown()
}
});
contains: https://developer.mozilla.org/en-US/docs/Web/API/Node/contains
Basically we check if element on which user clicked is inside dropdown or dropdown itself, and if not then dismiss it.

Related

Angular Material Limit toggling of MatExapansionPanel to only clicking arrow

I'm using Angular Material to create my toggling panels. I still want my panel to expand and contract when clicking the arrow, but I not when I click anywhere in the panel header because I want to add a checkbox at the top. Currently, when I click on my checkbox, the toggling event of the panel fires when I click the checkbox. The 'change' event of the checkbox still fires afterward.
I don't mind to have the panel toggles only when clicking its arrow, how do I stop the toggling of the panel from firing when clicking anywhere in the top?
HTML
<mat-expansion-panel #panel
(opened)="togglePanel()"
(closed)="togglePanel()">
<mat-expansion-panel-header>
<mat-panel-title>
<mat-checkbox (change)="onCheckChanged($event)">
<label>Options 1</label>
</mat-checkbox>
</mat-panel-title>
<mat-panel-description></mat-panel-description>
</mat-expansion-panel-header>
</mat-expansion-panel>
TypeScript
togglePanel() {
// this event fires before the onCheckChanged event
}
onCheckChanged(event: MatCheckboxChange) {
// this event fires after the togglePanel event
}
There is currently a feature request in for this, about a year old so not sure of the ETA... seems to be some workarounds people are playing with that might help but appear to have mixed reviews.
https://github.com/angular/material2/issues/8190
Revision
I tested the following in stackblitz and it seems to work.
HTML
<mat-accordion>
<mat-expansion-panel #expansionPanel>
<mat-expansion-panel-header (click)="expandPanel(expansionPanel, $event)">
Component
expandPanel(matExpansionPanel, event): void {
event.stopPropagation(); // Preventing event bubbling
if (!this._isExpansionIndicator(event.target)) {
matExpansionPanel.close(); // Here's the magic
}
}
private _isExpansionIndicator(target: EventTarget): boolean {
const expansionIndicatorClass = 'mat-expansion-indicator';
return (target['classList'] && target['classList'].contains(expansionIndicatorClass) );
}
Stackblitz
https://stackblitz.com/edit/angular-5kugm3?embed=1&file=app/expansion-overview-example.html

How to cange value of button overflowText property?

I have panel wiht toolbar with buttons. Panel resizable when it small buttons hide in menu. In menu it show icon and value of overflowText. But on click button i need change overflowText.
expandClick: function (btn) {
var me = this;
btn.blur();
btn.overflowText = btn.overflowText === "expand" ? "reduce" : "expand";
view.fireEvent('expandGraph', view);
}
in browser's console on breckpoint i see right value but there is no change in interface. Why?!
btn.setConfig( name, [value] );
try to use this function to set specific initial configs dinamically.
Sometimes the button din't refresh his state if you modify directly the variable
Try to refresh component layout with doLayout() method after you change overflowText property.

Fade In / FadeOut angular js

I'm pretty new to AngularJS and would like to know how to do this:
$(".change-agency-clicker").on("click", function (e) {
e.preventDefault();
$(".form").fadeOut(function () {
$(".agency-change-form").fadeIn();
$("#agentForm").show();
});
});
So when the user clicks on a button it fadeout a panel and fades in a second panel.
Just follow this steps:
When the element .change-agency-clicker is clicked (ngClick), toggle the value of a variable.
If this variable is true, hide (ngHide) the element .form.
If this variable is true, show (ngShow) the elements .agency-change-form and #agentForm.
Animate all that things with CSS transitions (here is a tutorial), and don't forget transition-delay if needed.
The idea, of course, is to think "declarative" and no more "imperative"!

Wijdropdown not working after being hidden

Using Wijmo Open ComponentOne's Dropdown, I tried to place it in a registration form that displays when a button is clicked. This form is inside a jquery modal window.
The problem is that it is not displayed like a wijdropdown inside the form.
I supposed that since is was hidden, then it wasn't part of the DOM and so I added a method in the callback of the function that displayed the modal window; when the modal window finishes displaying, then call the .wijdropdown() on the element. However, it didn't work.
In conclusion: the select tag is not being wijdropdowned...
¿Any recommendations?
Script
$(function() {
// show overlay
$('#product-slideshow-overlay-trigger').live('click', function() {
var $registerOverlay = $('#product-slideshow-overlay');
//left position
var positionLeft = ($(window).width() - $registerOverlay.width())/2;
$registerOverlay.css({'left':positionLeft});
//show mask
$('#mask').fadeIn();
$registerOverlay.slideDown(function()
{
console.log("Started");
/**Add WijmoDropdown***/
$('#estado').wijdropdown(function()
{
console.log("Did the wijdropdown");
});
console.log("Ended");
});
return false
});
}); // end document ready function
Refresh the wijdropdown when the dropdown is not hidden:
$('.wijmo_drp').wijdropdown("refresh");
or
Find the wijmo component and check if it's visible or not (styled or not).
And trigger the visiblity changed event when you display the modal window.
if($('.wijmo-wijobserver-visibility').is(':visible'))
{
$('.wijmo-wijobserver-visibility').trigger("wijmovisibilitychanged");
}

ExtJS MVC Controller ref to Tab Panel's active tab

I have an MVC app which has a Tab Panel rendered as the only item in the viewport. Within the tabs I would like to put the same type of component, for which the event handling is equal within all tabs.
Therefore I need an ExtJS MVC Controller ref to the active tab, that would lead me to execute events on the components in the active tab. Is it possible to have such a ref?
My current approach is this:
get reference to Tab Panel
call getActiveTab()
call the controller events for the component in active tab
Is it possible to encapsulate the above 3 steps in one controller ref? Would be beautiful :-)
I'm using ExtJS 4.1.
Personally, I think controller refs are overrated. This sounds like a simple case where you can use one as you describe, but I prefer to listen to the event, and navigate from the firing component to the one I need.
In your case, assuming your tab panel contains regular ext panels, I'd do something like the following:
onButtonClick: function (button) {
var panel = button.up('panel[tab]');
if (panel) {
panel.someMethod();
}
}
The up method will find the closest ancestor that is of xtype panel and has a property named tab. If you have more specific xtypes or known properties, use those instead.
The panel should be the active one (else how was its button clicked?) but you can check that by going up another level to the tab panel and getting the activeTab there.
onButtonClick: function (button) {
var panel = button.up('panel[tab]'),
tabPanel = button.up('tabpanel'),
activeTab = tabPanel && tabPanel.getActiveTab();
if (panel && panel === activeTab) {
panel.someMethod();
}
}
Say your tabPanel has itemId: 'content'. Inside that panel you will have bunch of tabs and on each tab you will have bunch of buttons (as an example). And you want to handle all these button's click in one controller. Do I understand you correctly?
I believe that simple ref inside your controller would work:
this.control('#content button', {
click: this.buttonClicked
}
});

Resources