2016-12-27 12 views
5

Chcę zaktualizować komponent ng1 do użycia wewnątrz komponentu ng2.NgUpgrade: Nie można użyć templateUrl podczas aktualizowania komponentów Angular1

Jeśli użyję tylko łańcucha szablonu, składnik ng1, aby zostać zaktualizowany, działa. Jednakże, jeśli przełączyć się za pomocą templateUrl Zamiast tego, awarii aplikacji i dać mi ten błąd:

angular.js:13920 Error: loading directive templates asynchronously is not supported 
at RemoteUrlComponent.UpgradeComponent.compileTemplate (upgrade-static.umd.js:720) 
at RemoteUrlComponent.UpgradeComponent (upgrade-static.umd.js:521) 
at new RemoteUrlComponent (remote-url.component.ts:11) 
at new Wrapper_RemoteUrlComponent (wrapper.ngfactory.js:7) 
at View_AppComponent1.createInternal (component.ngfactory.js:73) 
at View_AppComponent1.AppView.create (core.umd.js:12262) 
at TemplateRef_.createEmbeddedView (core.umd.js:9320) 
at ViewContainerRef_.createEmbeddedView (core.umd.js:9552) 
at eval (common.umd.js:1670) 
at DefaultIterableDiffer.forEachOperation (core.umd.js:4653) 

Tutaj jest upadać wykazania mój problem:

https://plnkr.co/edit/2fXvfc?p=info

I już po kątowej 1 -> 2 poradnik aktualizacji i wygląda na to, że ten kod powinien zadziałać. Nie jestem do końca pewien, dlaczego nie działa.

Odpowiedz

3

Znalazłem dość tanie rozwiązanie problemu.

Po prostu użyj template: require('./remote-url.component.html') zamiast templateUrl: './remote-url.component.html' i powinno działać dobrze!

+0

próbowałem swoje podejście, ale mam ten błąd zamiast: 'Uncaught ReferenceError: require jest niezdefiniowane na VM586 remoting- url.component.js: 8' – Houa

+0

Aby użyć 'require'użyj użyć odpowiedniego modułu ładującego, w tym przypadku myślę, że użyłem commonJS dla więcej szczegółów .. https://stackoverflow.com/questions/19059580/client-on-node-uncaught-referenceerror- require-is-not-defined – Florian

2

To jest naprawdę frustating, ponieważ dokumentacja uaktualnienia Angular mówi wyraźnie, że można używać templateUrl. Nigdy nie wspomina o tym problemie asynchronicznym. Znalazłem sposób obejścia go za pomocą $ templateCache. Nie chciałem zmienić mojej dyrektywy kątowej 1, ponieważ używa ona moich aplikacji kątowych 1, a także będzie używana przez 4 kanciaste aplikacje. Musiałem więc znaleźć sposób, aby zmodyfikować go w locie. Użyłem $ delegate, $ provider i $ templateCache. Mój kod znajduje się poniżej. Używam również tego, aby usunąć atrybut replace, ponieważ jest przestarzały.

function upgradeDirective(moduleName, invokedName) { 
    /** get the invoked directive */ 
    angular.module(moduleName).config(config); 

    config.$inject = ['$provide']; 
    decorator.$inject = ['$delegate', '$templateCache']; 

    function config($provide) { 
     $provide.decorator(invokedName + 'Directive', decorator); 
    } 

    function decorator($delegate, $templateCache) { 
     /** get the directive reference */ 
     var directive = $delegate[0]; 

     /** remove deprecated attributes */ 
     if (directive.hasOwnProperty('replace')){ 
      delete directive.replace; 
     } 

     /** check for templateUrl and get template from cache */ 
     if (directive.hasOwnProperty('templateUrl')){ 
      /** get the template key */ 
      var key = directive.templateUrl.substring(directive.templateUrl.indexOf('app/')); 

      /** remove templateUrl */ 
      delete directive.templateUrl; 

      /** add template and get from cache */ 
      directive.template = $templateCache.get(key); 
     } 

     /** return the delegate */ 
     return $delegate; 
    } 
} 

upgradeDirective('moduleName', 'moduleDirectiveName'); 
1

Pretty low-tech rozwiązaniem tego problemu jest, aby załadować szablony w swojej index.html i przypisać im identyfikatory, które odpowiadają templateUrls dyrektyw szukasz, tj:

<script type="text/ng-template" id="some/file/path.html"> 
    <div> 
    <p>Here's my template!</p> 
    </div> 
</script> 

Następnie Angular automatycznie umieszcza szablon w szablonie $ templateCache, na którym narzędzie kompiluje szablon rozpoczynający się od UpgradeComponent, więc bez zmiany templateUrl w dyrektywie rzeczy będą działały, ponieważ id będzie zgodny z szablonem.

Jeśli zaznaczysz kod źródłowy UpgradeComponent (patrz poniżej), zobaczysz skomentowany kod, który zajmuje się pobieraniem adresu URL, więc musi być w pracach, ale na razie może to być opłacalne rozwiązanie i nawet skryptowalny.

private compileTemplate(directive: angular.IDirective): angular.ILinkFn { 
    if (this.directive.template !== undefined) { 
     return this.compileHtml(getOrCall(this.directive.template)); 
    } else if (this.directive.templateUrl) { 
     const url = getOrCall(this.directive.templateUrl); 
     const html = this.$templateCache.get(url) as string; 
     if (html !== undefined) { 
     return this.compileHtml(html); 
     } else { 
     throw new Error('loading directive templates asynchronously is not supported'); 
     // return new Promise((resolve, reject) => { 
     // this.$httpBackend('GET', url, null, (status: number, response: string) => { 
     //  if (status == 200) { 
     //  resolve(this.compileHtml(this.$templateCache.put(url, response))); 
     //  } else { 
     //  reject(`GET component template from '${url}' returned '${status}: ${response}'`); 
     //  } 
     // }); 
     // }); 
     } 
    } else { 
     throw new Error(`Directive '${this.name}' is not a component, it is missing template.`); 
    } 
    } 
0

Utworzyłem narzędzie do metody, które rozwiązało ten problem. Zasadniczo dodaje treść szablon URL do kątowego za templateCache, wykorzystujące requireJS i „text.js”:

initTemplateUrls(templateUrlList) { 
    app.run(function ($templateCache) { 
     templateUrlList.forEach(templateUrl => { 
     if ($templateCache.get(templateUrl) === undefined) { 
      $templateCache.put(templateUrl, 'temporaryValue'); 
      require(['text!' + templateUrl], 
      function (templateContent) { 
       $templateCache.put(templateUrl, templateContent); 
      } 
     ); 
     } 
     }); 
    }); 

Co należy zrobić, to umieścić tego narzędzia metody w appmodule.ts na przykład, a następnie utworzyć listę z templateUrls że masz zamiar uaktualnić z kątowym dyrektywy, na przykład:

const templateUrlList = [ 
     '/app/@[email protected]/common/directives/grid/pGrid.html', 
    ]; 
Powiązane problemy