2015-11-12 14 views
12

Angularjs (ad es angolare 1) ha avuto questo comodo comportamento di ricerca di un tipo di < script = "text/ng-modello" > elemento che aveva l'id dell'url template specificato prima di richiederlo al server.modello come <script type = "text/ng-template"> equivalente con angolari 2

Es: il codice qui sotto non determina alcuna richiesta http ulteriore

<script type="text/ng-template" id="mytemplate.html"> 
    This is a body for my template 
</script> 
<script> 
    //... 
    app.directive('myComponent', function() { 
     return { 
      templateUrl: 'mytemplate.html' // does NOT trigger a http get 
     }; 
    }); 
</script> 

Ciò non sembra funzionare utilizzando angolare 2.

@View({ 
    templateUrl: 'mytemplate.html', // will be fetched from server ! 
}) 
class MyComponent{} 

C'è un altro modo di raggiungerlo? Mi sto perdendo qualcosa ?

PS: non si desidera embbed tutto il mio html nei miei file TS ...

+0

Puoi usare 'template' invece di' templateUrl'. –

+0

@EricMartinez è quello che intendevo per "non voglio incorporare il mio html": sto generando template da una vista aspnet (rasoio) ... non è incorporabile in un file js. E non è neanche comodo modificare html in una stringa js. – Olivier

+0

è molto più conveniente ora che è possibile utilizzare i backtick .. – foxx

risposta

7

Se qualcuno è interessato, ho trovato una soluzione semplice (una soluzione più pulita sarebbe meglio, però)

function template(url, viewdef) { 
    var elt = document.getElementById(url); 
    if (elt && elt.getAttribute('type') == 'text/ng-template') { 
     viewdef.template = elt.innerHTML; 
    } else 
     viewdef.templateUrl = url; 
    return viewdef; 
} 

@View(template('mytemplate.html', { 
    directives: [NgIf /*required directives*/] 
})) 
class MyComponent{} 

Ma si presume che lo script < sia già presente quando questo script è caricato.

[EDIT] Meglio soluzione

Ho appena si avvicinò con la semplice idea di ignorare solo la fabbrica @View decoratore.

1) Creare un file viewoverride.ts

import * as ng from 'angular2/core' 
let oldNgView = ng.View; 
function ViewOverride(viewDef) { 
    if (typeof viewDef.templateUrl == "string") { 
     let elt = document.getElementById(viewDef.templateUrl); 
     if (elt && elt.getAttribute('type') == 'text/ng-template') { 
      viewDef.template = elt.innerHTML; 
      delete viewDef.templateUrl; 
     } 
    } 
    return oldNgView(viewDef); 
} 
ng.View = <ng.ViewFactory>ViewOverride; 

NB: E 'molto importante per metterla in un file separato e indipendente, per costringerla ad essere eseguito prima di altre importazioni

2) E mettere questo come il prima riga del file di bootstrap:

import './viewoverride' 

3) Questo è tutto. La notazione @View è ora sovrascritto

@View({templateUrl:'mytemplate.template'}) class MyClass{} 

sarà ora cercare un elemento di script che id è mytemplate.template

+0

un'altra soluzione potrebbe utilizzare Gulp per creare un processo di raggruppamento. – Vincent

+0

@Vincent Come accennato nel mio commento sul post della domanda, questa non è un'opzione: sto generando i miei modelli in fase di runtime. – Olivier

+0

come fare se più ng-template in una pagina? .. è possibile? –

4

Penso che un modo più pulito per questo sarebbe se si fornisce la vostra abitudine ViewResolver, ispirato al angolare beta 17 s' codice sorgente, qualcosa nelle linee di:

import { Type, ViewMetadata, Reflector, Injectable, ComponentMetadata } from 'angular2/core'; 
import { ViewResolver } from 'angular2/compiler'; 

const SCRIPT_TYPE_NAME = 'text/ng2-template'; 

@Injectable() 
export class CustomViewResolver extends ViewResolver 
{ 
    constructor(private _r: Reflector){ super() } 
    resolve(component: Type): ViewMetadata 
    { 
    let annotations = this._r.annotations(component); 
    annotations.forEach(cm => 
    { 
     if(cm instanceof ComponentMetadata && cm.templateUrl && typeof cm.templateUrl == 'string') 
     { 
     let elemTpl = (<any>document).getElementById(cm.templateUrl); 
     if(elemTpl && elemTpl.getAttribute('type') == SCRIPT_TYPE_NAME) 
     { 
      cm.template = elemTpl.innerHTML; 
      elemTpl.remove(); 
      cm.templateUrl = undefined 
     } 
     else 
      throw new Error(`template "${cm.templateUrl}" not found among html scripts`) 
     } 
    }) 
    return super.resolve(component) 
    } 
} 

Plunker Link

Problemi correlati