web-dev-qa-db-ja.com

Angular ComponentでAngularJSディレクティブを使用する

Angularjsディレクティブをangularコンポーネントで使用するようにアップグレードしようとしています。ハイブリッド(ng1 + ng2)環境が機能するようになりました。 angularjsサービスをangularに挿入して、angularコンポーネントで使用することもできます(実際には、angularjs 1.4.xでも機能します)。

現在、angularで既存のangularjsディレクティブを使用しようとしていますが、機能していません。

参考までに、私のコードの一部を示します。

[index.html](my-appはAngular 4ルートコンポーネントです)

...
<body>
    <div class="banner">Angular Migration</div>
    <my-app>Loading...</my-app>
...
</body>
...

[main.ts](ブートストラップコード)

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { UpgradeModule } from '@angular/upgrade/static';
import { Router } from '@angular/router';
import { AppModule } from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
  let upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
  upgrade.bootstrap(document.documentElement, ['sampleApp']);
  platformRef.injector.get(Router).initialNavigation();
});

[app.module.ts](Angular 4モジュール)

import { NgModule, Component } from '@angular/core';
import { HashLocationStrategy, LocationStrategy, CommonModule } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';
import { UpgradeModule } from '@angular/upgrade/static';
import { RouterModule, Routes, UrlHandlingStrategy } from '@angular/router';

import { HybridUrlHandlingStrategy } from './hybridUrlHandlingStrategy';
import { AppComponent } from './app.component';

export const routes: Routes = [
...
];

@NgModule({
  imports: [
    CommonModule,
    BrowserModule,
    UpgradeModule,
    RouterModule.forRoot([], { useHash: true, initialNavigation: false })
  ],
  providers: [
    { provide: LocationStrategy, useClass: HashLocationStrategy },
    { provide: UrlHandlingStrategy, useClass: HybridUrlHandlingStrategy },
    { provide: 'appService', useFactory: (i: any) => i.get('appService'), deps: ['$injector'] },
    { provide: 'mdToHtml', useFactory: (i: any) => i.get('mdToHtml'), deps: ['$injector'] }
  ],
  declarations: [
    AppComponent
  ],
  bootstrap: [ AppComponent ]    
})
export class AppModule {
  ngDoBootstrap() { }
}

[app.component.ts](Angular 4コンポーネント)

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

@Component({
  selector: 'my-app',
  template: `
    <router-outlet></router-outlet>
    <div ng-view></div>
  `,
})
export class AppComponent { }

[app.js](AngularJs app)

'use strict';

angular.module('sampleApp', [
  'ngRoute',
  'app.components.services.appService'
])
  .config(function ($routeProvider) {
    $routeProvider
      .otherwise({
        template: ''
      });
  });

[myStars.js](AngularJsディレクティブ)

'use strict';

angular.module('app.components.directives.myStars', [])
.controller('MyStarsCtrl', function() {
  console.log("**** in MyStarsCtrl ")
})
.component('myStars', {
  restrict: 'E',
  bindings: {
    count: '=count'
  },
  template: '<div>***** M Y   S T A R S *****</div>'
});

[myStars.ts](myStarsディレクティブをAngular 4に移行する試み)

import { Directive, ElementRef, Injector, Input, Output, EventEmitter } from '@angular/core';
import { UpgradeComponent } from '@angular/upgrade/static';

@Directive({
  selector: 'my-stars'
})
export class MyStarsDirective extends UpgradeComponent {
  @Input() count: number;
  @Output() clicked: EventEmitter<number>;

  constructor(elementRef: ElementRef, injector: Injector) {
    super('myStars', elementRef, injector);
  }
}

[test.module.ts](Angular 4テストモジュール)

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule, Routes} from '@angular/router';
import { TestComponent } from './test.component';

// importing the new MyStarsDirective)
import { MyStarsDirective } from '../../../components/directives/myStars/myStars';

const thisRoute: Routes = [
    {
        path: 'test/:id',
        component: TestComponent
    }
];

@NgModule({
    declarations: [
        TestComponent,
        MyStarsDirective, // <<<< adding directive here
    ],
    providers: [],
    imports: [
        CommonModule,
        RouterModule.forChild(thisRoute)
    ],
    exports: [
        RouterModule
    ]
})

export class TestModule {}

[test.component.ts](Angular 4テストコンポーネント)

import { Component, Inject, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { HybridUrlHandlingStrategy } from '../../../hybridUrlHandlingStrategy';
import { MyStarsDirective } from '../../../components/directives/myStars/myStars';

@Component({
  templateUrl: './test.component.html'
})
export class TestComponent implements OnInit {
  routeParams: any
  myService: any
  mdToHtml: any

  constructor(
    @Inject('myService') myService: any,
    @Inject('mdToHtml') mdToHtml: (str: string) => string,
    private activatedRoute: ActivatedRoute
  ) {
    this.myService = myService;
    this.mdToHtml = mdToHtml;
  }
  ngOnInit() {
    this.routeParams = this.activatedRoute.params.subscribe(params => {
      console.log("params", params['groupId'])
...
  }
  ngOnDestroy() {
    this.routeParams.unsubscribe();
  }
}

[test.component.html](Angular 4 html)

...
<my-stars></my-stars>      <!-- <<<< using directive here -->
...

注:このハイブリッドアプリを機能させるために、angularjsのバージョンを1.5にアップグレードしました。

テストコンポーネントページをブラウザで表示したときのエラーは次のとおりです。

enter image description here

どんな助けでも大歓迎です。

ありがとう。

11
Will

興味のある方のために、ここにこのエラーの解決策があります。

[test.module.ts](Angular 4テストモジュール)

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule, Routes} from '@angular/router';
import { TestComponent } from './test.component';

// importing the new MyStarsDirective)
import { MyStarsDirective } from '../../../components/directives/myStars/myStars';

const thisRoute: Routes = [
    {
        path: 'test/:id',
        component: TestComponent
    }
];

@NgModule({
    declarations: [
        TestComponent,
        MyStarsDirective, // <<<< adding directive here
    ],
    providers: [
        {
            provide: '$scope',
            useFactory: i => i.get('$rootScope'),
            deps: ['$injector']
        }, // <<<< added this section to fix the No provider for $scope error
    ],
    imports: [
        CommonModule,
        RouterModule.forChild(thisRoute)
    ],
    exports: [
        RouterModule
    ]
})

export class TestModule {}

私はこのリンクで答えを見つけました https://github.com/angular/angular/issues/1499 (BrunoPoetaに触発されました)3月10日のgkalpakによるコメントを参照してください。

次に、通常のディレクティブをアップグレードして1.4.xを使用できるかどうかを確認します。

12
Will