LoginSignup
13
7

More than 5 years have passed since last update.

[Angular] router-outletのコンポーネントの状態により親コンポーネントの状態を変えたい(しかも子供からいちいち指示したくない)ときのやり方

Last updated at Posted at 2018-06-27

親コンポーネントの状態を子コンポーネントの状態によって変更したいという時ってよくあると思います。

直接HTMLに子のセレクタを記載している場合なら、 @ViewChild とか @ViewChildren で取得してその中身を見れば良いですよね(その行為が良いかはともかく)。

でも、 router-outlet の場合ってどうしていますか?

実は、 activate Output() で簡単に取得できるので、便利です。

例えば、子コンポーネントの状態によってタイトルを変えたいとしましょう(タイトルを変える場合にこの方法を使うのは微妙だと思いますが、わかりやすいので)

parent.component.ts
@Component({
  selector: 'app-parent',
  template: `<div><h1>{{ title }}</h1><router-outlet></router-outlet></div>`,
})
export class ParentComponent {
  title: string;
  nameToTitle = {
    ONE: '1つ目',
    TWO: '2つ目',
  };
}
child1.component.ts
@Component({
  selector: 'app-child1',
  template: `<div>Child ONE!!</div>`
})
export ChildComponent {
  name = 'ONE';
}
child2.component.ts
@Component({
  selector: 'app-child2',
  template: `<div>Child TWO!!</div>`
})
export ChildComponent {
  name = 'TWO';
}

上記のコンポーネントが、routerにより、 child1 , child2 と変更されると想定します。
この場合、親コンポーネントを少し変更して下記のようにできます。

parent.component.ts
@Component({
  selector: 'app-parent',
  template: `<div><h1>{{ title }}</h1><router-outlet (activate)="onActivate($event)"></router-outlet></div>`, // <= activate を追加
})
export class ParentComponent {
  title: string;
  nameToTitle = {
    ONE: '1つ目',
    TWO: '2つ目',
  };

  onActivate(componentRef: any): void { // <= 追加
    this.title = this.nameToTitle[componentRef.name];
  }
}

これで簡単に router-outlet の状態を参照して親コンポーネントの値を変更できます。

他のやり方としては、子コンポーネントから親コンポーネントをサービス経由で変更する、などの方法があります(こっちが一般的)。
でも全部のComponentでやるのは面倒なのでこういうやり方でも良いときはあるかなと(継承すればDRYにもできますが、時と場合によります)

13
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
7