Angular 4 - 从app组件调用子组件方法

简而言之,我使用角度4路由器,如果这有任何区别,它引起了一些关于View Child方法的担忧,因为我赢了't always be sure what component is currently active and if possible i' d喜欢避免为每个模板添加 #binding 属性 .

我试过这个ViewChild装饰器,ContentChild装饰器,事件,服务,到目前为止绝对 nothing 已经工作了,我不确定这是真的很复杂还是只是PEBCAK .

有问题的按钮包含在 app.component 中 -

app.component.ts

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})

export class AppComponent {
  currentUrl: string = null;

  constructor(private router: Router, private currentRoute: ActivatedRoute) {}

  ngOnInit() {
    this.router.events.subscribe((val) => {
      this.currentUrl = this.router.url;
    });
  }
}

app.component.html (只是简洁按钮)

<div class="fab-container">
  <button class="btn btn-warning btn-fab" (click)="fabAction()">
    +
  </button>

这里的一般想法是,当单击此按钮时,它会在子组件上执行 fabAction() 方法;

@Component({
  selector: 'app-course-list',
  templateUrl: './course-list.component.html',
  styleUrls: ['./course-list.component.scss']
})
export class CourseListComponent implements OnInit {

  courses: Course[];
  showFilter: boolean = false;

  constructor(
    private courseService: CourseService
  ) { }

  ngOnInit(): void {
    this.getCourses();
  }

  getCourses(): void {
    this.courseService.getCourses().then(courses => this.courses = courses);
  }

  // Should execute this method when button is clicked on app component
  fabAction(): void {
    console.log('responding to click on parent component');
    this.showFilter = !this.showFilter;
  }
}

</div>

有一点值得一提的是,每个组件都会在应用程序组件上单击fab按钮时执行自己的操作,有些会打开模态,有些会显示/隐藏内容,有些会重定向,所以很高兴成为能够在组件本身上指定此行为 .

阅读关于此的官方角度文档给我留下了更多的问题而不是答案,所以我已经把它全部带回了一个清白的名单,希望有人可以提出一个更理想的解决方法 .

Edit - 根据要求提供 app.component.html 的完整标记

<header *ngIf="currentUrl != '/landing'">
  <div class="brand">
    <img src="/assets/circle-logo.png" />
  </div>
  <nav>
    <div class="page-title">
      <h2>{{ page?.title }}</h2>
      <h4>{{ page?.strapline }}</h4>
    </div>
    <ul class="header-nav">
      <li [routerLink]="['/courses']">Courses</li>
      <li>Dashboard</li>
      <li>Community</li>
      <li>Blog</li>
      <li>About</li>
    </ul>
    <div class="fab-container">
      <button class="btn btn-warning btn-fab" (click)="fabAction()">
        +
      </button>
    </div>
  </nav>
</header>
  <router-outlet></router-outlet>
<app-footer></app-footer>

这是我的应用程序路由模块,我在其中定义我的路线以及显示哪条路线的组件(在英雄角4演示中完成)

const routes: Routes = [
    { path: '', redirectTo: 'landing', pathMatch: 'full' },
    { path: 'landing', component: LandingComponent },
    { path: 'courses', component: CourseListComponent },
    { path: 'course/:id', component: CourseComponent }
];

@NgModule({
    imports: [ RouterModule.forRoot(routes) ],
    exports: [ RouterModule ]
})

export class AppRoutingModule {}

回答(2)

2 years ago

创建一个具有RxJS主题的服务,在按下FAB时调用 next . 然后在任何关心的组件中,您可以 subscribe 到主题 .

import { Subject } from 'rxjs/Subject'

@Injectable()
export class FabService {
  clickSubject = new Subject();
}

app.component

@Component(...)
export class AppComponent {

  constructor(private fabService: FabService) {}

  fabAction() {
    this.fabService.clickSubject.next();
  }
}

child.component

@Component(...)
export class ChildComponent implements OnInit, OnDestroy {

  private clickSub: Subscription;

  constructor(private fabService: FabService) {}

  ngOnInit() {
    this.clickSub = this.fabService.clickSubject.subscribe(() => {
      // FAB was clicked
    });
  }

  ngOnDestroy() {
    this.clickSub.unsubscribe();
  }
}

我可以想到的唯一情况是这可能不起作用的是你是否延迟加载功能模块,因为那些将获得FabService的单独实例(或者你最终调用它的任何东西) . 我认为有一种解决方法,但我无法想到这一点 .

2 years ago

要访问与当前路由关联的组件实例,您可以利用OnActivate挂钩接口在激活路由时将此实例设置为共享服务:

@Component({
  selector: 'some-cmp',
  template: `
    <div>routerOnActivate: {{log}}</div>
  `})
  export class AppComponent implements OnActivate {
    constructor(private service:RouteStateService) {
    }

    routerOnActivate(next: ComponentInstruction, prev: ComponentInstruction) {
      this.service.setCurrentRouteComponent(this);
    }
 }

然后,您将能够以这种方式访问组件实例并访问该函数:

var component = this.service.getCurrentRouteComponent();
component.somefunction()

没有测试过代码,请查看this了解更多信息 . 希望这可以帮助 .