#angular #svg #angular-material #angular-httpclient
#angular #svg #angular-material #angular-httpclient
Вопрос:
Я пытаюсь реализовать кнопки с пользовательскими значками SVG, используя Angular Material 7.2 и Angular 7.2.11. Я не столкнулся с какими-либо проблемами при использовании стандартного шрифта значка материала. Однако пользовательские значки просто приводят к появлению «Значка ошибки при извлечении: <svg>
тег не найден» на консоли.
Я копался в коде в @angular/material/esm2015/icon.js и обнаружили, что _fetchUrl (), похоже, получает SVG, но тело объекта HttpResponse пустое, несмотря на фактический ответ, содержащий SVG, как подтверждено Firefox. Заголовки в объекте HttpResponse содержат правильную длину содержимого.
При вставке URL-адреса, сообщенного объектом HttpResponse, в браузер отображается правильный SVG.
_fetchUrl() использует параметр ‘text’ responseType для HttpClient::get(), что должно быть нормально, насколько я могу судить, несмотря на указание в ответе content-type: image/svg xml
. На всякий случай я переименовал SVG и дал ему расширение ‘txt’. Последующий ответ имел text/plain
тип содержимого, но тело HttpResponse по-прежнему было пустым.
Удаление реестра значков материалов из уравнения и простая get()
попытка приводит к той же проблеме. Запрос успешно завершен, SVG отправлен, но HttpResponse имеет пустое тело.
Модуль приложения:
import { HttpClientModule, ... } from '@angular/common/http';
import {
...
MatIconModule,
...
} from '@angular/material';
@NgModule({
...
imports: [
...
HttpClientModule,
MatIconModule
...
],
...
})
Компонент приложения:
@Component({
...
})
export class AppComponent {
constructor(private router: Router, private matIconRegistry: MatIconRegistry, private domSanitizer: DomSanitizer, private http: HttpClient, ...)
{
this.matIconRegistry.addSvgIcon('test_icon',
this.domSanitizer.bypassSecurityTrustResourceUrl('/assets/svg/test.svg'));
http.get('/assets/svg/test.svg', { responseType: 'text' }) .subscribe(svg => console.log(`Response: ${svg}`));
}
}
Компонентный HTML:
<button mat-icon-button>
<mat-icon svgIcon="test_icon"></mat-icon>
</button>
Тестируйте файлы SVG:
<?xml version="1.0" encoding="UTF-8" ?>
<svg width="64" height="64" version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="64" height="64" style="fill:rgb(0,0,0,0)" />
</svg>
<svg>Test</svg>
Вывод на консоль:
Request to access cookie or storage on “https://fonts.googleapis.com/icon?family=Material Icons” was blocked because we are blocking all third-party storage access requests and content blocking is enabled. calendar
Angular is running in the development mode. Call enableProdMode() to enable the production mode. core.js:21273
Error retrieving icon: <svg> tag not found icon.js:867:81
Запрос / ответ:
GET /assets/svg/test.svg HTTP/1.1
HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: *
Accept-Ranges: bytes
Content-Type: image/svg xml; charset=UTF-8
Content-Length: 219
ETag: W/"d9-8SqOE9sCdf/cpMgr8wAdHVFXV g"
Date: Tue, 02 Apr 2019 00:36:12 GMT
Connection: keep-alive
<?xml version="1.0" encoding="utf-8" ?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<rect x="0" y="0" width="32" height="32" style="fill:rgb(0,0,0,0)" />
</svg>
Ответ №1:
Наконец-то удалось отследить проблему до HTTP-перехватчика в проекте. Это приводило к удалению тела ответа.
Комментарии:
1. Здравствуйте, я сталкиваюсь с такой же проблемой прямо сейчас. Вы также выяснили, как предотвратить его удаление из тела? Поскольку мне нужен перехватчик, чтобы исправить SSR для пользовательских svg-файлов в Material-UI
MatIconRegistry
.2. В моем случае это было нечто подобное, http-перехватчик заменял URL-адрес для вызова конечной точки сервера. Решается с помощью условия if, подобного
path === assests ? _not replace_ : _replace_
Ответ №2:
Вы можете следовать этому фрагменту кода для каждого добавления настраиваемых значков материалов в реестр материалов. Значки Я поддерживаю перечисляемый список значков и использую методы загрузки значков. Шаг 1: Сначала создайте IconService.
import { Injectable } from '@angular/core';
import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser';
import { environment } from 'src/environments/environment';
import { Icons } from '../../enums/icons.enum';
@Injectable({
providedIn: 'root'
})
export class IconService {
baseURL: string = environment.baseURL;
constructor(
private matIconRegistry: MatIconRegistry,
private domSanitizer: DomSanitizer
) { }
public registerIcons(): void {
this.loadIcons(Object.values(Icons), this.baseURL 'assets/svg/icons');
}
private loadIcons(iconKeys: string[], iconUrl: string): void {
iconKeys.forEach(key => {
debugger;
this.matIconRegistry.addSvgIcon(key, this.domSanitizer.bypassSecurityTrustResourceUrl(`${iconUrl}/${key}.svg`));
});
}
}
Шаг 2: Внедрите службу в свой app.module.ts в разделе provider
@NgModule({
declarations: [
AppComponent,
NavMenuComponent
],
imports: [
AppRoutes,
NgbModule,
BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
HttpClientModule,
FormsModule,
BrowserAnimationsModule,
MatMenuModule,
MatSidenavModule,
MatIconModule,
MatTooltipModule,
ToastrModule.forRoot(),
],
providers: [ ToastrService , CookieService, ErrorService, HttpService, StorageService, IconService
],
bootstrap: [AppComponent]
})
export class AppModule { }
Шаг 3: Внедрите службу значков в файл конструктора app.component.ts и вызовите методы registerIcons
import { Component } from '@angular/core';
import { IconService } from './core/services/icon/icon.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
constructor(private iconService: IconService) {
this.iconService.registerIcons();
}
}
Ответ №3:
this.domSanitizer.bypassSecurityTrustResourceUrl('./assets/svg/test.svg'));
Вы видите разницу?
Комментарии:
1. Да, я должен был упомянуть, что пробовал разные пути, хотя, как я уже упоминал, он отлично находит SVG и отвечает на запрос правильным SVG, что подтверждено с помощью сетевого анализа Firefox. Проблема возникает после того, как он получает SVG и пытается его проанализировать. Однако, просто ради моего здравомыслия, я пошел дальше и попробовал этот измененный путь еще раз, и это не помогло.