我创建了一个父子组件。我必须从子组件的按钮单击中执行父组件的方法。为此,我使用EventEmitter从子组件向父组件发出事件。为了获取发出的事件并调用父组件的方法,我正在使用 ViewChild 使用子组件的引用。我已经订阅了发出的事件。 在单击子组件后,我应该收到一个警报,但是在单击后,我会得到两个警报,这意味着该事件多次触发。请解释并提供解决方案。
<!-- child component .html file -->
<div class="container-fluid">
<div id="FormHeader">
<div style="float: left;width: auto;font-weight: 600;font-size: 20px;margin: 4px 0px 0px 3px;">
{{FormName}}
</div>
<div style="background-color:#efefef;width:auto;cursor: pointer;border-radius: 4px;float: right;margin:3px 3px 0px 0px;">
<button igxButton="icon" igxRipple igxButtonColor="#000" igxRippleCentered="true" style="float: right;" (click)="OnFormDelete()">
<igx-icon fontSet="material" title="Delete">delete_forever</igx-icon>
</button>
<button igxButton="icon" igxRipple igxButtonColor="#000" igxRippleCentered="true" style="float: right;" (click)="OnFormSave()">
<igx-icon fontSet="material" title="Save">save</igx-icon>
</button>
<button igxButton="icon" igxRipple igxButtonColor="#000" igxRippleCentered="true" style="float: right;" (click)="OnFormSearch()">
<igx-icon fontSet="material" title="Load">folder_open</igx-icon>
</button>
<button igxButton="icon" igxRipple igxButtonColor="#000" igxRippleCentered="true" style="float: right;" (click)="OnFormRefresh()">
<igx-icon fontSet="material" title="New">restore_page</igx-icon>
</button>
</div>
</div>
</div>
//Child component
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-form-header',
templateUrl: './form-header.component.html',
styleUrls: ['./form-header.component.scss']
})
export class FormHeaderComponent implements OnInit {
@Input() FormName:any;
@Output() onSave = new EventEmitter<any>();
@Output() onSearch= new EventEmitter<any>();
@Output() onDelete= new EventEmitter<any>();
@Output() onNew= new EventEmitter<any>();
constructor() { }
ngOnInit() {
console.log(this.FormName);
}
OnFormSave()
{
this.onSave.emit();
}
OnFormSearch()
{
this.onSearch.emit();
}
OnFormDelete(){
this.onDelete.emit();
}
OnFormRefresh()
{
this.onNew.emit();
}
}
//Parent component
import { Component, OnInit, ViewChild ,AfterViewInit} from '@angular/core';
import { HttpServiceService } from '../../Shared/Http/http-service.service';
import {FormHeaderComponent } from '../../Layout/form-header/form-header.component'
import { VendorDetail, VendorContactDetail, VendorBankDetail } from '../../Models/vendor-detail';
import { IgxDropDownComponent, ISelectionEventArgs, IgxDialogComponent, IgxGridComponent, IgxGridCellComponent, IgxRowComponent, IgxGridRowComponent } from 'igniteui-angular';
@Component({
selector: 'app-vendor-page',
templateUrl: './vendor-page.component.html',
styleUrls: ['./vendor-page.component.scss']
})
export class VendorPageComponent implements OnInit {
@ViewChild('BankGrid',{read:IgxGridComponent,static:false}) bankgrid: IgxGridComponent;
@ViewChild('ContactGrid',{read:IgxGridComponent,static:false}) public ContactGrid: IgxGridComponent;
@ViewChild('AddBankDialog',{static:false}) AddBankDialog:IgxDialogComponent;
@ViewChild('AddContactDialog',{static:false}) AddContactDialog:IgxDialogComponent;
@ViewChild('formHeader',{static: false}) set FormHeaderCo(formHeader:FormHeaderComponent){
formHeader.FormName ="VendorMaster";
formHeader.onSave.subscribe(()=>{
alert('Save clicked');
});
formHeader.onDelete.subscribe(()=>{
alert('Delete clicked');
});
formHeader.onSearch.subscribe(()=>{
alert('Search clicked');
});
formHeader.onNew.subscribe(()=>{
alert('New clicked');
});
}
VendorRegDetail = new VendorDetail();
ContactRegDetail : any = {};
BankRegDetail : any = {};
CityDropDownArr:any;
StateDropDownArr:any;
CountryDropDownArr:any;
GSTRegTypeDropDownArr:any;
ContactDetailArr:VendorContactDetail[]=[];
BankDetailArr:VendorBankDetail[]=[];
AddAndEditContact:any ={};
AddAndEditBank:any ={};
constructor(public http:HttpServiceService) { }
ngOnInit() {
this.FillPageValues();
}
ngAfterViewInit()
{
this.ContactGrid.data = [];
this.ContactGrid.reflow();
this.bankgrid.reflow();
}
FillPageValues()
{
this.http.PostApi('api/Vendor/VendorFillValues','',Response=>{
let TemptblRes = Response;
this.CityDropDownArr = TemptblRes['Table'];
this.StateDropDownArr = TemptblRes['Table1'];
this.CountryDropDownArr = TemptblRes['Table2'];
this.GSTRegTypeDropDownArr = TemptblRes['Table3'];
});
}
SelectCountry(eve:ISelectionEventArgs)
{
this.CountryDropDownArr.filter(item=>{
if(eve.newSelection.value === item.CountryName)
{
this.VendorRegDetail.CountryNo = item.CountryNo;
}
})
}
SelectState(event:ISelectionEventArgs)
{
this.StateDropDownArr.filter(item=>{
if(event.newSelection.value === item.StateName)
{
this.VendorRegDetail.StateNo = item.StateNo;
}
})
}
SelectCity(eve:ISelectionEventArgs)
{
this.CityDropDownArr.filter(item=>{
if(eve.newSelection.value === item.CityName)
{
this.VendorRegDetail.CityNo = item.CityNo;
}
});
}
SelectGSType(eve:ISelectionEventArgs)
{
this.GSTRegTypeDropDownArr.filter(item=>{
if(eve.newSelection.value === item.GSTRegistrationTypeName)
{
console.log(item);
this.VendorRegDetail.GSTRegistrationNo = item.GSTRegistrationTypeNo;
}
});
}
AddContactDetail(){
if(this.AddAndEditContact.type ==="edit")
{
this.ContactGrid.getRowByIndex(this.AddAndEditContact.rowNo).update(this.ContactRegDetail);
}
if(this.AddAndEditContact.type !=="edit")
{
this.ContactGrid.addRow(this.ContactRegDetail);
}
this.ContactGrid.reflow();
this.ContactRegDetail ={};
this.AddContactDialog.close();
}
EditContactDetail(cell:IgxGridRowComponent)
{
this.AddAndEditContact.type = "edit";
this.ContactRegDetail = cell.rowData;
this.ContactGrid.reflow();
this.AddContactDialog.open();
}
DeleteContactRow(cell:any)
{
this.ContactGrid.getRowByIndex(cell.rowIndex).delete();
}
AddBankDetail(){
if(this.AddAndEditBank.type ==="edit")
{
this.bankgrid.getRowByIndex(this.AddAndEditBank.rowNo).update(this.BankRegDetail);
}
if(this.AddAndEditBank.type !=="edit")
{
this.bankgrid.addRow(this.BankRegDetail);
}
this.bankgrid.reflow();
this.BankRegDetail ={};
this.AddBankDialog.close();
}
EditBankDetail(cell:IgxGridRowComponent)
{
this.AddAndEditBank.type = "edit";
this.BankRegDetail = cell.rowData;
this.bankgrid.reflow();
this.AddBankDialog.open();
}
DeleteBankRow(cell:any)
{
this.bankgrid.getRowByIndex(cell.rowIndex).delete();
}
}
<!-- parent component .html file -->
<app-form-header #formHeader></app-form-header>
<div class="container-fluid">
<igx-tabs class="form" >
<igx-tabs-group label="Vendor Details">
<div class="container-fluid">
<div class="row">
<div class="col-md-4">
<div class="row">
<div class="col-sm-4" style="padding-top:25px;" >
Code<span style="color:red">*</span> :
</div>
<div class="col-sm-8" >
<igx-input-group>
<input igxInput name="Code" type="text" [(ngModel)]="VendorRegDetail.VendorCode" required="required" disabled="true" style="cursor: not-allowed;" />
<label igxLabel for="Code">Code</label>
</igx-input-group>
</div>
<div class="col-sm-4" style="padding-top:22px;margin-top: 20px;" >
VendorName<span style="color:red">*</span> :
</div>
<div class="col-sm-8" style="margin-top: 20px;">
<igx-input-group>
<input igxInput name="vendorName" type="text" required="required" [(ngModel)]="VendorRegDetail.VendorName"/>
<label igxLabel for="vendorName">Vendor Name</label>
</igx-input-group>
</div>
<div class="col-sm-4" style="padding-top:22px;margin-top: 20px;">
Address 1<span style="color:red">*</span> :
</div>
<div class="col-sm-8" style="margin-top: 20px;">
<igx-input-group>
<input igxInput name="Address1" type="text" required="required" [(ngModel)]="VendorRegDetail.Address1"/>
<label igxLabel for="Address1"> Address1</label>
</igx-input-group>
</div>
<div class="col-sm-4" style="padding-top:22px;margin-top: 20px;">
Address 2 :
</div>
<div class="col-sm-8" style="margin-top: 20px;">
<igx-input-group>
<input igxInput name="Address2" type="text" [(ngModel)]="VendorRegDetail.Address2"/>
<label igxLabel for="Address2"> Address2</label>
</igx-input-group>
</div>
<div class="col-sm-4" style="padding-top:22px;margin-top: 20px;">
Address 3 :
</div>
<div class="col-sm-8" style="padding-bottom:20px;margin-top: 20px;">
<igx-input-group>
<input igxInput name="Address3" type="text" [(ngModel)]="VendorRegDetail.Address3" />
<label igxLabel for="Address3"> Address3</label>
</igx-input-group>
</div>
</div>
</div>
<div class="col-md-4">
<div class="row">
<div class="col-sm-4" style="padding-top:25px;">
City :
</div>
<div class="col-sm-8" >
<div>
<igx-input-group #inputGroup [igxToggleAction]="citydropDown" class="input-group">
<input #input class="input" type="text" igxInput [igxDropDownItemNavigation]="citydropDown"
readonly= "true"
placeholder="choose an city"
[value]="citydropDown.selectedItem?.value"
(keydown.ArrowDown)="openCityDropDown()" />
<igx-suffix igxButton="icon" class="dropdownToggleButton" igxRipple>
<igx-icon>arrow_drop{{ citydropDown.collapsed ? '_down' : '_up' }}</igx-icon>
</igx-suffix>
</igx-input-group>
<igx-drop-down #citydropDown [width]="'250px'" [height]="'160px'" (onSelection)="SelectCity($event)" >
<igx-drop-down-item *ngFor="let item of CityDropDownArr" [value]="item.CityName" >
{{ item.CityName }}
</igx-drop-down-item>
</igx-drop-down>
</div>
</div>
<div class="col-sm-4" style="padding-top:22px;margin-top: 20px;">
State :
</div>
<div class="col-sm-8" style="margin-top: 20px;" >
<div *ngIf="VendorRegDetail.CityNo">
<igx-input-group #inputGroup [igxToggleAction]="statedropDown" class="input-group">
<input #input class="input" type="text" igxInput [igxDropDownItemNavigation]="statedropDown"
readonly= "true"
placeholder="choose an state"
[value]="statedropDown.selectedItem?.value" />
<igx-suffix igxButton="icon" class="dropdownToggleButton" igxRipple>
<igx-icon>arrow_drop{{ statedropDown.collapsed ? '_down' : '_up' }}</igx-icon>
</igx-suffix>
</igx-input-group>
<igx-drop-down #statedropDown [width]="'250px'" [height]="'160px'" (onSelection)="SelectState($event)">
<igx-drop-down-item *ngFor="let item of StateDropDownArr" [value]="item.StateName" >
{{ item.StateName }}
</igx-drop-down-item>
</igx-drop-down>
</div>
</div>
<div class="col-sm-4" style="padding-top:22px;margin-top: 20px;">
Country :
</div>
<div class="col-sm-8" style="margin-top: 20px;">
<div *ngIf="VendorRegDetail.StateNo">
<igx-input-group #inputGroup [igxToggleAction]="CountrydropDown" class="input-group">
<input #input class="input" type="text" igxInput [igxDropDownItemNavigation]="CountrydropDown"
readonly= "true"
placeholder="choose a Country"
[value]="CountrydropDown.selectedItem?.value" />
<igx-suffix igxButton="icon" class="dropdownToggleButton" igxRipple>
<igx-icon>arrow_drop{{ CountrydropDown.collapsed ? '_down' : '_up' }}</igx-icon>
</igx-suffix>
</igx-input-group>
<igx-drop-down #CountrydropDown [width]="'250px'" [height]="'100px'" (onSelection)="SelectCountry($event)">
<igx-drop-down-item *ngFor="let item of CountryDropDownArr" [value]="item.CountryName">
{{ item.CountryName }}
</igx-drop-down-item>
</igx-drop-down>
</div>
</div>
<div class="col-sm-4" style="padding-top:22px;margin-top: 20px;">
Mailing Name<span style="color:red">*</span> :
</div>
<div class="col-sm-8" style="margin-top: 20px;">
<igx-input-group>
<input igxInput name="MailingName" type="text" required="required" [(ngModel)]="VendorRegDetail.MailingName"/>
<label igxLabel for="MailingName"> Mailing Name </label>
</igx-input-group>
</div>
<div class="col-sm-4" style="padding-top:22px;margin-top: 20px;">
PAN No.<span style="color:red">*</span> :
</div>
<div class="col-sm-8" style="margin-top: 20px;padding-bottom:20px;">
<igx-input-group>
<input igxInput name="PANNo" type="text" required="required"[(ngModel)]="VendorRegDetail.PANNo" />
<label igxLabel for="PANNo">PANNo</label>
</igx-input-group>
</div>
</div>
</div>
<div class="col-md-4">
<div class="row">
<div class="col-sm-4" style="padding-top:25px;">
CIN No. :
</div>
<div class="col-sm-8" >
<igx-input-group>
<input igxInput name="CINNo" type="text" required="required" [(ngModel)]="VendorRegDetail.CINNo" />
<label igxLabel for="CINNo">CINNo</label>
</igx-input-group>
</div>
<div class="col-sm-4" style="padding-top:22px;margin-top: 20px;">
GST Reg. Type<span style="color:red">*</span> :
</div>
<div class="col-sm-8" style="margin-top: 20px;">
<igx-input-group #inputGroup [igxToggleAction]="GstdropDown" class="input-group">
<input #input class="input" type="text" igxInput [igxDropDownItemNavigation]="GstdropDown"
readonly= "true"
placeholder="choose an GST Type"
[value]="GstdropDown.selectedItem?.value"
(keydown.ArrowDown)="openGstdropDown()"/>
<igx-suffix igxButton="icon" class="dropdownToggleButton" igxRipple>
<igx-icon>arrow_drop{{ GstdropDown.collapsed ? '_down' : '_up' }}</igx-icon>
</igx-suffix>
</igx-input-group>
<igx-drop-down #GstdropDown [width]="'250px'" [height]="'100px'" (onSelection)="SelectGSType($event)">
<igx-drop-down-item *ngFor="let item of GSTRegTypeDropDownArr" [value]="item.GSTRegistrationTypeName">
{{ item.GSTRegistrationTypeName }}
</igx-drop-down-item>
</igx-drop-down>
</div>
<div class="col-sm-4" style="padding-top:22px;margin-top: 20px;">
GSTIN No. :
</div>
<div class="col-sm-8" style="margin-top: 20px;padding-bottom: 20px;" *ngIf="VendorRegDetail.GSTRegistrationNo===3">
<igx-input-group>
<input igxInput name="Country" type="text" [(ngModel)]="VendorRegDetail.GSTINNo"/>
<label igxLabel for="Country"> GSTINNo</label>
</igx-input-group>
</div>
</div>
</div>
</div>
</div>
</igx-tabs-group>
<igx-tabs-group label="Contact Detail">
<div style="float: left;padding:10px 0px 10px 20px">
<button igxButton="flat" igxRipple="white" (click)="AddContactDialog.open()" [displayDensity]="'compact'" style="font-weight: 800;">
<igx-icon>add_box</igx-icon> ADD
</button>
</div>
<div style="padding:60px 0px 20px 60px;overflow: auto;text-align: center;">
<igx-grid #ContactGrid width="1000px" [displayDensity]="'compact'" height="200px" >
<igx-column field="ContactPersonName" header="Contact Person Name"> </igx-column>
<igx-column field="ContactEmail" header="Email" > </igx-column>
<igx-column field="ContactNo" header="Contact No."> </igx-column>
<igx-column field="Designation" header="Designation"> </igx-column>
<igx-column field="Edit" width="90">
<ng-template igxCell let-cell="cell" >
<button igxButton="icon" (click)="EditContactDetail(cell);AddAndEditContact.rowNo=cell.rowIndex;" >
<igx-icon style="font-size: 20px">edit</igx-icon>
</button>
<button igxButton="icon" tabindex="0" >
<igx-icon style="font-size: 20px" (click)="DeleteContactRow(cell)">delete</igx-icon>
</button>
</ng-template>
</igx-column>
</igx-grid>
</div>
<igx-dialog #AddContactDialog title="Add Contact"
leftButtonLabel="Cancel"
(onLeftButtonSelect)="AddContactDialog.close();"
(onRightButtonSelect)="AddContactDetail();ContactRegDetail={};AddAndEditContact.type='new'"
rightButtonLabel="Add"
[closeOnOutsideSelect]="true" style="max-width: 200px;">
<div class="">
<igx-input-group style="margin: 20px;">
<label igxLabel for="personname" >Contact Person Name</label>
<input igxInput id="personname" type="text" [(ngModel)]="ContactRegDetail.ContactPersonName" />
</igx-input-group>
<igx-input-group style="margin: 20px;">
<label igxLabel>Email</label>
<input igxInput id="Email" type="email" [(ngModel)]="ContactRegDetail.ContactEmail" />
</igx-input-group>
<igx-input-group style="margin: 20px;">
<label igxLabel>Contact No.</label>
<input igxInput id="phoneno" type="text" [(ngModel)]="ContactRegDetail.ContactNo" />
</igx-input-group>
<igx-input-group style="margin: 20px;">
<label igxLabel>Designation </label>
<input igxInput id="designation" type="text" [(ngModel)]="ContactRegDetail.Designation" />
</igx-input-group>
</div>
</igx-dialog>
</igx-tabs-group>
<igx-tabs-group label="Bank Detail">
<div style="float: left;padding:10px 0px 10px 20px">
<button igxButton="flat" igxRipple="white" (click)="AddBankDialog.open()" [displayDensity]="'compact'" style="font-weight: 800;">
<igx-icon>add_box</igx-icon> ADD
</button>
</div>
<div style="padding:60px 0px 20px 60px;overflow: auto;text-align: center;">
<igx-grid [data]="BankDetailArr"
width="1000px" [displayDensity]="'compact'" #BankGrid height="200px">
<igx-column field="BankName" header="Bank Name"> </igx-column>
<igx-column field="BankBranch" header="Branch"> </igx-column>
<igx-column field="AccountNo" header="Account No."> </igx-column>
<igx-column field="IFSCCode" header="IFSC Code"> </igx-column>
<igx-column field="Edit" width="90">
<ng-template igxCell let-cell="cell" >
<button igxButton="icon" (click)="EditBankDetail(cell);AddAndEditBank.rowNo = cell.rowIndex" >
<igx-icon style="font-size: 20px">edit</igx-icon>
</button>
<button igxButton="icon" tabindex="0" (click)="DeleteBankRow(cell)"><igx-icon style="font-size: 20px">delete</igx-icon></button>
</ng-template>
</igx-column>
</igx-grid>
</div>
<igx-dialog #AddBankDialog title="Add Bank Detail"
leftButtonLabel="Cancel"
(onLeftButtonSelect)="AddBankDialog.close();"
(onRightButtonSelect)="AddBankDetail();BankRegDetail={};AddAndEditBank.type='new'"
rightButtonLabel="Add"
[closeOnOutsideSelect]="true" style="max-width: 200px;">
<div>
<igx-input-group style="margin: 20px;">
<label igxLabel for="Bankname">Bank Name</label>
<input igxInput id="Bankname" type="text" [(ngModel)]="BankRegDetail.BankName" />
</igx-input-group>
<igx-input-group style="margin: 20px;">
<label igxLabel>Branch</label>
<input igxInput id="Branch" type="text" [(ngModel)]="BankRegDetail.BankBranch" />
</igx-input-group>
<igx-input-group style="margin: 20px;">
<label igxLabel>Account No.</label>
<input igxInput id="accountno" type="text" [(ngModel)]="BankRegDetail.AccountNo" />
</igx-input-group>
<igx-input-group style="margin: 20px;">
<label igxLabel>IFSC Code </label>
<input igxInput id="ifsccode" type="text" [(ngModel)]="BankRegDetail.IFSCCode"/>
</igx-input-group>
</div>
</igx-dialog>
</igx-tabs-group>
</igx-tabs>
</div>