Хорошо, у меня есть 2 обходных пути, чтобы справиться с этим! Они больше похожи на хаки, поскольку (1) они не выполняются стандартным способом Angular
, и (2) могут сломаться в будущем из-за изменений реализации в пределах Angular
. Ниже приведены 2 способа достижения output property
для WebComponent
, построенного с помощью Angular Elements
(я использую "@angular/core": "~9.1.11"
и "@angular/elements": "^9.1.11"
)
- Мой коллега указал, что
createCustomElement
предоставляет только входные данные как свойства. Смотрите код здесь . Итак, hack - это пометить свойство как Input()
, а затем просто прочитать его извне, как обычное свойство! Это очень неинтуитивно и не следует какой-либо стандартной семантике. И интересно, что Angular
не жалуется, если у меня есть только getter
для свойства, украшенного @Input()
- Лучший подход, как было указано
Danny '365CSI' Engelman
в комментариях, мы можем определить новое свойство в собственном элементе HTML, используя Object.defineProperty
Обратите внимание, что вместо варианта (1) лучшим подходом может быть улучшение / расширение logi c в Angular
для включения других свойств из класса компонента в качестве свойств элемента, возможно, с новым настраиваемым декоратором, например @outputProperty
.
Пример кода с реализацией обоих вышеуказанных подходов
// The component
import { Component, OnInit, ViewEncapsulation, Input, ElementRef } from '@angular/core';
@Component({
// selector, templateUrl & styleUrls
encapsulation: ViewEncapsulation.ShadowDom,
})
export class MyComponent implements OnInit {
constructor(
private element: ElementRef,
) {
// THIS IS APPROACH 2 => we are defining a 'result2' property on the HTMLElement
Object.defineProperty(this.element.nativeElement, 'result2', {
get: () => { return { name: this.name, count: this.count }; },
enumerable: true,
});
}
public name = 'World';
public count = 0;
// More code for component functionalities and state management...
// Just note that this does NOT work i.e. cannot read it from outside
public get result0(): ElementMetadata {
return { name: this.name, count: this.count };
}
public set result0(value) { console.log(`result value set to ${value}`); }
// THIS IS APPROACH 1 => we are marking 'result1' with a getter, as @Input
@Input()
public get result1(): ElementMetadata {
return { name: this.name, count: this.count };
}
}
// The module (no changes made specifically for this)
export class AppModule {
constructor(private injector: Injector) { }
ngDoBootstrap() {
const custElement = createCustomElement(
MyComponent,
{ injector: this.injector },
);
customElements.define('my-component', custElement);
}
}