0

I have 3 components:

(1) AppComponent: This is just a regular AppComponent, nothing special. In app.component.html I use my MyComponent:

<my-component></my-component>

(2) MyComponent: This is just a wrapper component that contains TheirComponent like this (my.component.html):

<their-component></their-component>

(3) TheirComponent: This is a third-party component (from an NPM package). It can contain directives and other components from the third-party components. For example:

<their-component>
    <their-header>Title</their-header>
    <their-footer>Title</their-footer>
</their-component>

My goal is to put all of these additional, inner directives and components (their-header and their-footer in this example) in app.component.html, and pass it through MyComponent to TheirComponent. So my app.component.html should look like this:

<my-component>
    <their-header>Title</their-header>
    <their-footer>Title</their-footer>
</my-component>

I tried to use ng-content for this. It works with simple HTML elements, I know, but not with these third-party directives. This is what I tried (my.component.html):

<their-component>
    <ng-content></ng-content>
</their-component>

It doesn't work, and there are no errors. Maybe this is a content projection problem, I'm not sure, how this is called. Any solution for this? Thanks.


Example: https://plnkr.co/edit/SgM4sbYQrZXDcrKuon2d?p=preview

Roland Rácz
  • 2,879
  • 3
  • 18
  • 44
  • Why don't you just import the Component? Why do you need to pass it to the parent that way? – Aer0 Feb 22 '18 at 09:55
  • @Aer0 I have to wrap the third-party component, because I have to write some methods and parameters that are very commonly used in my application with this component. But the inner directives/components are unique for each use case, so I can't put them in my.component.html. – Roland Rácz Feb 22 '18 at 09:58
  • Did you try wrapping them in an ``? – Aer0 Feb 22 '18 at 09:59
  • Yes, a long time ago, but it had some issues, and it is not dynamic enough. They have too many components and directives. Or should I put all of the directives in a big `ng-template` (in *app.component.html*), that I can use in an `ng-template` (in *my.component.html*)? – Roland Rácz Feb 22 '18 at 10:15
  • @Aer0 I tried it, it doesn't work. – Roland Rácz Feb 22 '18 at 10:21
  • I've kind of trouble understanding your current promel. Could you eventually set up a small demo so we can follow up all of your thoughts? E.g. here https://codesandbox.io/s/angular – Aer0 Feb 22 '18 at 10:23
  • @Aer0 Codesandbox didn't worked, but check this one out: https://plnkr.co/edit/SgM4sbYQrZXDcrKuon2d?p=preview – Roland Rácz Feb 22 '18 at 11:56
  • 1
    It's just that `` doesn't support buttons to be passed by any other way than as children. Projection with `` requires children to be accessed differently and also stamping as template doesn't look the same for the consuming component. – Günter Zöchbauer Feb 26 '18 at 08:56
  • @GünterZöchbauer I see, thank you. Do you have any advice (direction) how to achieve (not this but) some kind of similar behavior? Or is it absolutely impossible to create a wrapper component? – Roland Rácz Feb 26 '18 at 09:05
  • 1
    It looks like it's not possible with the `` except something like https://stackoverflow.com/questions/38888008/how-can-i-use-create-dynamic-template-to-compile-dynamic-component-with-angular but I guess you'd rather avoid that. – Günter Zöchbauer Feb 26 '18 at 09:19

1 Answers1

2

If you really need it you can take advantage of using ngProjectAs attribute.

In order to have all addition functionality provided by ButtonGroup(k-group-start, k-group-end classes etc) you have to pass buttons array to kendo component.

Here's how it could look like:

import { Component, QueryList, ContentChildren, Input, ViewChild } from '@angular/core';
import { Button, ButtonGroup } from '@progress/kendo-angular-buttons';

@Component({
  selector: 'my-component',
  template: `
    <kendo-buttongroup>
        <ng-content ngProjectAs="[kendoButton]"></ng-content>
    </kendo-buttongroup>
  `
})
export class MyComponent {

  @ViewChild(ButtonGroup) buttonGroup: ButtonGroup;

  @ContentChildren(Button) buttons: QueryList<Button>;

  ngAfterViewInit() {
    this.buttonGroup.buttons = this.buttons;
    this.buttonGroup.ngAfterContentInit();
  }
}

Plunker Example

See also:

yurzui
  • 205,937
  • 32
  • 433
  • 399
  • Thank you. This is exactly what I was looking for! My original problem was with Kendo's Grid, but this works with that too. Although I get `ExpressionChangedAfterItHasBeenCheckedError`, but only in development mode. Interesting that there are no documentation for `ngProjectAs`. – Roland Rácz Feb 28 '18 at 11:16
  • The Plunker Example isn't working anymore – SubJunk Apr 19 '21 at 22:56