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

时间:2017-12-26 02:05:56

标签: angular angular4-router

简而言之,我有一个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按钮时,每个组件都会执行自己的操作,有些会打开模态,有些会显示/隐藏内容,有些会重定向所以它和&# #39;能够在组件本身上指定此行为真的很棒。

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

修改 - 按要求提供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 个答案:

答案 0 :(得分: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了解详情。希望这会有所帮助。

答案 1 :(得分: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的独立实例(或者你最终调用它的任何东西)。我认为有一种解决方法,但我无法想到这一点。