How to use multiple mat-drawer inside mat-drawer-container? - angular-material

After using multiple drawer inside a mat-drawer-container the backdrop is disabled & drawer opening one upon the other.
Below is the structure.
<mat-drawer-container autosize (backdropClick)="closeSidenav()" >
<mat-drawer #globalSearch [class.side-drawer]="!searchService.drawerWidth" position="end" disableClose [class.full-drawer]="searchService.drawerWidth">
<app-global-search></app-global-search>
<app-global-bookmark ></app-global-bookmark>
<router-outlet></router-outlet>
</mat-drawer>
<mat-drawer #globalbookmark [class.side-drawer]="!bookmarkService.sidenavWidth" position="end" disableClose [class.full-drawer]="bookmarkService.sidenavWidth">
<app-global-bookmark></app-global-bookmark>
<router-outlet></router-outlet>
</mat-drawer>
<mat-drawer-content>
<router-outlet></router-outlet>
</mat-drawer-content>
</mat-drawer-container>

Related

How do I replace the QUEUES content in twilio flex AgentDesktop?

I want to either replace the content element within the QUEUES element, or remove it and add a custom tab. Is this possible?
I was able to remove all the tab content using
flex.WorkerDirectory.Content.replace(<div key="tabs">CustomTabs</div>);
However, I want to keep the 'transfer' header so I can close that panel
This is a start
flex.WorkerDirectory.Content.remove("tabs");
flex.WorkerDirectory.Content.add(<div class="Twilio-Tabs Twilio Twilio-WorkerDirectoryTabs css-1vzbs6y" key="worker-directory">
<div class="Twilio-Tabs-Labels css-1a43y29">
<div class="Twilio-TabHeader css-y47si7">
<button class="css-1i3d2ep"><span class="Twilio">QUEUES</span></button>
<div class="Twilio-TabHeader-StateIndicator-Inactive css-1qqd035"></div>
</div>
</div>
<button type="button">SomeQueueName1</button>
</div>);
Twilio developer evangelist here.
You should target Flex.WorkerDirectory.Tabs, instead of Flex.WorkerDirectory. That way you have access directly to the Tabs content. First remove the queues tab:
Flex.WorkerDirectory.Tabs.Content.remove("queues");
You can then add a new tab like this:
Flex.WorkerDirectory.Tabs.Content.add(
<Flex.Tab
key="new-tab
label="New Tab"
>
<div>New tab content here</div>
</Flex.Tab>
);
Let me know if that helps at all.

What happened to w3-sidenav? Is it possible to use w3-sidebar instead without the drawbacks?

What happened to w3-sidenav? We now only seem to have w3-sidebar which is not as good as it always displays in large (laptop, desktop) machines.
Is it possible to use w3-sidebar, but avoid the always-on problem for large screens? I want it visible only when I say.
The w3 tutorials suggest that you use a class="w3-sidebar w3-bar-block" to build a side nav. You have different option of always display etc:
1) Always Display: Add Style="width=25%", and then to the adjacent div, add style="margin-left:25%"
2)Open over content:
a) add to sidebar style="display:none" id="mySideBar" <button onClick="we-close" class="w3-bar-iitem w3-large">Close × </button>
b) Add to content (Adjacent Div): <button class="w3-button w3-large" onClick="W3-open()">☰ </button>
c) Add script
function w3-open(){
document.getElementById("mySideBar").style.display="block";
}
function w3-close(){
document.getElementById("mySideBar").style.display="none";
}
Another option with this is to open the sidebar over the whole page, in which case you will use the same code as option 2 above, just add to the JS w3-open() function: document.getElementById("mySideBar").style.width="100%";
3) Collapsible & Responsive: (I think this is the one you will probably prefer):
a) Define sidebar div with
class="w3-sidebar w3-bar-block w3-collapse w3-card w3-animate-left" style="width: 200px" id="mySideBar">
<button class="w3-bar-item w3-button w3-large we-hide-large" onClick="w3-close()">close × </button>
b) Define the main wrapper div with
<div class="w3-main" style="margin-left:200px">
<div class="w3-blue">
<button class="w3-button …." onClick="w3-open()"> ☰ </button>
</div>
</div>
c) insert the javascript as per the above option 2, both w3-open() & w3-close()
Do not quote my code above, I just typed it freehand, so its probably riddled with errors.
Here is the w3school script for option 3
You can read more about sidebars here.

Angular mat-sidenav property isHandset$ | async explain

<mat-sidenav-container class="sidenav-container">
<mat-sidenav #drawer class="sidenav" fixedInViewport="true" [attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'"
[mode]="(isHandset$ | async) ? 'push' : 'push'" [opened]="!(isHandset$ | async)">
<mat-toolbar color="primary">Menu</mat-toolbar>
<mat-nav-list>
<a mat-list-item href="#">Link 1</a>
<a mat-list-item href="#">Link 2</a>
<a mat-list-item href="#">Link 3</a>
</mat-nav-list>
</mat-sidenav>
I do not understand what is written in the code (isHandset$ | async)please explain
'Handset' is one of the breakpoint names of angular material layout. The list of breakpoint names is Handset, Tablet, Web, HandsetPortrait, TabletPortrait, WebPortrait, HandsetLandscape, TabletLandscape, WebLandscape.
Please check https://material.io/design/layout/responsive-layout-grid.html#breakpoints for more information about material layout breakpoints
In your example above, isHandset$ is coming from the corresponding component .ts file. Please look for code similar to below in your component file.
isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
.pipe(
map(result => result.matches)
);
When you resize the browser and when browser width matches with handset (mobile phone screen) width isHandset$ sets to true. ! (isHandset$ | async) in turn sets 'opened' attribute of sidenav drawer to false and collapses the sidenav drawer.
As isHandset$ is an Observable property, therefore 'async' pipe is used for the asynchronous call.
With regard to #MuhammadMehdi's comment:
[attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'"
is used for accessibility. People that have disabilities and for example are blind need to use a screen reader, for that purpose they are adding the 'dialog' role on the small screen size (because the menu pops out like a dialog) and 'navigation' role on the desktop size because its always displayed and used for navigation.
Here you have some more info on aria roles
https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles

angular material mat-sidenav async content area not rendering in correct position

I have a sidenav that works great with mock data, but when I load the data for the sidenav asynchronously from a rest service, the content part renders on the entire page area, and then when the async call returns, the sidenav renders, and ends up covering part of the content area. If I close the sidenav and open again, it looks find. However, on initial load, I can't see the left part of the content.
<mat-sidenav-container fullscreen class="main-sidenav-container">
<mat-sidenav #sidenav mode="side" opened>
<mat-nav-list>
<mat-list-item disa *ngFor="let navBarItem of observableNavBarItems|async" (click)="onSelected(navBarItem.value)">
<img mat-list-icon class="{{navBarItem.icon}}" />
<h4 mat-line>{{navBarItem.name}}</h4>
</mat-list-item>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<router-outlet></router-outlet>
</mat-sidenav-content>
</mat-sidenav-container>
Any thoughts on how to fix this?
i fixed a similar Problem (using the MatDrawer) by setting the following MatDrawerContainer property according to the Angular Materials documentation: https://next.material.angular.io/components/sidenav/api
#Input()
autosize: boolean
Whether to automatically resize the container whenever the size of
any of its drawers changes.
Use at your own risk! Enabling this option can cause layout thrashing
by measuring the drawers on every change detection cycle. Can be
configured globally via the MAT_DRAWER_DEFAULT_AUTOSIZE token.
in my case:
<mat-drawer-container autosize="true" >
<mat-drawer #drawer mode="side" opened="true">
...
</mat-drawer>
<mat-drawer-content>
...
</mat-drawer-content>
</mat-drawer-container>
i had the same problem and i've found a solution that works fine in my case.
First of all, i needed my component hosting the mat-nav-list being invoked as soon as its view had been rendered.
In order to do this, i choose to decorate mat-nav-list with a directive (renderingDetector).
Here is the code:
import { Directive, AfterViewInit, Output, EventEmitter } from '#angular/core';
#Directive({
selector: '[renderingDetector]'
})
export class RenderingDetectorDirective implements AfterViewInit {
#Output() onViewRendered = new EventEmitter<void>(true);
ngAfterViewInit() {
this.onViewRendered.emit();
}
}
NOTE: as a possible solution, i also tried to move the whole mat-nav-list content into a separate component in order to control its life-cycle as well as it's been done inside the directive, but this approach headed to the application recharging the page every time i clicked on an item (so that all benefits of Single Page Application went lost).
On the other side, the hosting component keeps watching on it.
<mat-nav-list renderingDetector (onViewRendered)="viewRendered()">
In order to have the mat-sidenav-content being rendered exactly beside the menus we should properly set the margin-left property.
#ViewChild('sidenavRef') sideNavRef: MatSidenav;
#ViewChild('sidenavContentRef', {read: ElementRef}) sideNavContentRef: ElementRef;
viewRendered() {
this.sideNavContentRef.nativeElement.style.marginLeft = String(this.sideNavRef._width) + "px";
}
sidenavRef and sidenavContentRef refer to the mat-sidenav and mat-sidenav-content elements in the html file
<mat-sidenav-container>
<mat-sidenav #sidenavRef>
...
</mat-sidenav>
<mat-sidenav-content #sidenavContentRef>
...
</mat-sidenav-content>
</mat-sidenav-container>

How can I apply toggle switch between light and dark theme in AngularDart

I want to apply a toggle between dark and light theme in AngularDart.
app_component
<material-icon icon="brightness_2"
class="material-list-item-primary"
aria-hidden="true"></material-icon>
Dark Theme
<span class="material-list-item-secondary">
<material-toggle [checked]="dark" label="Off">
</material-toggle>
</span>
app_component.dart
class LayoutComponent {
bool dark = false;
}
I haven't tried but I think this is the way to do it.
Wrap your applications content into a component different from your root component and use *ngIf to enable the dark or non-dark version.
This will destroy and recreate all components. Therefore keeping the application status in global services might be a good idea.
app_component.html
<material-toggle [checked]="dark" label="Off"></material-toggle>
<my-app-inner *ngIf="!dark"></my-app-inner>
<my-app-inner *ngIf="dark" darkTheme></my-app-inner>
ensure DarkThemeDirective is listed in
directives: [DarkThemeDirective]
You can put the <material-toggle> everywhere in your application, you just need to ensure that the value *ngIf is bound to is updated accordingly.

Resources