Angular 5 - 组件和服务之间的通信

Angular 5 - communication between Components and Services

我用Angular 5. 目的是在登录正常时加载数据,并在其他组件中使用这些数据。 使用 Services Class 和 getActiveTasks 方法和 getStats 方法加载数据。 登录组件:

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent {

  constructor(private auth: AuthenticationService,
              private klinckServices: KlinckServices,
              private router: Router) { }

  loadData($event) {
    console.log('Authentification OK');
    let success;
    this.klinckServices.getActiveTasks(this.auth.getEcmUsername())
      .then((webScriptdata) => {
          console.log('KlinckSercices - loadData');
          success = webScriptdata;
          this.klinckServices.listTasks = success.data as ActiveTask[];
          this.router.navigate([this.klinckServices.getStats()]);
          console.log(this.klinckServices.listServices);
        },
        msg => {
          alert(msg);
          return '';
        });
   // this.router.navigate([this.klinckServices.loadData()]);
  }
}

服务Class:

@Injectable()
export class KlinckServices {

  listTasks: ActiveTask[];
  listServices: Stats [] = [];

  constructor(private apiService: AlfrescoApiService,
              private auth: AuthenticationService) {
    console.log('KlinckServices - constructor');
  }
  getStats(): string {
    this.listTasks.forEach((item, index) => {
      if (this.getServicesInListTasks(item.properties.wfvd_nomService) !== null) {
        if (! this.getServicesInListServices(item.properties.wfvd_nomService)) {
          const listLength = this.listTasks.filter(item2 => item2.properties.wfvd_nomService === item.properties.wfvd_nomService).length;
          console.log(listLength);
          const at: ActiveTask[] = [];
          for (let i = 0; i < listLength; i++) {
            at.push(this.listTasks.filter(item2 => item2.properties.wfvd_nomService === item.properties.wfvd_nomService)[i]);
          }
          this.listServices.push({
            data: at,
            count: listLength,
            service: item.properties.wfvd_nomService
          });
        }
      }
    });
    return '/dashboard';
  }
  getServicesInListServices( serviceSearch: string) {
    return(this.listServices.find( x => x.service === serviceSearch));
  }
  getServicesInListTasks( serviceSearch: string) {
    return(this.listTasks.find( x => x.properties.wfvd_nomService === serviceSearch));
  }

加载仪表板组件后,我需要检索这些数据:

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit, AfterViewInit 
{
  @ViewChild(DataTableDirective) datatableElement: DataTableDirective;
  @Input() public klinckServices: KlinckServices;

  listTasks: ActiveTask[];
  listPatients: Patient[];
  listMedecins: Medecin[];
  listDocType: Typologie[];
  listServices: Stats [] = [];
  dtOptions: any = {};
  docNodeId: string;
  detailTaskId: any;

  constructor(private auth: AuthenticationService,
              public dialog: MatDialog,
              private http: HttpClient) 
  {
    console.log('DashboardComponent - constructor');
    this.listServices = this.klinckServices.listServices;
    console.log(this.listServices);
    this.getPatients();
    this.getMedecins();
    this.getDocumentType();
  }

但我在控制台中收到此错误消息:"ERROR TypeError: Cannot read property 'listServices' of undefined"

那么在组件和服务之间进行通信的最佳方式是什么?

例如您可以:

  1. 在Angular中使用单例服务,登录时加载一次数据
  2. 不在登录时加载数据,而是在仪表板初始化时加载数据(接口 U 在 class 定义中使用的 OnInit 方法 - 当然,您必须在构造函数中注入 KlinkService 才能将其用作 @CornelC 在他的回答中提到)。

你的其他问题:为什么你不在 KlinkService.getActiveTasks 的服务中使用 Rxjs(它是 angualar 的标准)(因为你称它为 promise)?

您应该像在 LoginComponent

中那样注入服务
constructor(private klinckServices: KlinckServices

你也应该提供给模块

providers: [KlinckServices]