When we register some icons in MatIconRegistry
and access to them in SSR
, we have some errors and icons aren't displayed.
Display icons and not have error in the console
Icon aren't displayed and we have error in the console
Create a component and register an icon in MatIconRegistry
:
import {Component, OnInit} from '@angular/core';
import {MatIconRegistry} from '@angular/material';
import {DomSanitizer} from '@angular/platform-browser';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
constructor(private _matIconRegistry: MatIconRegistry, private _domSanitizer: DomSanitizer) {
this._matIconRegistry.addSvgIcon('loader', this._domSanitizer.bypassSecurityTrustResourceUrl('assets/Icons/loader-default.svg'));
}
ngOnInit() {
}
}
@NgModule({
declarations: [
AppComponent
],
imports: [
// Make AppModule compatible with Universal
BrowserModule.withServerTransition({ appId: 'universal-app' }),
MatIconModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {
}
Access to it in server side rendering
:
<mat-icon svgIcon="loader"></mat-icon>
In the console you'll have this message:
Error retrieving icon:
ERROR [Error]
MatIconRegistry
should work in SSR
"dependencies": {
"@angular/animations": "^5.2.2",
"@angular/cdk": "^5.1.1",
"@angular/common": "^5.2.2",
"@angular/compiler": "^5.2.2",
"@angular/core": "^5.2.2",
"@angular/forms": "^5.2.2",
"@angular/http": "^5.2.2",
"@angular/material": "^5.1.1",
"@angular/platform-browser": "^5.2.2",
"@angular/platform-browser-dynamic": "^5.2.2",
"@angular/platform-server": "^5.2.2",
"@angular/router": "^5.2.2",
"@hapiness/config": "^1.1.1",
"@hapiness/core": "^1.3.0",
"@hapiness/ng-universal": "^5.2.2",
"@hapiness/ng-universal-transfer-http": "^5.2.2",
"@nguniversal/module-map-ngfactory-loader": "^5.0.0-beta.5",
"core-js": "^2.5.1",
"rxjs": "^5.5.6",
"zone.js": "^0.8.20"
},
"devDependencies": {
"@angular/cli": "^1.6.6",
"@angular/compiler-cli": "^5.2.2",
"@angular/language-service": "^5.2.2",
"@types/jasmine": "~2.8.3",
"@types/jasminewd2": "~2.0.2",
"@types/node": "^9.4.0",
"codelyzer": "^4.1.0",
"jasmine-core": "~2.8.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~2.0.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "^1.2.1",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.1.2",
"ts-loader": "^3.3.1",
"ts-node": "^4.0.1",
"tslint": "^5.9.1",
"typescript": "^2.6.2"
}
Anyone here ?
Having the same probleam here!
So bad but for them it鈥檚 only a minor issue even if universal
is one the most important feature in angular
For SSR, full URL is needed in order to retrieve svg icon.
When encountered to this issue, I fixed it with something like this:
import {Component, OnInit, Inject} from '@angular/core';
import {MatIconRegistry} from '@angular/material';
import {DomSanitizer} from '@angular/platform-browser';
import { PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
constructor(private _matIconRegistry: MatIconRegistry, private _domSanitizer: DomSanitizer, @Inject(PLATFORM_ID) private platformId: string) {
const svgUrl = 'assets/Icons/loader-default.svg';
// domain and port for SSR in this example is static. Use i.e. environment files to use appropriate dev/prod domain:port
const domain = (isPlatformServer(platformId)) ? 'http://localhost:4000/' : '';
this._matIconRegistry.addSvgIcon('loader', this._domSanitizer.bypassSecurityTrustResourceUrl(domain + svgUrl));
}
ngOnInit() {
}
}
I go this error instead error retrieving icon: <svg> tag not found
and absolute path doesn't solve this issue. I have searched through the internet and could barely find any solution or workaround for it, please help give me any hint if you can, thanks a lot
Hi there, do not take it wrong but what is the advantage of using mat-icon compared to img ?
With universal even using the method above I can see a flash of content forthe svg using
And I just spend 2hours on a bug linked to the solution above, unfortunatly no time to investiguate the real root issue behind as it s lie behind a lot of complexity with sessions, cookies and http interceptor server and session side.
I am just going to forget mat-icon for a while and use the native img for now...
A pity, but no choice I believe we need to be productive and use the right solution for the right app, in the mean time if some one can enlight me with why mat-icon would be abetter choice I am happy to hear and maybe finding the time to investiguate mat-icon solution more.
Thank you guys
Exemple of good arguments are:
Changing the SVG color.
I am facing the same problem with angular universal (prerendering)
Reproduction:
cd freelancer-theme && npm i
npm run build:prerender
Error retrieving icon:
Error retrieving icon:
Error retrieving icon:
Error retrieving icon:
Process finished with exit code 0
Note: I guess that the base-href
cli arg doesn't take any effect with MatIconRegistry
Got simular issue, but the icon appers suddenly after a few refreshes.
Just follow this receipt to use absolute paths on server side:
https://angular.io/guide/universal#using-absolute-urls-for-server-requests
If you don't need icons to be actually rendered by server you can just replace icons with epmty SVG
private registerIcon(name: string, filename: string) {
if (isPlatformServer(this.platformId)) {
/* Register empty icons for server-side-rendering to prevent errors */
this.matIconRegistry.addSvgIconLiteral(name, this.domSanitizer.bypassSecurityTrustHtml('<svg></svg>'));
} else {
this.matIconRegistry.addSvgIcon(name, this.domSanitizer.bypassSecurityTrustResourceUrl(`assets/path/to/icons/${filename}.svg`));
}
}
In this case all icons will be empty in server response but frontend will load them after loading
Even this example isn't working.
Seconding the concern something is up with mat-icons and svgs, even the angular material examples are broken
https://stackblitz.com/angular/yjprlknbxmgk?file=src%2Fapp%2Ficon-svg-example.html
For me it was the path to the icons themselves when using DomSanitiser. I changed my path "../assets/icon" to point directly to the assets folder "assets/icon", because it seems that the compiler does not automatically fix this during production.
Just run into this same problem! And it has nothing to do with server side!
here's the one I opened - https://github.com/angular/components/issues/19767. Might be related.
I ran into this issue as well and couldn't solve my problem until I realized that I had an interceptor that was changing all outbound request headers to application/json.
I fixed it by adding some extra logic to see if I was requesting a resource from the assets folder to fix it.
If any of you are still having this issue you might look at that.
For SSR, full URL is needed in order to retrieve svg icon.
When encountered to this issue, I fixed it with something like this:import {Component, OnInit, Inject} from '@angular/core'; import {MatIconRegistry} from '@angular/material'; import {DomSanitizer} from '@angular/platform-browser'; import { PLATFORM_ID } from '@angular/core'; import { isPlatformBrowser, isPlatformServer } from '@angular/common'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent implements OnInit { constructor(private _matIconRegistry: MatIconRegistry, private _domSanitizer: DomSanitizer, @Inject(PLATFORM_ID) private platformId: string) { const svgUrl = 'assets/Icons/loader-default.svg'; // domain and port for SSR in this example is static. Use i.e. environment files to use appropriate dev/prod domain:port const domain = (isPlatformServer(platformId)) ? 'http://localhost:4000/' : ''; this._matIconRegistry.addSvgIcon('loader', this._domSanitizer.bypassSecurityTrustResourceUrl(domain + svgUrl)); } ngOnInit() { } }
Facing same issue, with version 10.0.2 of @nguniversal/express-engine. @milosbr solution works indeed, however reading angular's doc about absolute urls, we shouldn't have to do this, unless I'm missing something...
If you are using one of the
@nguniversal/*-engine packages
(such as@nguniversal/express-engine
), this is taken care for you automatically. You don't need to do anything to make relative URLs work on the server.
@JGGentzel Do you have a way I can contact you by? I'd need some help in figuring out how to fix the interceptor issue.
Seconding the concern something is up with mat-icons and svgs, even the angular material examples are broken
https://stackblitz.com/angular/yjprlknbxmgk?file=src%2Fapp%2Ficon-svg-example.html
I'm also getting the error <svg> tag not found at MatIconRegistry...
with just a regular non-SSR Angular project. Like @aparroccini said, even the example in the docs has the same error. Anyone know how to fix?
Most helpful comment
For SSR, full URL is needed in order to retrieve svg icon.
When encountered to this issue, I fixed it with something like this: