You will first need to check if the icon exists before passing it to the registry, and then passing your fallback icon instead if it does not.
You could do this either via a http request or creating a new image element and binding to the onload
and onerror
functions.
Example using http:
app.component.html
<div *ngIf="iconsLoaded">
<div *ngFor = "let user of users">
<mat-icon [svgIcon]="user"></mat-icon>
<span>{{user}}</span>
</div>
</div>
app.component.ts
export class AppComponent {
users = ['user1','user2','user3','user4']
iconsLoaded:boolean
constructor(private iconRegistry: MatIconRegistry, private sanitizer: DomSanitizer, private http:HttpClient){
this.addUserIcons()
}
async addUserIcons(){
for(let user of this.users){
const iconPath = await this.getIconPathWithFallback(user)
this.iconRegistry.addSvgIcon(user, this.sanitizer.bypassSecurityTrustResourceUrl(iconPath));
}
// let the dom know when all icons have been loaded and block attempt rendering before (e.g. via *ngIf)
this.iconsLoaded=true
}
// use a get request to see if the svg exists, if not return a default svg
async getIconPathWithFallback(user:string){
const iconPath = `assets/icons/${user}.svg`
const response = await this.http.head(iconPath,{responseType: 'blob'}).toPromise()
// if the svg icon is found the response will have type svg. If file not found returns html
console.log('response type',response.type)
return response.type === 'image/svg+xml' ? iconPath : 'assets/icons/default.svg'
}
}
Here is a working stackblitz: https://stackblitz.com/edit/angular-ppbzvn
Output

If you were to use a standard <img>
tag instead of <mat-icon>
it would be possible to just bind to the onerror
call directly to replace the url if the image can't be found. This is discussed in another post here:
how can i check if image exists in assets folder using angular 4
and
Angular2: check file existance with http.get