elementRef является нулевым после построения углового приложения
В шаблоне компонента я выбираю элемент svg с ElementRef. Он работает нормально, но когда я собираю приложение и открываю его, elementRef имеет значение null.
@Component({
selector: 'app-svg',
template: `<div id="root">
<object [data]='trustedUrl' type="image/svg+xml" height="450" width="650" #dataSvg></object>
</div>`,
styleUrls: ['./svg.component.css']
})
constructor(private sanitizer: DomSanitizer, private elRef: ElementRef) {
}
целевой элемент elementRef
@ViewChild('dataSvg') dataSvg: ElementRef;
передать его в переменную elementRef
ngOnInit() {
this.elementRef = this.elRef.nativeElement.querySelector('#dataSvg');
}
после загрузки контента я выбираю svg:
ngAfterContentInit() {
const elementRef = this.elementRef;
// when content is loaded...
elementRef.addEventListener('load', function (event) {
// ...retrieve svg element
elementRef.querySelector ('svg') является нулем
когда я запускаю 'npm run build' и захожу в dist/index.html, contentDocument > имеет значение null:
4 ответа
Ты используешь @ViewChild('dataSvg') dataSvg: ElementRef;
но в вашем шаблоне вы не указали привязку для dataSvg
,
Есть 2 способа сделать это:
1) использование @Directive, как описано в Angular Docs2) использование ссылки на шаблон #
:в твоем случае:<object ... #dataSvg></object>
Не упоминается, если вы уже используете Директиву, но в коде шаблона у вас есть только id=dataSvg
Согласно официальному документу, вы не можете получить доступ к @ViewChild
элемент, если вы не делаете это в хуке AfterView (AfterViewInit
или же AfterViewChecked
) вместо OnInit
один.
- Вы можете найти здесь хорошую статью о различиях между
@ViewChild
,@ViewChildren
,@ContentChild
а также@ContentChildren
,
DOM еще не полностью встроен ngOnInit
, Вам нужно подождать, пока дети (шаблон здесь) будут созданы.
Вместо ngOnInit
вставьте свой код в ngAfterViewInit
,
Более подробную информацию о хуках в жизненном цикле компонентов можно найти в документации Angular.
В приведенном ниже месте явно дайте читать: ElementRef,
@ViewChild('dataSvg') dataSvg: ElementRef;
Должен быть
@ViewChild('dataSvg', {читать: ElementRef }) dataSvg: ElementRef;
С ElementRef связана угроза безопасности:
Разрешение прямого доступа к DOM может сделать ваше приложение более уязвимым для XSS-атак.
https://angular.io/api/core/ElementRef
Рассмотрите возможность использования Renderer2:
Я нашел свое решение совместимости для добавления элемента SVG:
в моем компоненте svg я устанавливаю источник svg с привязкой innerHTML, когда мой ввод изменяется, я загружаю svg сервисом, который безопасно возвращает данные svg:
привязка источника данных SVG в компоненте:
@Component({
selector: 'app-svg',
template: `<div id="root">
<div [innerHTML]="svgSafe" type="image/svg+xml" height="450" width="650" #dataSvg></div>
</div>`,
styleUrls: ['./svg.component.css'] ,
animations: [
]
})
загрузить источник SVG с вводом:
ngOninit() {
var url = this.data.url;
var id = 1;
if(url === 'assets/object_move.svg') {
id = 1;
}
if(url === 'assets/object_wait.svg') {
id = 2;
}
..
var dataSVG;
this
.loaderService
.getSVGData(id)
.subscribe((dataSvg) => {
this.svgSafe = this.sanitizer.bypassSecurityTrustHtml(dataSvg.data);
});
}