【问题标题】:Emit an event From services Angular从服务 Angular 发出事件
【发布时间】:2020-10-07 10:39:55
【问题描述】:

组件代码

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


on reading this link able to know its not good practice to use eventemitter in servies。上面的代码完美运行我的问题是我有formData的通用函数,它获取表单的值取决于tabclick值。第一次事件在单击其他选项卡时按预期发射,即第二次单击它发射两次,当第三次发射 3 次 4 意味着 4 次时,任何人都可以建议我最好的方法,我是 ne 角度

【问题讨论】:

    标签: angular angular-services angular-components angular-event-emitter


    【解决方案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 并非设计为多播 observable 的 Angular 特定实现。其目的是为具有父子关系的组件提供自定义事件。

    如果查看EventEmitter的来源,它是RxJS Subject的接口扩展。因此,如果我们需要在服务中使用多播 observable,我们可以直接使用它。

    服务

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

    您还需要在关闭组件时关闭所有活动订阅以避免潜在的内存泄漏。您可以在 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();
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-02-05
      • 1970-01-01
      • 2021-09-06
      • 1970-01-01
      • 2021-02-19
      • 2018-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多