I have the following div and it shows a login button on a nav bar, but if the screen is small I want to hide this button. For some reason when I add the fxHide.gt-sm=true it doesn't hide when I make the screen smaller. How can I fix this?
<div fxHide.gt-sm="true">
<ng-template #login>
<button
mat-icon-button
[routerLink]="['/auth']"
[style.width]="'auto'"
[style.overflow]="'visible'"
matTooltip="Login or Register"
class="topbar-button-right">
<span>Login</span>
<mat-icon>exit_to_app</mat-icon>
</button>
</ng-template>
</div>
What you want:
Default behavior: shown
If lt-md (less than medium screen) => hide
With your current implementation you have:
Default behavior: shown
If gt-sm (greater than small screen) => hide
Now, what you want translates into:
<div fxShow fxHide.lt-md>
You could invert the logic into
<div fxHide fxShow.gt-sm>
That should do it.
fxHide.gt-sm means hide it when it's greater than small. Change it to fxShow.gt-sm if you only want it visible on larger screen.
Faced the same thing but after importing FlexLayoutModule it worked.
If the OP is having issues making the fxHide command work at all, this question may be a duplicate of Angular Material FlexLayout fxHide does not hide
You must ensure that FlexLayout is imported in all modules that wish to use it:
https://stackoverflow.com/a/62672981/4440629
Related
I want the "Setting" drawer to respond to window resize like it does on this settings page.
Taking a look at their style elements, I can see a lot of mat-drawer css classes that (I presume) handle the drawer's state and events:
mat-drawer mat-drawer-side mat-drawer-open etc.
Is there documentation on these css classes on how they function? Are they even Material classes?
Trying this, I would ignorantly expect the side-nav to be open by default without using opened on mat-drawer but it does not work.
<mat-drawer-container
class="mat-drawer-container flex-auto sm:h-full mat-drawer-transition mat-drawer-container-has-open">
<mat-drawer #drawer class="mat-drawer sm:w-96 dark:bg-gray-900 mat-drawer-side mat-drawer-opened"
style="transform: none; visibility: visible;">
<p>Sidenav open</p>
</mat-drawer>
<button type="button" mat-button (click)="drawer.toggle()">
Toggle sidenav
</button>
</mat-drawer-container>
I would like to achieve this drawer functionality with a similar method like theirs without using Angular HostListener decorator like this.
I'm sorry I'm reposting this but my previous question was marked as closed due to absence of minimal reproducible code. I have attached a stackblitz link with this one.
Original question - Bootstrap search-select dropdown but now when I try to search through the list and the dropdown opens on top, the list gets reduced and floats mid-air
Please don't close this one too. This is very important for my project and I have been stuck on this one for 16 hrs.
I have created a custom search select dropdown using the bootstrap dropdown in my Angular 8 project. The functionality works perfectly but the issue lies when the dropdown opens up on top of the element. Now when I search using the search box, the list gets updated accordingly and gets shortened but it keeps floating mid-air. You can see the issue in the GIF below.
Issue GIF - https://imgur.com/a/SeMVjns
As you can see in the first case when I search, the list gets shortened and it floats mid-air. What I want is when the list gets shortened, it still appear directly above the Expert dropdown button without any space in between.
Below is my HTML code:
<div class="dropdown h-100" [ngClass]="{'statusDropdownContainer': config.src != 'unavailability'}">
<a class="btn btn-white dropdown-toggle mb-2 statusFilterDropdown h-100 w-100 flex-middle" [ngClass]="{'btnDisable': disable, 'srcUnavailability': config.src == 'unavailability' }" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="text-truncate">{{config.src != 'unavailability' ? config.dropdownTitle + ':' : ''}} {{selectedValue ? selectedValue : 'All'}}</span>
</a>
<div class="dropdown-menu w-100 pt-0" aria-labelledby="dropdownMenuButton">
<input type="text" class="w-100 p-2 searchInput" [ngModel]="searchValue" (ngModelChange)="filterDropdown($event)" placeholder="{{config.placeholder}}">
<a *ngFor="let option of filteredList; let i=index" class="dropdown-item pointer text-contain" [ngClass]="{'alternateBackground': i%2 == 0 }" (click)="selectValue(option.name, option.unique_code)">
{{option.name}}
</a>
<div *ngIf="filteredList.length <=0" class="text-center text-muted mt-1">No {{config.user}} found</div>
</div>
</div>
What CSS changes do I need to make?
Stackblitz - https://stackblitz.com/edit/angular-ivy-nghkhp?file=src/app/app.component.html
Edit: I found the exact issue that's causing the problem. Bootstrap's dropdown uses popperJS to position the dropdown. PopperJS calculates the dropdown's position on the scroll event, so whenever the window scrolls, the dropdown's dimensions are recalculated (uses transform CSS). But in my case, since there is no scroll, the dimensions are not calculated and the dropdown has the same height as before the user searches something in the search box. But what I want is for the dimensions to be recalculated every time there is a change in the list's data. Any suggestions would be helpful. Thanks.
Bootstrap's dropdown uses popperJS to position the dropdown. PopperJS calculates the dropdown's position on the scroll event, so whenever the window scrolls, the dropdown's dimensions are recalculated (uses transform CSS).
One approach could be to give the height of the body slightly more than the viewport height and then programmatically trigger the scroll on ngModelChange
STACKBLITZ SOLUTION
You may add to CSS (You may also hide the vertical scroll-bar if not required with overflow-y: hidden;)
body {
min-height: 101vh;
}
And you might add scroll down 1px and scroll up 1px in your filterDropdown(e) method on ngModelChange as below to achieve the desired effect.
filterDropdown(e) {
console.log("e in filterDropdown -------> ", e);
window.scrollTo(window.scrollX, window.scrollY + 1);
let searchString = e.toLowerCase();
if (!searchString) {
this.filteredList = this.data.slice();
return;
} else {
this.filteredList = this.data.filter(
user => user.name.toLowerCase().indexOf(searchString) > -1
);
}
window.scrollTo(window.scrollX, window.scrollY - 1);
console.log("this.filteredList indropdown -------> ", this.filteredList);
}
I am trying to implement the notification component that will show the list of the items and will be opened by clicking on the notification icon on the fixed navigation bar on the top. I don't think it's a menu bar. Because the menu provides the actions that can be performed and it can also have a sub-menu.
https://www.w3.org/TR/wai-aria-practices/#menu
Can anyone let me know what should be the aria-role of such kind of components?
Below is the code sample. I will open the template dynamically by clicking on the notification icon button:-
<button aria-label="notifications">
<mat-icon class="mr-md">notifications</mat-icon>
</button>
<!-- Notification template -->
<div class="notifications__item">
Notifications
<li *ngFor="let notification of notifications" class="notifications__item">
<mat-icon class="notifications__icon material-icons-round">
{{ notification.icon }}
</mat-icon>
<div class="notifications__content">
<div [ngClass]="{ 'notifications__warn': notification?.type }">
<span>{{ notification.title }}</span>
</div>
<div>{{ notification.description }}</div>
</div>
<small class="notifications__caption">
{{ notification.duration }}
</small>
</li>
</div>
There are still a lot of things to consider that your example doesn't cover, so this isn't a complete answer, it is just pointing you to the relevant WAI-ARIA depending on what route you take.
The button
The first thing to consider is the button. You need to tell screen reader users what state it is currently in. For this we use aria-expanded to indicate whether the item it controls is currently opened or closed. (aria-expanded="true" for open, aria-expanded="false" for closed.)
At the same time we want to indicate what item this button controls (as the notification list isn't 'owned' by the element - for example if it was an <li> with a nested <ul> in a menu then the list would be 'owned' by it).
For this we would use aria-controls or aria-owns and point it to the ID of the element it controls. For the difference between them see this stack overflow post as a good explanation, in this example I would say it is aria-controls but yet again depends on your implementation and positioning in the DOM.
With regards to the button itself and where it sits in your menu, this is still considered navigation so it should sit within your <nav> element. However if this sits outside of your navigation along with say a 'help' and 'account' section you may consider those items part of a toolbar. (yet again I would say it doesn't apply here but something to look at)
Also it doesn't appear to be applicable here but if you include any links etc. within the 'popup' / modal that shows the notification list (i.e. a 'view all notifications' link), you should consider aria-haspopup="true"
The notification list
Right so we have a button pointed to the container (don't forget to give the container the relevant ID for aria-owns or aria-controls). Next what about the container itself?
Well in this example it appears that the container should be treated like a modal.
So for this reason you need to consider:-
trapping focus in the modal,
close with Escape,
returning focus to the button that activated it on close,
providing a close button that is accessible by keyboard,
a title for the modal (even if it is visually hidden)
What I would recommend is add some of the accessibility features above, try it with a screen reader and keyboard and see if it is easy to use. Once you have decided on your pattern ask some more questions on specific use case issues as the above is general guidance.
A few things to consider based on your markup
Additional things to consider from your example:-
use aria-hidden="true" on your icons, they don't add anything for screen readers (assuming your notification.title is descriptive).
For the notification title consider making it a relevant heading (<h2> - <h6> depending on position in document.
Don't forget to add some visually-hidden text that describes the warning level (I can see you have some form of colouring / distinction in [ngClass]="{ 'notifications__warn': notification?.type }" - expose the same info to screen readers.)
You currently have a <li> within a <div> - maybe change the outer <div> into an <ul> so it is semantically correct (<div class="notifications__item"> into <ul class="notifications__item">)
I hope the above is useful to set you on the right track, a lot to read but after reading the linked articles you should be able to make a better decision on what pattern you are using (as I didn't even mention making this a sub item within your menu) and can then ask some more questions on specific details you don't yet understand.
final thoughts / tips
test with a screen reader - this is the biggest tip I can give on working out how WAI-ARIA works and interacts with things.
Also if you are ever in doubt as to whether a WAI-ARIA attributre is applicable it is better to not include it.
Incorrect use or WAI-ARIA is actually worse than not including it at all so make sure you understand when to use an attribute reasonably well before implementing it. If I am ever unsure (as it still happens to me!) I tend to look at 2 or 3 examples of it in use and see if my pattern fits the examples I looked at.
I develop a small angular material application. My objective is to obtain the following design for a card, that fit on every kind of media (desktop, mobile, tablette)
my "app.component.html" is the following
<mat-toolbar color="primary">
<div style="width:100%;" class="md-toolbar-tools" >
Liste des annonces
<span flex></span>
</div>
</mat-toolbar>
<div fxLayout="row">
<div fxFlex="20%"></div>
<div fxFlex="60%">
<mat-card *ngFor="let annonce of annonces; let i = index" style="border:red">
<mat-card-content style="border:blue">
<img src="./../assets/image/image{{i+1}}.jpg" alt="Avatar" style="position:absolute;top:0px;left:0px;width:40%;height:100%">
<div class="container" style="left: 45%; top:10px;">
<div style="left:70%;">{{annonce.dateConstruction | date:'dd MMMM yyyy'}}</div>
<div>
<span>{{annonce.type}}</span>
<span style="float:right">{{annonce.prix}}</span>
</div>
<h4>{{annonce.surface}}</h4>
<h4>{{annonce.adresse}}</h4>
<div style="left:45%;">
<p>{{annonce.description}}</p>
</div>
</div>
</mat-card-content>
</mat-card>
</div>
<div fxFlex="20%"></div>
</div>
<router-outlet></router-outlet>
I am terrible in placing elements and text in html pages, and therefore in a material card. I obtain the following output in the browser
Furthermore when I shrink my browser, I can't see the element and text on the rigth of the image placed correctly. I tried to reproduce the same on stackblitz (https://stackblitz.com/edit/angular-pexq15?file=package.json), but I got trouble with the angular material tags that are not taken in account.
So could you help me and tell me what is going wrong and comment the correct code so I improve myself in html/css. Thanks a lot
You should try leveraging the #angular/flex-layout Library for this. Additionally, you should consider moving your styles to your CSS File, since this will make your HTML File a lot cleaner and the styles more reusable. In your stackblitz you missed to include the styles for #angular/material in your SCSS File and you did not import the #angular/flex-layout module, which is why your stylings were messed up.
I tried to fix your example on Stackblitz. To get the desired spacings for your text, simply add paddings or margins to the left of those elements. Also beware of your image: You have to add a fitting height property, or it will become cropped/stretched.
I'm making a webpage that's using bootstrap-modal.js from Twitter bootstrap
bootstrap-modal.js allows you to create "modals." You basically click a button and a little javascript window slides down where you can display different content etc. Here's a demo http://jsfiddle.net/mjmitche/xt4aQ/44/
I'm going to have several buttons/modals on my webpage, so I have to set it up so each button triggers a different modal. I assume that the best way to do this is to give them different classes or ids
Problem, if I change the ids given by bootstrap-modal.js, it changes the properties of the modals...For example, it may remove or add a black screen backdrop etc. The fiddle linked to above shows how the code below works.
Question: Do you know how I could differentiate the modals so that each button triggers a different modal but allow them all to have the same properties?
<div id="modal-from-dom" class="modal hide fade">
<div class="modal-header">
×
<h3>Modal Heading</h3>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
Primary
Secondary
</div>
</div>
Button
<button data-controls-modal="modal-from-dom" data-backdrop="true" data-keyboard="true" class="btn important">Launch left Modal</button>
You said you can't use id's so why not classes? try adding a different class to each modal. Here is your updated fiddle: http://jsfiddle.net/xt4aQ/52/
And I tried changing the id to number "2" and it works just fine. Just copy all the code and change the id by appending an ascending number.