【问题标题】:How to communicate parent component interaction through child route component? (Angular2)如何通过子路由组件进行父组件交互? (角2)
【发布时间】:2017-06-13 02:41:16
【问题描述】:

在路由配置的根组件中,我有一个按钮。当我点击这个按钮时,我想在激活的子路由中触发一个事件。

我已经为此苦苦挣扎了一段时间,唯一看起来很有希望的是使用bi-directional service (link to angular docs)。但是,我不确定如何让它工作。

这里有一个 plunk 来演示:

https://plnkr.co/edit/7zDTTTlABWD2GFo01jaz?p=preview

我已经设置了一个简单的路由配置,它会自动重定向到 TestComponent。当我在路由应用级别单击“单击”按钮时,我希望能够触发 TestComponent 中的clickDetected() 函数。

希望一切都清楚 - 任何建议都值得赞赏!

代码如下;


app.component

@Component({
  selector: 'my-app',
  template: `
    <input type="button" (click)="onClick('hello')" value="click" />
    <router-outlet></router-outlet>
  `,
})
export class AppComponent {
  constructor(private testService: TestService) {
  }

  onClick(v){
    this.testService.declareClick(v)
  }
}

测试服务

@Injectable()
export class TestService {

  private clickedSource = new Subject<string>();

  clicked$ = this.clickedSource.asObservable();

  declareClick(value: string) {
    console.log(value)
    return this.clickedSource.next(value);
  }

}

test.component

@Component({
  selector: 'my-test',
  template: `
    <div>
      <h1>Test Component</h1>
    </div>
  `,
})
export class TestComponent implements OnInit {

  public clicked?: any

  constructor(private testService: TestService) {
  }

  clickDetected(){
   console.log("parent clicked")
  }

  ngOnInit(){
    this.testService.declareClick()
/*      .subscribe((v) => {
        this.clicked? = v;
        console.log(v)
      })*/
  }

}

【问题讨论】:

标签: angular angular2-routing


【解决方案1】:

您只需要将.subscribe() 发送到正在接收.next() 事件的Observable

this.testService.clickedSource.subscribe((val)=>{
  console.log(2, val);
});

固定 Plunker:https://plnkr.co/edit/aPR6KvuOi2tgQXLgokHi?p=preview

【讨论】:

  • 啊,非常令人沮丧,我错过了一个小编辑,非常感谢您指出我哪里出错了! (当计时器允许时将接受)
  • 嗯.. 我在回答中也看到了这个错误。我不知道为什么我认为您无法访问父模块中提供的服务。我的回答仍然有效,并且在其他各种情况下仍然有用,所以..我会把它留在那里。 :)
  • @echonax 我正在尝试使用另一个级别的路由来实现此解决方案,但我无法订阅 observable?我试图让 plunk 启动并运行,但由于某种原因,将子路由系统放入其中很复杂。
  • @lolio 只要该服务在主 app.module 的提供者列表中,您就应该能够订阅它。你能补充更多细节吗?
  • @echonax 我有一个主路由模块,然后是子路由模块。在子路由模块中,我将按钮放在根组件中。我无法订阅此根目录下的子路由模块内列出的任何组件中的主题。我能想到的最简单的解释是,它与当前示例相同,只是所有内容都向下移动了一层,如果您可以设想的话。 (对不起,如果写得不好,也许我可以试着用一个例子来说明我在周末的意思)
【解决方案2】:

编辑——不要这样做——

感谢@echonax,我了解到这实际上是你应该做的一个例子。我来实际上是为了帮助人们,最终我学到了一些东西。请参阅 angular2 文档,了解为什么不应该这样做。

结束编辑

您可以使用共享模块来做到这一点。您创建一个提供测试服务的模块,并在 AppModule 和您的路由模块中导入。然后,您可以为这两个组件提供相同的服务实例。我从你的代码中为你做了一个 plunkr,展示了它是如何工作的。

如果您想了解有关 SharedModule 的更多信息,请查看 Angular2 文档。 https://angular.io/docs/ts/latest/guide/ngmodule.html#!#shared-module

编辑了您的问题 plunkr。 https://plnkr.co/edit/SU8AT4


共享模块

import { NgModule } from '@angular/core';
import { TestService } from './test.service';

@NgModule({
  imports: [],
  declarations: [],
  providers: [
    TestService
  ],
  exports: [ ]
})
export class SharedModule { }

新的 AppModule

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { TestComponent } from './test.component';
import { SharedModule } from './shared.module';
import { AppRoutingModule } from './app-routing.module';

@NgModule({
  imports: [
    BrowserModule,
    AppRoutingModule,
    SharedModule
  ],
  declarations: [
    AppComponent,
    TestComponent
  ],
  providers: [ ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

新的 AppRoutingModule

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { TestComponent }  from './test.component';
import { SharedModule } from './shared.module';

const appRoutes: Routes = [
  { path: '',   redirectTo: 'test', pathMatch: 'full' },
  { path: 'test',  component: TestComponent },
];

@NgModule({
  imports: [
    RouterModule.forRoot(appRoutes),
    SharedModule
  ],
  exports: [ RouterModule ],
  providers: []
})
export class AppRoutingModule { }

【讨论】:

  • 小心“不要在共享模块中指定应用程序范围的单例提供程序。导入该共享模块的延迟加载模块将制作自己的服务副本。 " @Angular2 SharedModule
  • 嗯.. 看来你是完全正确的。我做了一个大横幅,人们不应该这样做。我应该把它留在这里作为删除它的反例吗?
  • 这只是延迟加载模块中的问题。你的例子也很有效,所以只要提到警告,我就不会看到伤害:-) 这也很有教育意义。
  • 很好.. 它保持。我现在使用lazyLoaded featureModule,我认为这可能是我一直遇到的问题之一。在 AppModule 中提供它实际上会在延迟加载的模块中工作吗?
  • 对于供应商:是的。对于指令:stackoverflow.com/questions/41433766/…
猜你喜欢
  • 2016-07-19
  • 1970-01-01
  • 2016-10-28
  • 2019-04-16
  • 2020-06-21
  • 2016-12-19
  • 1970-01-01
  • 2017-11-20
  • 1970-01-01
相关资源
最近更新 更多