发出一个事件 来自服务 Angular

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

组件代码

import { Component, OnInit, EventEmitter, Output, Input } from '@angular/core';
import { Socket } from 'ngx-socket-io';
import { CommonService } from 'src/app/services/common.service';
import { FormioService } from 'src/app/services/formio.service';
@Component({
  selector: 'app-initialrecord',
  templateUrl: './initialrecord.component.html',
  styleUrls: ['./initialrecord.component.sass']
})
export class InitialRecordComponent implements OnInit {
  form: any = "";
  rendered = false;
  showForm: any = false;
  showTable: any = false;
  showAdd: any = true;
  showClose: any = false;
  patientData: any = {};
  currentTab = "";
  submitFunction = 'onSubmit';
  formId: any = ''
  rows: any = [];
  cols: any = [];
  formioJson: any;
  patientid = "";
  patientName = ""
  @Output() refreshForm = new EventEmitter();
  @Input() patientDetails: any = {};
  constructor(
    private FormioService: FormioService,
    private commonService: CommonService,
    private socket: Socket ) { }

  ngOnInit() {
    this.patientid=JSON.parse(this.commonService.getValue("patientDetails"))._id
    this.patientName =JSON.parse(this.commonService.getValue("patientDetails")).data.fname
    this.formioJson = JSON.parse(sessionStorage.getItem("formioJson"));
    this.listFormData('vitals')
  }

  listFormData(formName: string) {
    this.formId = formName;
    this.rows = [];
    this.cols = []
    this.toggleView(true, false, true, false)
    this.currentTab = this.formioJson[formName].name;
    let path = this.formioJson[formName].path
    let fromName = this.formioJson[formName].name
    this.FormioService.loadForms(path).subscribe(data => {
      this.FormioService.checkNested(data, true);
      this.cols = this.FormioService.cols;
    })
//calling service function
    this.FormioService.getFormData(path, formName, this.patientid, "data.patientId")
// subscribe the event
    this.FormioService.receivedRow.subscribe((param: any) => {
      this.rows = param.row;
      this.patientData[this.formioJson[formName].name] = param.data;
    });
  }

}

服务代码

import { Injectable , EventEmitter} from '@angular/core';
import { Socket } from 'ngx-socket-io';
import { environment } from '../../environments/environment';
import { ToastrService } from 'ngx-toastr';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { CommonService } from 'src/app/services/common.service';
import  moment from 'moment';

@Injectable({
  providedIn: 'root'
})
export class FormioService {
  headers: any;
  row :any[];
  cols:any[];
  receivedRow: EventEmitter<any>;
  patientData: any ={};
  constructor(private socket: Socket, private toaster: ToastrService,
    private httpClient: HttpClient,private commonService: CommonService) {
      this.receivedRow = new EventEmitter<any>()
      this.headers = new HttpHeaders({'Content-Type':'application/json; charset=utf-8','x-jwt-token':this.commonService.getValue("formioToken")})
     }
  public FORMIO_BASE_URL = environment.formioBaseUrl;
  public SOCKET_IO_URL = environment.nodeServerUrl


  getFormData(formUrl: string, tabName: string, patientId: string,keyName:string) {
    let form: any = new Object();
    form.roomId = this.commonService.roomId();
    form.token = this.commonService.getToken();
    form.eventName = tabName;
    form.formId = formUrl;
    form.query = keyName+"=" + patientId
    this.socket.emit('list', form);
    this.socket.on(tabName, async data => {
      this.row=[]
      data.forEach(element => {
        element.data['date'] =moment(element.created).format('DD-MM-YY HH:mm');
        console.log( element.data['date'] =moment(element.created).format('DD-MM-YY HH:mm'))
        this.row.push(element.data);
      });
      this.receivedRow.emit({row:this.row,data:data})
      console.log(this.row,"Formioservice")
    });
  }
  checkNested(obj: any,flag) {
    if(flag){
      this.cols =[]
      this.cols.push(JSON.parse( '{"field":"date","header":"Date"}'))
    }
    for (let prop in obj) {
      if (obj.hasOwnProperty(prop)) {
        if (typeof obj[prop] == "object") {
          //console.log('Key: ${prop}')
          this.checkNested(obj[prop],false);
        } else {
          //console.log("key >>> " + key + " >> props >>> " + obj[prop]);
          if (obj['tableView']) {
            //  console.log(`Key: ${prop} 'key_value: ${obj['key']} 'label_value: ${obj['label']} 'table_view_value: ${obj['tableView']} `)
            let temp: string = '{"field":"' + obj['key'] + '","header":"' + this.capitalize(obj['label']) + '"}';
            //  console.log(JSON.parse(temp));
            this.cols.push(JSON.parse(temp));
            break;
          }
        }
      }
    }

  }
  capitalize = (s: any) => {
    if (typeof s !== 'string') return ''
    return s.charAt(0).toUpperCase() + s.slice(1)
  }
}


看了这个链接就能知道在服务中使用eventemitter不是一个好的做法。 以上代码工作得很好,我的问题是我有一个formData的通用函数,它根据tabclick值来获取form的值,第一次事件是如预期的那样,当点击其他tab时,即第二次点击时,它发出两次,当第三次时,它发出3次,4意味着4次,任何人都可以给我建议,我是ne to angular的最佳方法。

angular angular-services angular-components angular-event-emitter
1个回答
1
投票

你每次都会发起一个新的订阅。listFormData 函数被调用。相反,你可以在 ngOnInit() 钩一次。

ngOnInit() {
  this.patientid=JSON.parse(this.commonService.getValue("patientDetails"))._id
  this.patientName =JSON.parse(this.commonService.getValue("patientDetails")).data.fname
  this.formioJson = JSON.parse(sessionStorage.getItem("formioJson"));
  this.listFormData('vitals')
  // subscribe the event
  this.FormioService.receivedRow.subscribe((param: any) => {
    this.rows = param.row;
    this.patientData[this.formioJson[formName].name] = param.data;
  });
}

listFormData(formName: string) {
  this.formId = formName;
  this.rows = [];
  this.cols = []
  this.toggleView(true, false, true, false)
  this.currentTab = this.formioJson[formName].name;
  let path = this.formioJson[formName].path
  let fromName = this.formioJson[formName].name
  this.FormioService.loadForms(path).subscribe(data => {
    this.FormioService.checkNested(data, true);
    this.cols = this.FormioService.cols;
  });
  //calling service function
  this.FormioService.getFormData(path, formName, this.patientid, "data.patientId");
}

也像你在问题中提到的。EventEmitter 并不是作为Angular特定的多播观察器的实现而设计的。它的目的是为具有父子关系的组件提供自定义事件。

如果你看一下 EventEmitter它是RxJS的一个接口扩展。Subject. 因此,如果我们在服务中需要一个多播观察器,我们可以直接使用它。

服务中的

import { Injectable} from '@angular/core';

import { Subject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class FormioService {
  ...
  receivedRowSource = new Subject<any>();
  receivedRow$ = this.receivedRowSource.asObservable();

  getFormData(formUrl: string, tabName: string, patientId: string,keyName:string) {
    ...
    this.socket.on(tabName, async data => {
      ...
      this.receivedRowSource.next({row:this.row,data:data});       // <-- use `next` to push new notification
    });
  }
}

您还需要在组件关闭时关闭任何活动的订阅,以避免潜在的内存泄漏。您可以调用将订阅分配给一个成员变量或调用 unsubscribe()ngOnDestroy() 钩子或使用RxJS takeUntil() 运营商。

import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

export class InitialRecordComponent implements OnInit, OnDestroy {
  ...
  completed$ = new Subject<any>();

  ngOnInit() {
    this.FormioService.receivedRow$.pipe(
      takeUntil(this.completed$)        // <-- pipe in the `takeUntil()` here
    ).subscribe((param: any) => {
      this.rows = param.row;
      this.patientData[this.formioJson[formName].name] = param.data;
    });
  }

  ngOnDestroy() {
    this.completed$.next();
    this.completed$.complete();
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.