I want to create a web element with angular, it includes inside some components, such as primeng split-button, and its going to be used with Vanilla JS.
Split-button has a property "appendTo", which takes target element to attach the overlay, valid values are "body" or a local ng-template variable of another element. Even if i set it as 'body', or HTMLBodyElement it keeeps appending to itself. Even if I call web-element in overlay window and pass a correct node to appendTo it keeps appearing right next after button. Example of settings, that are apllied to split-button, even string 'body' performes the same result, Wrong position? it has to be in the end of body tag
Is there some chances to fix it, maybe I have to build each primeng component inside my custom nested-component as a web-element and then only create a full covering?
The property of the question is to make dropdown instances appending to right element, not to itself.
Edit Code examples:
Web-component cover looks like:
@Component({
selector: 'my-web-element',
template: `
<my-nested-component
[exampleInput]="exmpleValue"
(exampleOutput)="exmpleMethod()">
</my-nested-component>
`,
styleUrls: ['./my-web-element.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class MyWebElementComponent {
@Input()
public exmpleValue: any;
@Output()
exampleMethodPerformed: EventEmitter<ExampleMethodPerformedArgs> =
new EventEmitter<ExampleMethodPerformedArgs>();
public exmpleMethod(event: ExampleMethodPerformedArgs){
this.exampleMethodPerformed.emit(event);
}
}
@NgModule({
declarations: [
MyWebElementComponent
],
imports: [
BrowserModule,
NestedComponentModule
],
entryComponents: [
MyWebElementComponent
]
})
export class AppModule {
constructor(private injector: Injector) {
const strategyFactory =
new ElementZoneStrategyFactory(MyWebElementComponent, injector);
const el =
createCustomElement(MyWebElementComponent, { injector: injector, strategyFactory });
customElements.define('my-web-element', el);
}
ngDoBootstrap() {
}
}
I build web-element calling ng build --configuration production --output-hashing none && node concatenate.js
Component itself looks like:
@Component({
selector: 'my-nested-component',
template: `
<my-cover-component>
<p-calendar
appendTo="body"
(onSelect)="onEmitExampleEvent($event)"
...other inputs and outputs>
</p-calendar>
<p-splitButton
[appendTo]="'body'"
(onClick)="onEmitExampleEvent($event)"
...other inputs and outputs>
</p-splitButton>
</my-cover-component>
`,
styleUrls: ['./my-web-element.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class NestedComponent {
@Input()
public exampleInput: any;
@Output()
exampleOutput: EventEmitter<ExampleMethodPerformedArgs> =
new EventEmitter<ExampleMethodPerformedArgs>();
public onEmitExampleEvent(event: ExampleMethodPerformedArgs){
this.exampleOutput.emit(event);
}
...other variables and methods
}
The usage of web-element:
<!doctype html>
<html lang="en" translate="no">
<head>
<meta charset="utf-8">
<title>MyWebElement Usage</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="google" content="notranslate">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<script type="text/javascript" src="./assets/my-web-element.js" defer></script>
</head>
<body class="body-frame">
<my-web-element id="myWebElement"></my-web-element>
<script>
const myWebElement = document.getElementById("myWebElement");
myWebElement.exmpleValue = 'Hello, world!'
myWebElement
.addEventListener('exampleMethodPerformed', (event) => {
console.log('ElementEvent is ', event)
});
document.body.append(myWebElement);
</script>
</body>
</html>