Я пытаюсь передать ввод объекта в тег пользовательского элемента angular. Пользовательский элемент состоит из тега videojs. Элемент не читает ввод, который я даю в пользовательском теге элемента.
Этот код — мой компонент видеоплеера, который я хочу преобразовать в настраиваемый элемент.
import { Component, ElementRef, Input, On Destroy, OnInit, ViewChild,AfterViewInit, ViewEncapsulation } from '@angular/core';
import videojs from "video.js"
@Component({
selector: 'app-video-player',
templateUrl: './my-video-player.component.html',
styleUrls: ['./my-video-player.component.scss'],
encapsulation:ViewEncapsulation.Emulated
})
export class MyVideoPlayerComponent implements OnInit,OnDestroy,AfterViewInit {
@ViewChild('myVideoPlayer',{static:true})
myVideoPlayer:ElementRef
@Input() options:{
fluid:boolean,
aspectRatio:string,
autoplay:boolean,
controls:boolean,
// height:number,
// width:number,
sources:{
src:string,
type:string
}[],
}
player:videojs.Player;
constructor(
) { }
ngAfterViewInit(){
}
ngOnInit() {
this.player = videojs(this.myVideoPlayer.nativeElement, this.options, function onPlayerReady() {
console.info('onPlayerReady', this);
});
}
ngOnDestroy() {
}
}
Вот HTML для компонента видеоплеера
<video id = "video-js" preload = "none" class = "video-js vjs-default-skin" controls #myVideoPlayer></video>
Вот код appModule, в котором я преобразовал MyVideoPlayerComponent в пользовательский элемент.
import { BrowserModule } from '@angular/platform-browser';
import { CUSTOM_ELEMENTS_SCHEMA, DoBootstrap, Injector, NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { MyVideoPlayerComponent } from './my-video-player/my-video-player.component';
import { createCustomElement } from '@angular/elements';
@NgModule({
declarations: [
MyVideoPlayerComponent
],
imports: [
BrowserModule,
AppRoutingModule,
],
providers: [],
schemas:[CUSTOM_ELEMENTS_SCHEMA],
bootstrap: [AppComponent],
entryComponents:[MyVideoPlayerComponent]
})
export class AppModule implements DoBootstrap {
constructor(private injector:Injector){
const webComponent=createCustomElement(MyVideoPlayerComponent,{injector:this.injector});
customElements.define('custom-player',webComponent)
}
ngDoBootstrap(){}
}
После создания проекта или даже если я непосредственно использую внутри тестовый компонент, который я сделал в том же проекте angular. Он показывает компонент видеоплеера, но не воспроизводит видео, поскольку он не может прочитать источник, даже когда я предоставляю атрибуты.
Код, показанный ниже, показывает, как я пытаюсь ввести данные для пользовательского элемента.
<custom-player options = "{ autoplay: true, controls: true, sources: [{ src: '../../assets/video.mp4', type: 'video/mp4' }]}" ></custom-player>
Будет здорово, если вы изучите эту проблему.
Вот данный снимок экрана пользовательского элемента, который я объявляю.
Красная метка показывает, что он получает src, а выделенный маркер показывает, что он не помещает src в тег видео.
введите здесь описание изображения
🤔 А знаете ли вы, что...
Один из ключевых принципов Angular - это двунаправленное связывание данных, которое автоматически обновляет интерфейс при изменении данных и наоборот.
Вам не нужно ../../
при запуске из ресурсов (обычно это допустимая отправная точка из конфигураций).
Кроме того, вы хотите изменить <custom-player options=
на <custom-player [options]=
(без [] вы фактически передаете строку, а не объект).
Я полагаю, вы следовали какому-то туториалу вроде этого. Если приведенное выше не имеет никакого эффекта, попробуйте сравнить с этим примером, чтобы увидеть, есть ли другие важные различия.
Обновлено:
Очень простой пример привязки свойств:
// interface for options
export interface VideoOptions {
fluid?: boolean;
aspectRation?: string;
autoplay?: boolean;
controls?: boolean;
sources?: Sources[];
}
export interface Source {
src: string;
type: string;
}
// ParentComponent ts
export class ParentComponent {
options: VideoOptions = {
autoplay: true,
controls: true,
sources: [{ src: 'assets/video.mp4', type: 'video/mp4' }]
}
}
// ParentComponent html
<app-child-component [options] = "options">
</app-child-component>
// ChildComponent ts
export class ChildComponent {
@Input() options: VideoOptions;
}
// ChildComponent html
<div>
{{options?.fluid}} <br>
{{options?.aspectRatio}} <br>
{{options?.controls}} <br>
{{options?.autoplay}} <br>
<ng-container *ngIf = "options.sources">
<div *ngFor = "let source of options.sources">
{{source.src}} --- {{source.type}}
</div>
</ng-container>
</div>
Похоже, вы уже разобрались с этим из своих комментариев, но просто для того, чтобы прояснить для всех, кто оказывается здесь с той же проблемой, вот почему это происходит.
Когда вы конвертируете компонент в веб-компонент Angular, любые входные данные будут сопоставлены, как описано здесь:
https://angular.io/guide/elements#mapping
Пользовательский элемент содержит компонент Angular, обеспечивая мост между данными и логикой, определенными в компоненте, и стандартными API-интерфейсами DOM. Свойства и логика компонентов отображаются непосредственно в атрибуты HTML и систему событий браузера.
API создания анализирует компонент в поисках входных свойств и определяет соответствующие атрибуты для пользовательского элемента. Он преобразует имена свойств, чтобы сделать их совместимыми с пользовательскими элементами, которые не различают регистр. В именах результирующих атрибутов используются строчные буквы, разделенные тире. Например, для компонента с @Input('myInputProp') inputProp соответствующий пользовательский элемент определяет атрибут my-input-prop.
Пользовательский элемент просто содержит Angular, а не сам компонент Angular. Чтобы передать данные на вход, вы должны использовать атрибут, который Angular создает для этого элемента, аналогично тому, как вы используете атрибут данных. Значение атрибута представляет собой строку, поэтому вам необходимо преобразовать его в JSON и обратно, если вы хотите передать объект.