从服务发出事件 Angular
Emit an event From services 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)
}
}
。上面的代码完美运行我的问题是我有 formData 的通用函数,它获取表单的值取决于 tabclick 值。第一次单击其他选项卡时事件按预期发出,即第二次单击它发射两次,当它第三次发射 3 次 4 意味着 4 次时,任何人都可以建议我最好的方法,我需要 angular
每次调用 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
, it is an interface extension of the 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
});
}
}
您还需要在关闭组件时关闭所有活动订阅,以避免潜在的内存泄漏。您可以在 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();
}
}
组件代码
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)
}
}
每次调用 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
, it is an interface extension of the 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
});
}
}
您还需要在关闭组件时关闭所有活动订阅,以避免潜在的内存泄漏。您可以在 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();
}
}