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

问题描述 投票:1回答:2

简而言之,我有一个Angular 4应用程序,它有一个包含android启发浮动动作按钮的标题,当点击此按钮时,应该在当前活动组件上执行一个方法(基本上是页面内容)。我正在使用角度4路由器,如果这有任何区别,它引起了一些关于View Child方法的担忧,因为我不会总是确定哪个组件当前是活动的,如果可能的话我想避免将#binding属性添加到每个单个模板。

我已经尝试过ViewChild修饰器,ContentChild装饰器,事件,服务,到目前为止,绝对没有任何工作,我很平坦。在这一点上,我不确定这是真的复杂还是只是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按钮时执行自己的操作,有些会打开模态,有些会显示/隐藏内容,有些会重定向,所以很高兴成为能够在组件本身上指定此行为。

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

编辑 - 按要求为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 {}
angular angular4-router
2个回答
1
投票

创建一个具有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的单独实例(或者你最终调用它的任何东西)。我认为有一种解决方法,但我无法想到这一点。


1
投票

要访问与当前路由关联的组件实例,您可以利用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了解更多信息。希望这可以帮助。

© www.soinside.com 2019 - 2024. All rights reserved.