Вот пример stackblitz , основанный на различных ответах здесь.
Директива ниже применяется к mat-select
, поэтому вам не нужно добавлять никаких дополнительных атрибутов. Он использует атрибут required
для выбора, чтобы знать, добавлять ли какие-либо пустые опции при открытии раскрывающегося списка.
Примечание : Вы не можете легко добавить элементы в базовый список используемых опций мата компонентом mat-select
, поэтому элементы опций mat добавляются вручную, и события также должны быть связаны вручную (я сделал это для события click
);
import { Directive, HostListener, OnInit, Renderer2, ElementRef, AfterViewInit } from '@angular/core';
import { MatSelect } from '@angular/material/select';
import { Directive, HostListener, OnInit, Renderer2, ElementRef, AfterViewInit } from '@angular/core';
import { MatSelect } from '@angular/material/select';
@Directive({
selector: 'mat-select'
})
export class OptionalMatSelectDirective {
constructor(private matSelect: MatSelect, private elementRef: ElementRef,
private renderer: Renderer2) { }
@HostListener('openedChange', ['$event'])
onOpenedChange( isOpened : boolean)
{
if(!isOpened || this.matSelect.required)
{
return; //Closing panel, or select is required
}
//Manually create a mat option DOM element
let matOption = this.renderer.createElement("mat-option");
this.renderer.setAttribute(matOption, 'class', 'mat-option');
//Bind events to the new mat option
this.renderer.listen(matOption,'click', ()=>
{
this.matSelect.value = "";
this.matSelect.close();
});
//Try to add the new mat option in first position of the list
let panel= document.querySelector('.mat-select-panel');
if(!panel)
{
throw "Cannot find mat select panel";
}
this.renderer.insertBefore(panel,matOption, panel.firstChild);
}
}