Передача внешнего атрибута или ввода в пользовательском элементе Angular

Я пытаюсь передать ввод объекта в тег пользовательского элемента 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 и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
Изучение Angular 1#
Изучение Angular 1#
Здравствуйте, друзья, как дела, надеюсь, у вас все хорошо.
1
0
2 154
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вам не нужно ../../ при запуске из ресурсов (обычно это допустимая отправная точка из конфигураций).

Кроме того, вы хотите изменить <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>

На самом деле это <custom-player> пользовательский веб-компонент. Является ли мой метод создания компонента правильным? И я читал в некоторых местах, что в пользовательском компоненте вам не нужно использовать [].

Shayan Ahmed 22.12.2020 08:23
[prop]='someVal' (связывание свойств) — это общий механизм angular для привязки значения к свойству в компоненте, указанном в шаблоне. Я бы порекомендовал вам переместить весь объект параметров из html в переменную в файле ts и передать его в ваш компонент, кстати. (html должен быть как можно более чистым). Кроме того, этот механизм не имеет ничего общего с тем, используете ли вы свой собственный или импортированный/родной компонент. Ссылка, которую я добавил, на самом деле делает то же самое, что и вы (с пользовательским компонентом проигрывателя, обертывающим тег видео), и использует [].
Gunnar B. 22.12.2020 11:18

Хорошо сейчас. Я нашел причину, по которой мой пользовательский видеоплеер на самом деле не получал источник видео, а также остальные элементы управления. Я использую Videojs в angular внутри пользовательского компонента. VideoJs принимает объект в качестве параметров `<app-my-video-player [options] = "{ autoplay: true, control: true, sources: [{ src: '../../assets/video.mp4', type : 'video/mp4' }]}"></app-my-video-player> ` Как показано выше. Но когда я передаю один и тот же объект через атрибуты настраиваемого компонента, он преобразует его в строку, а не в объект.

Shayan Ahmed 23.12.2020 11:56
<custom-player my-source = "{autoplay: true, controls: false, sources: [{ src: './video.mp4', type: 'video/mp4' }]}"></custom-player> вот мой пользовательский компонент, в котором атрибут my-source должен быть отправлен как объект, но он входит в виде строки, из-за которой проигрыватель videojs не читает его должным образом.
Shayan Ahmed 23.12.2020 12:01

Решено. Мне просто нужно было преобразовать строку. Сначала я преобразовал строку с помощью JSON.Stringfy. Затем я дважды преобразовал его обратно в JSON.parse и, следовательно, получил желаемый результат. Хотя это был не очень традиционный метод, и я уверен, что у людей могут быть лучшие решения. Но на данный момент это работало для меня. Спасибо :)

Shayan Ahmed 23.12.2020 12:56

Он отправляет строку, потому что вы не используете [] в своем пользовательском компоненте. Это должно быть <custom-player [my-source]=... (свойство было options в вашем первоначальном посте). Это именно то, что я написал. Вам не нужно никакого дополнительного преобразования/анализа.

Gunnar B. 23.12.2020 22:41

Я попытался добавить [] к пользовательскому компоненту, например [my-source], но он даже не читает его. И из того, что я читал в статьях, пользовательский компонент фактически принимает ввод без []. По крайней мере, так обстоит дело с угловым. После того, как мы создали пользовательский компонент, например, если мы принимаем ввод, например @Input() mySource:object, тогда мы должны использовать этот ввод, например my-source, при вводе ввода через пользовательский элемент в angular. Хотя я уверен, что вы правы, говоря о простом элементе angular, который мы используем [], но не используем его с пользовательским веб-компонентом.

Shayan Ahmed 24.12.2020 07:40
Property binding не имеет ничего общего с пользовательским компонентом или нет. Это стандартный угловой механизм, который работает до тех пор, пока элемент имеет соответствующее свойство (либо стандартное, либо определенное в пользовательском компоненте). Пожалуйста, прочитайте документы angular.io/guide/property-binding Если вы не смогли заставить его работать с вашей настройкой, значит, что-то еще не так. Я добавил небольшой пример привязки свойства к моему ответу.
Gunnar B. 24.12.2020 10:37

Похоже, вы уже разобрались с этим из своих комментариев, но просто для того, чтобы прояснить для всех, кто оказывается здесь с той же проблемой, вот почему это происходит.

Когда вы конвертируете компонент в веб-компонент Angular, любые входные данные будут сопоставлены, как описано здесь:

Https://angular.io/guide/elements#mapping

Пользовательский элемент содержит компонент Angular, обеспечивая мост между данными и логикой, определенными в компоненте, и стандартными API-интерфейсами DOM. Свойства и логика компонентов отображаются непосредственно в атрибуты HTML и систему событий браузера.
API создания анализирует компонент в поисках входных свойств и определяет соответствующие атрибуты для пользовательского элемента. Он преобразует имена свойств, чтобы сделать их совместимыми с пользовательскими элементами, которые не различают регистр. В именах результирующих атрибутов используются строчные буквы, разделенные тире. Например, для компонента с @Input('myInputProp') inputProp соответствующий пользовательский элемент определяет атрибут my-input-prop.

Пользовательский элемент просто содержит Angular, а не сам компонент Angular. Чтобы передать данные на вход, вы должны использовать атрибут, который Angular создает для этого элемента, аналогично тому, как вы используете атрибут данных. Значение атрибута представляет собой строку, поэтому вам необходимо преобразовать его в JSON и обратно, если вы хотите передать объект.

Другие вопросы по теме