2016-06-24 17 views
7

Uso Angular 2-rc3 e ho un Component e voglio applicare la transizione, solo in un altro modo. Ecco la mia componente:Componente di eliminazione con modello in linea

import { Component, Input } from '@angular/core'; 

@Component({ 
    selector: 'my-list', 
    template: `<ul> 
     <li *ngFor="let item of data"> 
      -- insert template here -- 
      <ng-content></ng-content> 
     </li> 
    </ul>` 
}) 
export class MyListComponent { 
    @Input() data: any[]; 
} 

e lo uso come questo:

<my-list [data]="cars"> 
    <div>{{item.make | uppercase}}</div> 
</my-list> 

Come potete vedere, sto cercando di definire un modello di linea che verrà utilizzato dalla mia componente. Ora questo è terribilmente sbagliato. Prima di tutto, un'eccezione databinding lo dice can't read property 'make' of undefined. Sta cercando di leggere item.make dal mio componente circostante, non dallo MyListComponent. Ma anche se disattivare temporaneamente questo per ora:

<my-list [data]="cars"> 
    <div>{item.make | uppercase}</div> 
</my-list> 

Poi appare il secondo problema:

-- insert template here -- 
-- insert template here -- 
-- insert template here -- 
-- insert template here -- 
{item.make | uppercase} 

Quindi angolare in realtà non copiare il modello da utilizzare all'interno del *ngFor, semplicemente lega gli elementi e finiscono associati all'ultima voce.

Come posso farlo funzionare?

Ho avuto lo stesso problema con AngularJS, dove petebacondarwin posted a solution to manipulate the DOM through compile, che è stato grande. Ho questa opzione anche con Angular 2 iniettando ElementRef nel mio componente, ma! Una grande differenza è che compile in AngularJS è andato via prima del database, il che significa che non c'erano problemi nell'uso di {{item.make}} nel modello. Con Angular 2, questo sembra essere un no-go poiché {{item}} viene analizzato in precedenza. Quindi qual è il modo migliore per farlo? Usando la notazione leggermente diversa [[item]] e la stringa che sostituisce l'intera cosa non sembra il modo più elegante ...

Grazie in anticipo!

// Modifica: ecco uno Plnkr che riproduce il problema.

+0

Sarebbe bello avere un Plunker che permetta di riprodurre dove tutto è a posto come lo si vuole usare. Trovo difficile, ad esempio, capire che cosa significhi "inserire il modello qui" nel modo esatto. –

+0

Aggiunto! Grazie. –

+0

@JPtenBerge Ho riscontrato un problema simile e [ho trovato una soluzione] (http://stackoverflow.com/questions/38174837/how-to-create-a-component-with-a-dynamic-template-component-transclude- with-in) – Ross

risposta

1
  • <ng-content> all'interno *ngFor non funziona, quindi

    <li *ngFor="let item of data"> 
        -- insert template here -- 
        <ng-content></ng-content> 
    </li> 
    

non farà qualcosa di significativo. Tutto sarà incluso nel primo <ng-content>

https://github.com/angular/angular/issues/8563 potrebbe risolvere alcuni dei vostri requisiti.

+1

Il problema di GitHub descrive esattamente ciò di cui ho bisogno, ma è attualmente nello stato di "Needs Design" senza alcun traguardo, quindi non mi offre molto. Il primo collegamento sembra esattamente ciò di cui ho bisogno, ma funziona con una versione già obsoleta di Angular (beta 8): facendo riferimento a 'TemplateRef' e la chiamata a' setLocal() 'non funziona più. Questa soluzione sembra comunque promettente e ho visto un tuo commento sulla cosa 'setLocal()', giocherò un po 'di più con questo. –

4

Per precisare il metodo ngForTemplate: (. Al angolare 4 dell'elemento viene ora chiamato <ng-template>)

  1. Utilizzare un tag <template> in entrambi i componenti esterni e interni , invece di <ng-content>.

  2. Il <li> viene spostato nella html app.component, e il <template> sul componente ha una speciale 'lasciarlo al' attributo che fa riferimento alla variabile iterata nel componente interno:

    <my-list [data]="cars"> 
        <template let-item> 
        <li> 
         <div>{{item.make | uppercase}}</div> 
        </li> 
        </template> 
    </my-list> 
    
  3. il componente interno ha <template> pure e utilizza una variante di ngFor modo:

    <ul> 
        <template #items ngFor [ngForOf]="data" [ngForTemplate]="tmpl"> 
         -- insert template here -- 
        </template> 
    </ul> 
    
  4. la 'Tmpl' variabile assegnato all'attributo ngForTemplate dev'essere recuperata nel codice componente:

    export class MyListComponent { 
        @Input() data: any[]; 
        @ContentChild(TemplateRef) tmpl: TemplateRef; 
    } 
    
  5. @ContentChild e TemplateRef sono bit angolari, quindi bisogno di essere importati

    import { Component, Input, ContentChild, TemplateRef } from '@angular/core'; 
    

See la forcella del tuo plunkr con queste modifiche qui plnkr.

Questa non è la soluzione più soddisfacente per il problema dichiarato, dal momento che stai passando i dati nell'elenco che potresti avere anche il ngFor all'esterno. Inoltre, il contenuto aggiuntivo (letterale '- insert template here -') viene eliminato, quindi si desidera visualizzare che deve essere anche sul modello esterno.

Posso vedere che potrebbe essere utile dove l'iterazione è fornita all'interno del componente interno (ad esempio da una chiamata di servizio), e forse per fare qualche manipolazione del modello nel codice.

+0

grazie mille per questa risposta e il plunkr. Anche se questo sembra funzionare, nel mio caso, quando ho una lista dinamica, niente viene visualizzato nella lista. Anche se ispeziono il DOM, posso vedere che ci sono associazioni di template. Qualche idea su cosa sta succedendo? – sohel101091

+0

Non sono sicuro dello scenario: posso aggiungere auto all'elenco su runtine con un pulsante e fare clic sul gestore di eventi, e vengono visualizzati nell'elenco. –

+0

Abbiamo trascorso molte ore ad agosto per trovare una soluzione. Questa risposta è veramente utile. Funziona e basta.Molte grazie!!! – Vil

Problemi correlati