【Angular2】 アプリケーション開発の幅を広げる! コンポーネント関数外部呼び出しのテクニック
Angular2 - アプリケーション外部からのコンポーネント関数呼び出し
以下の手順で、アプリケーション外部からのコンポーネント関数呼び出しを実現できます。
コンポーネントをエクスポートする
まず、呼び出したいコンポーネントを @Component
デコレータの exports
オプションを使用してエクスポートする必要があります。
@Component({
selector: 'my-component',
templateUrl: './my-component.html',
styleUrls: ['./my-component.css'],
exports: ['myFunction']
})
export class MyComponent {
myFunction() {
// 呼び出せる関数
}
}
次に、コンポーネントインスタンスを取得する必要があります。これは、@Component
デコレータの providers
オプションを使用して、コンポーネントをプロバイダーとして登録することで行えます。
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [MyComponent]
})
export class AppComponent {
constructor(private myComponent: MyComponent) {}
}
コンポーネント関数呼び出す
最後に、取得したコンポーネントインスタンスを使用して、コンポーネント関数を呼び出します。
this.myComponent.myFunction();
アプリケーション外部からの呼び出し
上記の例では、コンポーネント MyComponent
とその関数 myFunction
をエクスポートしています。これは、他のモジュールやテストから MyComponent
と myFunction
にアクセスできるようにします。
例えば、別のモジュールから MyComponent
をインポートして myFunction
を呼び出すことができます。
import { MyComponent } from './my-component';
@Component({
selector: 'another-component',
templateUrl: './another-component.html',
styleUrls: ['./another-component.css']
})
export class AnotherComponent {
constructor(private myComponent: MyComponent) {}
callMyFunction() {
this.myComponent.myFunction();
}
}
テストからの呼び出し
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MyComponent } from './my-component';
describe('MyComponent', () => {
let fixture: ComponentFixture<MyComponent>;
let component: MyComponent;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [MyComponent]
});
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
});
it('should call myFunction', () => {
spyOn(component, 'myFunction');
// コンポーネントをトリガーする
// ...
expect(component.myFunction).toHaveBeenCalled();
});
});
この例では、spyOn
関数を使用して myFunction
関数をスパイしています。これにより、関数が実際に呼び出されたかどうかを確認できます。
注意点
- コンポーネントをエクスポートする場合は、セキュリティ上のリスクに注意する必要があります。
- コンポーネント関数に依存する外部コードを変更する前に、コンポーネントの API が変更されていないことを確認する必要があります。
my-component.ts
@Component({
selector: 'my-component',
templateUrl: './my-component.html',
styleUrls: ['./my-component.css'],
exports: ['myFunction']
})
export class MyComponent {
myFunction() {
console.log('myFunction called!');
}
}
<p>My Component</p>
/* styles for my-component */
import { Component, OnInit } from '@angular/core';
import { MyComponent } from './my-component';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
constructor(private myComponent: MyComponent) {}
ngOnInit() {
// コンポーネントをトリガーする
this.myComponent.myFunction();
}
}
<my-component></my-component>
import { Component } from '@angular/core';
import { MyComponent } from './my-component';
@Component({
selector: 'another-component',
templateUrl: './another-component.html',
styleUrls: ['./another-component.css']
})
export class AnotherComponent {
constructor(private myComponent: MyComponent) {}
callMyFunction() {
this.myComponent.myFunction();
}
}
<button (click)="callMyFunction()">Call My Function</button>
my-app.spec.ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { MyComponent } from './my-component';
describe('AppComponent', () => {
let fixture: ComponentFixture<AppComponent>;
let component: AppComponent;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [AppComponent, MyComponent]
});
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
});
it('should call myFunction', () => {
spyOn(component.myComponent, 'myFunction');
fixture.detectChanges();
expect(component.myComponent.myFunction).toHaveBeenCalled();
});
});
実行方法
- 上記のコードを
my-component.ts
、my-component.html
、my-component.css
、app.component.ts
、app.component.html
、another-component.ts
、another-component.html
、my-app.spec.ts
というファイルに保存します。 - 以下のコマンドを実行して、Angular CLI を使用してプロジェクトを作成します。
ng new my-app
- 作成したプロジェクトディレクトリに移動します。
cp my-component.ts my-component.html my-component.css app.component.ts app.component.html another-component.ts another-component.html my-app.spec.ts my-app/src
- 以下のコマンドを実行して、アプリケーションをビルドして実行します。
ng serve
ブラウザで http://localhost:4200 にアクセスすると、My Component
というコンポーネントが表示されます。
説明
my-component.ts
ファイルには、MyComponent
コンポーネントとmyFunction
関数が定義されています。
Angular2 でコンポーネント関数呼び出しを行うその他の方法
イベントバインディングを使用して、コンポーネント間でデータをやり取りすることができます。これにより、コンポーネント間で関数を呼び出すこともできます。
@Component({
selector: 'my-parent',
templateUrl: './my-parent.html',
styleUrls: ['./my-parent.css']
})
export class MyParentComponent {
callMyFunction() {
console.log('myFunction called!');
}
}
@Component({
selector: 'my-child',
templateUrl: './my-child.html',
styleUrls: ['./my-child.css']
})
export class MyChildComponent {
constructor(private parent: MyParentComponent) {}
onClick() {
this.parent.callMyFunction();
}
}
<my-child (click)="onClick()"></my-child>
my-child.html
<button (click)="onClick()">Call My Function</button>
@Injectable()
export class MyService {
callMyFunction() {
console.log('myFunction called!');
}
}
@Component({
selector: 'my-parent',
templateUrl: './my-parent.html',
styleUrls: ['./my-parent.css']
})
export class MyParentComponent {
constructor(private service: MyService) {}
callMyFunction() {
this.service.callMyFunction();
}
}
@Component({
selector: 'my-child',
templateUrl: './my-child.html',
styleUrls: ['./my-child.css']
})
export class MyChildComponent {
constructor(private service: MyService) {}
onClick() {
this.service.callMyFunction();
}
}
<button (click)="callMyFunction()">Call My Function</button>
<button (click)="onClick()"></my-child>
import { Observable } from 'rxjs/Observable';
@Component({
selector: 'my-parent',
templateUrl: './my-parent.html',
styleUrls: ['./my-parent.css']
})
export class MyParentComponent {
private myFunctionSubject = new Observable<void>();
callMyFunction() {
this.myFunctionSubject.next();
}
}
@Component({
selector: 'my-child',
templateUrl: './my-child.html',
styleUrls: ['./my-child.css']
})
export class MyChildComponent {
constructor(private parent: MyParentComponent) {}
ngOnInit() {
this.parent.myFunctionSubject.subscribe(() => {
console.log('myFunction called!');
});
}
}
<button (click)="callMyFunction()">Call My Function</button>
- イベントバインディング は、単純なコンポーネント間通信に適しています。
- サービス は、より複雑なコンポーネント間通信に適しています。
angular