我有一个带有自定义svg图标的角垫图标。我正在动态渲染svg图标。现在以防万一,如果实际的svg图标丢失了,我该如何设置默认的(静态)svg图标。
类似于img标签中的onError attr的东西。
谢谢, 西哈德
html:
<mat-icon svgIcon="{{row.username}}" //default_svg_icon_src// ></mat-icon>
component:
this.users.forEach(user => {
this.matIconRegistry.addSvgIcon(
user.username,
this.domSanitizer.bypassSecurityTrustResourceUrl("../assets/icons/"+user.username+".svg")
);
})
答案 0 :(得分:2)
您首先需要先检查该图标是否存在,然后再将其传递给注册表,然后再传递回退图标(如果不存在)。
您可以通过http请求或创建一个新的图像元素并绑定到onload
和onerror
函数来完成此操作。
使用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'
}
}
这是一个有效的堆叠闪电战:https://stackblitz.com/edit/angular-ppbzvn
如果您使用标准的<img>
标记而不是<mat-icon>
,则可能无法将图片直接绑定到onerror
调用以替换网址找到了。在另一篇文章中对此进行了讨论:
how can i check if image exists in assets folder using angular 4 和 Angular2: check file existance with http.get
答案 1 :(得分:1)
接受的答案有两个主要问题:
更好的解决方案:使用拦截器!
@Injectable()
export class SvgFallbackInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<unknown>, next: HttpHandler) {
const regex = /\.svg$/;
const isSvg = regex.test(req.url);
if (isSvg) {
return next.handle(req).pipe(
catchError(err => {
const defaultResponse = new HttpResponse({
body: `<svg> ...[your default svg]...</svg>`,
headers: err.headers,
status: 200, // or perhaps 302?
statusText: 'OK',
url: err.url,
});
return of(defaultResponse);
})
);
}
else {
return next.handle(req);
}
}
}