简体   繁体   English

从服务 Angular 发出事件

[英]Emit an event From services Angular

Componet Code组件代码

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;
    });
  }

}

service code服务代码

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)
  }
}


on reading this link able to know its not good practice to use eventemitter in servies .The above code working perfectly my issue is I have common function for formData which fetch value of form depend on tabclick value.1st time event is emitting as expect when click other tab ie second click its emitting two time,when third time its emitting 3 times 4 means 4 times can any one suggest me the best approach I am ne to angular 在阅读此链接时,能够知道在服务中使用 eventemitter 是不好的做法。上面的代码运行良好,我的问题是我对 formData 有常见的 function,它获取表单的值取决于 tabclick 值。第一次事件在单击时按预期发射其他选项卡,即第二次单击其发射两次,第三次其发射 3 次 4 表示 4 次任何人都可以建议我最好的方法,我是 angular

You are initiating a new subscription each time the listFormData function is called.每次调用listFormData function 时,您都会启动新订阅。 Instead you could subscribe in the ngOnInit() hook once.相反,您可以在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");
}

Also like you've mentioned in the question, EventEmitter is not designed as an Angular specific implementation of a multicast observable.同样就像您在问题中提到的那样, EventEmitter并非设计为 Angular 特定于多播可观察的实现。 It's purpose is to provide custom events to components with parent-child relationships.它的目的是为具有父子关系的组件提供自定义事件。

If you look at the source of the EventEmitter , it is an interface extension of the RxJS Subject .如果查看EventEmitter的来源,它是 RxJS Subject的接口扩展。 So if we require a multicast observable in a service, we could use it directly.因此,如果我们需要在服务中使用多播 observable,我们可以直接使用它。

Service服务

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
    });
  }
}

You also need to close any active subscriptions upon closing of the component to avoid potential memory leaks.您还需要在关闭组件时关闭所有活动订阅以避免潜在的 memory 泄漏。 You could either call assign the subscription to a member variable an call unsubscribe() in the ngOnDestroy() hook or use RxJS takeUntil() operator.您可以在ngOnDestroy()挂钩中调用将订阅分配给成员变量调用unsubscribe()或使用 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();
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM