Отправить событие из сервисов Angular

Код компонента

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. Событие 1-го раза испускается, как и ожидалось, при нажатии на другую вкладку, т.е. второй щелчок по его испусканию два раза, когда третий время, когда он излучает 3 раза 4 означает 4 раза, может ли кто-нибудь предложить мне лучший подход, который мне не подходит для angular


person Arunvairavan V    schedule 17.06.2020    source источник


Ответы (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< /a>, это расширение интерфейса 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();
  }
}
person Michael D    schedule 17.06.2020