I am having a scenario where I need only option in mat multi select. Currently I am adding a button along with the options, and added a functionality to select single item. The issue I am facing is the text Only is getting appended with the option. Here is the code snip:
<mat-select
[formControl]="selectionControl" (selectionChange)="selectionChange($event.value)" multiple
>
<mat-option class="position-relative options-wrapper"
*ngFor="let version of [1,2,3,4,5,6,7,8,9,10] [value]="version">
<span>{{version}}</span>
<button mat-button class="position-absolute only-btn" style="top:5px; right: 0px;"
>Only</button>
</mat-option>
</mat-select>
Any help to resolve this is appreciated.
I am having a scenario where I need only option in mat multi select. Currently I am adding a button along with the options, and added a functionality to select single item. The issue I am facing is the text Only is getting appended with the option. Here is the code snip:
<mat-select
[formControl]="selectionControl" (selectionChange)="selectionChange($event.value)" multiple
>
<mat-option class="position-relative options-wrapper"
*ngFor="let version of [1,2,3,4,5,6,7,8,9,10] [value]="version">
<span>{{version}}</span>
<button mat-button class="position-absolute only-btn" style="top:5px; right: 0px;"
>Only</button>
</mat-option>
</mat-select>
Any help to resolve this is appreciated.
Share Improve this question edited Feb 4 at 6:56 mat.hudak 3,2434 gold badges29 silver badges49 bronze badges asked Feb 4 at 6:24 Venkatesh PrasadVenkatesh Prasad 912 silver badges9 bronze badges3 Answers
Reset to default 2I'm not sure if I understand you correctly, but I guess this is what you are looking for
<mat-select
[formControl]="selectionControl" (selectionChange)="selectionChange($event.value)" multiple
>
<mat-option class="options-wrapper"
*ngFor="let version of [1,2,3,4,5,6,7,8,9,10] [value]="version">
<span>{{version}}</span>
<!-- Try without relative and absolute positions -->
<button mat-button class="only-btn" style="margin-left: 1rem">Only</button>
</mat-option>
</mat-select>
EDIT:
Try removing relative and absolute positions, they don't make much sense there. Try playing with margin
values.
A possible solution:
You could use a directive to show the button on hover. It will create and remove the button on mouseover and mouseleave, respectively. It will also listen any clicks on the button and emit true when clicked.
Please note that the directive's selector name and output variable need to be the same for the output to work the way it is given and used in the html.
directive:
@Directive({
selector: '[hoverButton]'
})
export class hoverButtonDirective {
@Output() hoverButton = new EventEmitter<boolean>();
constructor( private _elemRef: ElementRef, private _renderer: Renderer2 ) {}
@HostListener('mouseenter')
onMouseEnter() {
const onlyButton = this._renderer.createElement('button');
this._renderer.setProperty(onlyButton, 'textContent', 'Only');
this._renderer.appendChild(this._elemRef.nativeElement, onlyButton);
this._renderer.listen( onlyButton, 'click', () => {
this.hoverButton.emit(true);
});
}
@HostListener('mouseleave')
onMouseLeave() {
const child = this._elemRef.nativeElement.querySelector('button');
if (child) {
this._renderer.removeChild(this._elemRef.nativeElement, child);
}
}
}
html:
<mat-select [formControl]="toppings" multiple>
@for (topping of toppingList; track topping) {
<mat-option [value]="topping" (hoverButton)="buttonAction()">
{{topping}}
</mat-option>
}
</mat-select>
I believe that is what you are looking for. 'buttonAction()' represents the function you want triggered when only is clicked.
Hope it helps.
Update
If you want the only button to appear only on row hover (as presented here:https://stackblitz/edit/lo4s7v7g-x6byneht?file=src%2Fexample%2Fselect-multiple-example.html) you need to update the code as it follows:
<mat-form-field>
<mat-label>Toppings</mat-label>
<mat-select [formControl]="toppings" multiple>
@for (topping of toppingList; track topping) {
<mat-option [value]="topping">
<div class="row">
{{topping}}
<button class="only-btn" mat-button>Only</button>
</div>
</mat-option>
}
</mat-select>
</mat-form-field>
<style lang="scss">
.row {
display: flex;
flex-direction: row;
&:hover {
.only-btn {
visibility: visible;
}
}
}
.only-btn {
visibility: hidden;
}
</style>
Please note that this code is using scss to make it more compact. If you want add some fading effect (to make the transition from hidden to visible smoother) take a look on css animations.
Original answer
If this is the wanted result you need to update the content of <mat-option>
as it follows:
<mat-form-field>
<mat-label>Toppings</mat-label>
<mat-select [formControl]="toppings" multiple>
@for (topping of toppingList; track topping) {
<mat-option [value]="topping">
<div class="row">
{{topping}}
<button mat-button>Only</button>
</div>
</mat-option>
}
</mat-select>
</mat-form-field>
<style>
.row {
display: flex;
flex-direction: row;
}
</style>
For more infos on flex you could read this extensive and well written guide :
https://css-tricks/snippets/css/a-guide-to-flexbox/
P.S.
Of course using
is not elegant nor the best way to space stuff, you can go forward and add padding etc...