2015-12-15 16 views
26

In angolare 2, SVG-rect è un componente che crea rect come qui di seguito,Rimuovere l'host HTML selettori elemento create dalla componente angolare

<svg height="550" width="450" x="0" y="0"> 
    <g id="svgGroup"> 
     <svg-rect> 
     <!--template bindings={}--> 
      <rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect> 
     <!--template bindings={}--> 
     </svg-rect> 
     <svg-rect> 
     <!--template bindings={}--> 
      <rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect> 
     <!--template bindings={}--> 
     </svg-rect> 
    </g> 
</svg> 

ma questo non renda rect perché dei tag elemento speciali creati. Se svg-rect tag vengono rimossi rende l'rect

<svg height="550" width="450" x="0" y="0"> 
    <g id="svgGroup"> 
     <!--template bindings={}--> 
     <rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect> 
     <!--template bindings={}--> 
     <!--template bindings={}--> 
     <rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect> 
     <!--template bindings={}--> 
    </g> 
</svg> 

In 1.x angolare, c'è sostituire: 'true' che rimuove i tag direttiva con l'uscita compilato. Possiamo implementare lo stesso in angular2?

risposta

19

Invece di cercare di sbarazzarsi dell'elemento ospite, trasformarlo in uno che è SVG valido, ma l'altro saggio unaffecting: Invece della vostra selettore elemento

selector: "svg-rect" 

e il suo elemento corrispondente nel modello :

template: `...<svg-rect>...</svg-rect>...` 

passaggio a un selettore di attributo :

selector: "[svg-rect]" 

e aggiungere tale attributo a un tag elemento gruppo:

template: `...<g svg-rect>...</g>...` 

Ciò si espanderà per:

<svg height="550" width="450" x="0" y="0"> 
    <g id="svgGroup"> 
     <g svg-rect> 
     <!--template bindings={}--> 
      <rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect> 
     <!--template bindings={}--> 
     </g> 
     <g svg-rect> 
     <!--template bindings={}--> 
      <rect x="10" y="10" height="100" width="100" fill="red" stroke="#000" stroke-width="2"></rect> 
     <!--template bindings={}--> 
     </g> 
    </g> 
</svg> 

che è SVG valido, che renderà. Plnkr

+0

Funziona bene ovunque sia necessario un elemento valido, l'ho appena usato per un piccolo componente per le intestazioni di tabella dove si verifica lo stesso problema. Una query, c'è qualche documentazione a cui è possibile collegarsi per questo? – David

+2

@David - Non lo troverai nei manuali (ancora), ma per assicurarti che è benedetto: ecco il thread in cui gli utenti fanno il caso che a volte (svg e tabelle) devi usare selettori di attributo per modificare la struttura : https://github.com/angular/angular/issues/11280. In risposta, la funzionalità è stata aggiunta (beh, ripristinata, in realtà) qui: https://github.com/angular/angular/pull/11808. –

+1

ma cosa succede se voglio aggiungere più elementi all'interno di un elemento (manualmente, non con * ngFor) – Marcel

4

Per citare il Angular 1 to Angular 2 Upgrade Strategy doc:

direttive che sostituiscono il loro elemento ospite (sostituire: true direttive angolare 1) non sono supportati in angolare 2. In molti casi queste direttive possono essere aggiornate oltre alle direttive normali componenti .

Ci sono casi in cui le direttive di componenti regolari non funzionano, in questi casi possono essere utilizzati approcci alternativi. Per esempio per svg vedere: https://github.com/mhevery/ng2-svg

21

Un altro approccio per rimuovere l'host del componente che utilizzo.

direttiva remove-host

//remove the host of avatar to be rendered as svg 
@Directive({ 
    selector: '[remove-host]' 
}) 
class RemoveHost { 
    constructor(private el: ElementRef) { 
    } 

    //wait for the component to render completely 
    ngOnInit() { 
     var nativeElement: HTMLElement = this.el.nativeElement, 
      parentElement: HTMLElement = nativeElement.parentElement; 
     // move all children out of the element 
     while (nativeElement.firstChild) { 
      parentElement.insertBefore(nativeElement.firstChild, nativeElement); 
     } 
     // remove the empty element(the host) 
     parentElement.removeChild(nativeElement); 
    } 
} 

Utilizzando questa direttiva;
<avatar [name]="hero.name" remove-host></avatar>

In remove-host direttiva, tutti i figli della nativeElement sono inseriti prima che l'host e poi l'elemento host viene rimosso.

Sample Example Gist
In base al caso d'uso, potrebbe esserci qualche problema di prestazioni.

+0

I problemi di prestazioni potrebbero essere ciò che pensavo all'inizio. Ma attualmente sto usando in questo modo i miei componenti di light design per sostituire l'host host, altrimenti ho problemi con la visualizzazione di html – Kuncevic

+0

@Kuncevich Buono a sapersi che la mia risposta ha aiutato, i colli di bottiglia delle prestazioni si sarebbero creati quando l'elemento 'ChangeDetection' è stato attivato come' shadow DOM! == DOM attuale. Ma se non ci sono molti elementi, questo non sarebbe così grande. Speriamo che;) – Bhavik

+0

Abbiamo bisogno di qualche analogia di Angular1 'replace: true' http://stackoverflow.com/questions/22497706/angular-directive-replace-true qualcuno ha detto che questa funzione è in realtà è in angular2 ma supportata non ufficialmente. – Kuncevic

6

C'è un altro approccio che possiamo ottenere il modello di un componente dal componente.
In primo luogo, creiamo la componente, la cui etichetta speriamo di rimuovere dal browser rendere

@Component({ 
    selector: 'tl-no-tag', 
    template: ` 
    <template #tmp> 
     <p>{{value}}</p> 
    </template>`, 
    styleUrls: [] 
}) 
export class TlNoTagComponent { 
    @ViewChild('tmp') tmp: any; 
    value = 5; 
} 

Poi, nel modello di un altro componente, scriviamo (non stiamo cercando di rimuovere il tag.):

<tl-no-tag #source></tl-no-tag> <!-- This line can be placed anywhere --> 
<template [ngTemplateOutlet]="source.tmp"></template> <!-- This line will be placed where needed --> 

Poi, abbiamo in del browser qualcosa di simile:

<tl-no-tag></tl-no-tag> 
<p>5</p> 

Così, abbiamo portato <p>{{value}}</p> fuori dalla TlNoTagComponent . <tl-no-tag></tl-no-tag> continuerà ad esserci, ma non bloccherà nessun css o svg-thing.

+0

"Il modello ha il proprio ambito di validità separato, quali variabili può vedere il modello?" Dai un'occhiata a questo (nella parte Contenuto modello): https://blog.angular-university.io/angular-ng-template-ng-container-ngtemplateoutlet/ – Timathon

Problemi correlati