Open takamori opened 5 years ago
It does work. You can see the difference in your example if you remove it, select the second option in the select and open it again.
ah.... I didn't notice (or expect) that behavior. That's not quite the same as what I was looking to do, then, since the top choice overlaps the input field, which isn't the way that Exposed Dropdown Menu is spec'd. Is there an appropriate way to implement the Exposed Dropdown Menu from the Material Design spec?
It looks like the "exposed dropdown" is a new addition to the spec. @crisbeto we should think about adding an API to support that. It might make sense to deprecate disableOptionCentering
and instead have something like a panelPosition
property
@jelbourn I know that the functionality is a bit like a select, but wouldn't it be nicer to add it to the menu component or even ship it as a standalone component, since there are one or two differences, e.g. the style? This would also help people who read or follow the Material Design Guidelines and then look for the corresponding component in the Angular Material library.
In addition, the exposed dropdown menu also contains also things like a "user input" mode or a "inside a toolbar" mode (...I'm not even sure if you can/should use it outside of such a "toolbar"...), see the "Behaviour" section in the MDG. https://material.io/design/components/menus.html#exposed-dropdown-menu
@TheCom3di4n In my case, I was looking for the select functionality in the Material Design Guidelines, originally starting from "Text fields" and found it under menu, so I'd actually prefer that the Material Design Guideline folks consider at least providing a cross-link in the other direction.
@takamori I fully agree with you, I also think that this is more of a select, as I already wrote above, and would feel more comfortable if they would place this component under the select in the Material Design Guidelines, since its behavior rather describes a kind of the native HTML select (...exactly one option can be selected...).
By the way, I find it really unfortunate, for reasons like these, that there is no issue tracker or public forum for the Material Design Guidelines in which you can ask questions or even start and have such discussions. But I guess that's intentional.
The workaround for getting the exposed dropdown might just be adding margin in the panelClass.
here's the example: https://stackblitz.com/edit/angular-khatke-8xhpbc?file=styles.css
@tahaabu that visually looks correct, but once the dropdown is activated, you can't click on the menu to close the dropdown– it looks like there's a .cdk-overlay-pane
masking most of the menu. Did you ever find a way to get around this?
@tahaabu We have faced with the same issue as @kwong-yw .
Can't close dropdown by the arrow or by the area above and to the left in our case.
CSS: margin: 32px 16px;
We can't shift .cdk-overlay-pane because we have another mat-select on the same page.
Fixed(not the final version):
HTML:
<mat-select #mySelect panelClass="server-group-drop-down-list" (openedChange)="openedChange($event)"
TS:
@ViewChild('mySelect') mySelect; ... public openedChange(opened: boolean): void { this.isOpened = opened; } @HostListener("document:click", ["$event.target"]) public onClick(targetElement) { if (this.isOpened) { const element = document.querySelector('.server-group-drop-down-list'); // your mat-select class if (!element.contains(targetElement)) { this.mySelect.close() } } }
I think you can close the dropdown on document click as well.
The real way to fix this, without hacks, is to use the overlayDir
property of the select and set it's positions
.
https://material.angular.io/cdk/overlay/api
I do this AfterViewInit
like this. There may be a better way:
export class SelectComponent implements AfterViewInit {
@ViewChild(MatSelect) select: MatSelect;
ngAfterViewInit() {
this.select.overlayDir.positions = [
{
originX: 'center',
originY: 'bottom',
overlayX: 'center',
overlayY: 'top'
}
];
}
@akmjenkins Good point, but this option is already deprecated. It becomes private in version 10.
Workaround which unfortunately require some code. Also you should properly handle disabled selects.
Is there any alternative for solving this problem because I have a use case where the option should stick to the bottom or the top?
I think that the underlying issue here is that everything happens in the overlay-pane element but it isn't accessible through the components that use it. For example, the mat-select has a panelClass
Input which helps to customize the style of the panel, but in many cases it is not sufficient, especially if we need to "scope" the custom css in order to ensure it doesn't affect other components that use the cdk-overlay. What would be ideal is to also have access the cdk-overlay-pane that wraps the panel.
Maybe it makes sense to not only allow a "scope" to be added to the specific DOM panel elements of these components, but also the overlay-pane in which it resides. This is even easier to accomplish since there already exists such an Input in the overlay-directive : cdkConnectedOverlayPanelClass
. If the mat-select (and possibly other such components) exposed this input through one of it's own, it would allow the customization of the overlay behaviors and styling.
I don't know if this goes against some internal architectural guidelines for components in general at Google, but if it is acceptable, maybe all components that make use of the overlay-directive could benefit from exposing the cdkConnectedOverlayPanelClass
Input. In most cases the angular team would only need to support the class gets properly added to the overlay, and the responsibility of the custom behaviors and styling would fall in the hands of the developer adding the class. Might be a win-win for all.
Ended up using an approach similar to @isbor but with the twist of providing a custom implementation of the Overlay in the component's viewProviders. The new class extends the Overlay but adds logic to add a custom class in order to scope the overlay. The benefit to this is the classes are already set when the overlay renders, removing any kind of "temporary invalid states" that might be caused when attempting to manipulate the classes after the component renders.
See the example here: https://stackblitz.com/edit/angular-issue-14105
interesting post. Could you help me to solve my current problem with select-panel position. Issue: mat-options panel is overlapping the dropdown when the panel is not having enough space to display at the bottom of the dropdown hence I want to show it on the top of the dropdown without overlapping if we don't have enough space below.
the expected behaviour is: options cdk-overlay should display on top / below of the dropdown based on the space availability in the screen.
ngAfterViewInit() { this.select.overlayDir.positions = [ { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'top' }, { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom' } ]; }
this code snippet solves the above problem, we can change the positions my modifying the above option in the array.
Ended up using an approach similar to @isbor but with the twist of providing a custom implementation of the Overlay in the component's viewProviders. The new class extends the Overlay but adds logic to add a custom class in order to scope the overlay. The benefit to this is the classes are already set when the overlay renders, removing any kind of "temporary invalid states" that might be caused when attempting to manipulate the classes after the component renders.
See the example here: https://stackblitz.com/edit/angular-issue-14105
On angular 11 and above, you can set the select overlay panel class via provider:
@Component({
selector: "app-custom-select",
templateUrl: "./custom-select.component.html",
styleUrls: ["./custom-select.component.scss"],
providers: [
{
provide: MAT_SELECT_CONFIG,
useValue: { overlayPanelClass: 'custom-overlay-panel' },
},
],
})
Example: Stackblitz
Bug, feature request, or proposal:
disableOptionCentering as discussed on https://material.angular.io/components/select/api does not appear to have any effect and prevents implementing the "Exposed Dropdown Menu" mentioned at https://material.io/design/components/menus.html#exposed-dropdown-menu .
What is the expected behavior?
Setting disableOptionCentering to true would change the options to appear either below or above the mat-select field.
What is the current behavior?
The options appear over the field, whether or not disableOptionCentering is used.
What are the steps to reproduce?
https://stackblitz.com/edit/angular-khatke I've tried using