Я пытаюсь передать ввод объекта в тег пользовательского элемента 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 в тег видео.
Введите здесь описание изображения
Вам не нужно ../../ при запуске из ресурсов (обычно это допустимая отправная точка из конфигураций).
Кроме того, вы хотите изменить <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>
[prop]='someVal'
(связывание свойств) — это общий механизм angular для привязки значения к свойству в компоненте, указанном в шаблоне. Я бы порекомендовал вам переместить весь объект параметров из html в переменную в файле ts и передать его в ваш компонент, кстати. (html должен быть как можно более чистым). Кроме того, этот механизм не имеет ничего общего с тем, используете ли вы свой собственный или импортированный/родной компонент. Ссылка, которую я добавил, на самом деле делает то же самое, что и вы (с пользовательским компонентом проигрывателя, обертывающим тег видео), и использует [].
Хорошо сейчас. Я нашел причину, по которой мой пользовательский видеоплеер на самом деле не получал источник видео, а также остальные элементы управления. Я использую Videojs в angular внутри пользовательского компонента. VideoJs принимает объект в качестве параметров `<app-my-video-player [options] = "{ autoplay: true, control: true, sources: [{ src: '../../assets/video.mp4', type : 'video/mp4' }]}"></app-my-video-player> ` Как показано выше. Но когда я передаю один и тот же объект через атрибуты настраиваемого компонента, он преобразует его в строку, а не в объект.
<custom-player my-source = "{autoplay: true, controls: false, sources: [{ src: './video.mp4', type: 'video/mp4' }]}"></custom-player>
вот мой пользовательский компонент, в котором атрибут my-source должен быть отправлен как объект, но он входит в виде строки, из-за которой проигрыватель videojs не читает его должным образом.
Решено. Мне просто нужно было преобразовать строку. Сначала я преобразовал строку с помощью JSON.Stringfy. Затем я дважды преобразовал его обратно в JSON.parse и, следовательно, получил желаемый результат. Хотя это был не очень традиционный метод, и я уверен, что у людей могут быть лучшие решения. Но на данный момент это работало для меня. Спасибо :)
Он отправляет строку, потому что вы не используете [] в своем пользовательском компоненте. Это должно быть <custom-player [my-source]=... (свойство было options в вашем первоначальном посте). Это именно то, что я написал. Вам не нужно никакого дополнительного преобразования/анализа.
Я попытался добавить [] к пользовательскому компоненту, например [my-source], но он даже не читает его. И из того, что я читал в статьях, пользовательский компонент фактически принимает ввод без []. По крайней мере, так обстоит дело с угловым. После того, как мы создали пользовательский компонент, например, если мы принимаем ввод, например @Input() mySource:object, тогда мы должны использовать этот ввод, например my-source, при вводе ввода через пользовательский элемент в angular. Хотя я уверен, что вы правы, говоря о простом элементе angular, который мы используем [], но не используем его с пользовательским веб-компонентом.
Property binding
не имеет ничего общего с пользовательским компонентом или нет. Это стандартный угловой механизм, который работает до тех пор, пока элемент имеет соответствующее свойство (либо стандартное, либо определенное в пользовательском компоненте). Пожалуйста, прочитайте документы angular.io/guide/property-binding Если вы не смогли заставить его работать с вашей настройкой, значит, что-то еще не так. Я добавил небольшой пример привязки свойства к моему ответу.
Похоже, вы уже разобрались с этим из своих комментариев, но просто для того, чтобы прояснить для всех, кто оказывается здесь с той же проблемой, вот почему это происходит.
Когда вы конвертируете компонент в веб-компонент Angular, любые входные данные будут сопоставлены, как описано здесь:
Https://angular.io/guide/elements#mapping
Пользовательский элемент содержит компонент Angular, обеспечивая мост между данными и логикой, определенными в компоненте, и стандартными API-интерфейсами DOM. Свойства и логика компонентов отображаются непосредственно в атрибуты HTML и систему событий браузера.
API создания анализирует компонент в поисках входных свойств и определяет соответствующие атрибуты для пользовательского элемента. Он преобразует имена свойств, чтобы сделать их совместимыми с пользовательскими элементами, которые не различают регистр. В именах результирующих атрибутов используются строчные буквы, разделенные тире. Например, для компонента с @Input('myInputProp') inputProp соответствующий пользовательский элемент определяет атрибут my-input-prop.
Пользовательский элемент просто содержит Angular, а не сам компонент Angular. Чтобы передать данные на вход, вы должны использовать атрибут, который Angular создает для этого элемента, аналогично тому, как вы используете атрибут данных. Значение атрибута представляет собой строку, поэтому вам необходимо преобразовать его в JSON и обратно, если вы хотите передать объект.
На самом деле это <custom-player> пользовательский веб-компонент. Является ли мой метод создания компонента правильным? И я читал в некоторых местах, что в пользовательском компоненте вам не нужно использовать [].