1

RE DUPLICATE: "This question has been asked before and already has an answer. "

So this question was asked 10 days after I asked it? Somebody doesn't know how to read time stamps.


I'm struggling with Angular 2 making it hard or perhaps impossible to do things that were trivial in Angular 1, especially without tons of superfluous code and/or DOM nodes. :(

In Angular 1 I had a query control that did sophisticated handling of keystrokes in an input box and dynamically displayed results in a dropdown list. The items being searched could be of any type, and the dropdown list items could be simple strings or complex inline templates.

For example, I might use it query a list of User objects and display them using a default template (e.g. toString):

  <search-box [query-provider]='userFinder'> </search-box>

Somewhere else I have a similar search, but I want the resulting list to contain a richer view of each user, so I provide a template inline, as a child of the search-box:

  <search-box [query-provider]='userFinder'>
       <!-- this is used as a template for each result item in the
            dropdown list, with `result` bound to the result item. -->
       <div>
            <span class='userName'>result.name</span>
            <span class='userAge'>result.age</span>
            <address [model]='result.address'><address>
       </div>
  </search-box>

My implementation of search-box needs to determine if there is any child content to use as a template and use it in the correct location in the search-box template.

@Component({
    select: 'search-box',
    template: `
        <div somestuff here>
            <input morestuff here>
            <ul this is where my dropdown items will go>
                <li *ng-for="#item of model.listItems"
                    TEMPLATE FOR ITEMS SHOULD GO HERE
                </li>
            </ul>
        </div>`
    ...

With Angular 1 I could easily transclude a child template to that location and bind it to the appropriate scope, or I could dynamically compiled a template. I can't get this to work in Angular 2 at all.

If I use <ng-content> there, it only appears in the first <li>.

Mud
  • 28,277
  • 11
  • 59
  • 92

3 Answers3

1

You can do this easily with ngForTemplate, here is my detailed answer for a similar question Custom template(transclusion without ng-content) for list component in Angular2

https://stackoverflow.com/a/36535521/306753

Community
  • 1
  • 1
Cagatay Civici
  • 6,406
  • 1
  • 29
  • 34
0

In Angular2 there are

See also Angular 2 dynamic tabs with user-click chosen components

which can be used like:

  constructor(private dcl: DynamicComponentLoader, private injector: Injector, private ref:ElementRef) {}

  ngAfterViewInit() {
    this.dcl.loadIntoLocation(ChildComponent, this.ref, 'child').then((cmp) => {
      cmp.instance.someProperty = 'xxx';
    });
  }
Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
0

I made some tests and this doesn't seem to be supported. The following doesn't work:

@Component({
  selector: 'sub',
  template: `
    Sub component : 

    <h3>#1</h3>

    <template ngFor #elt [ngForOf]="list">
      <div>{{elt}}</div>
      <ng-content></ng-content>
    </template>

    <h3>#2</h3>

    <ng-content ngFor #elt [ngForOf]="list"></ng-content>
  `
})

Even with the template syntax for loops.

This works however when providing the content. This could perhaps be a workaround for you.

@Component({
  selector: 'my-app',
  template: `
    <sub>
      <div>from parent</div>
      <template ngFor #elt [ngForOf]="list">
        <div>{{elt}} - parent</div>
      </template>
    </sub>
  `,
  directives: [ SubComponent ]
})

See the plunkr I used for my tests: https://plnkr.co/edit/a06vVP?p=preview.

I also saw an issue regarding this (and slot):

Thierry Templier
  • 198,364
  • 44
  • 396
  • 360