【问题标题】:Calling method from grandchild component in angular 7从角度7中的孙子组件调用方法
【发布时间】:2019-10-16 06:08:20
【问题描述】:

我有一个 Angular 7 应用程序并试图从其孙组件调用 Parent 的方法。我有模态组件,它是大子组件。我正在尝试从那里调用该方法。我通过使用有效的输出事件从其直接父级调用相同的方法 但是我怎么给孙子打电话。

我已经声明了事件

@Output() termDetailsEvent = new EventEmitter<string>();

并这样调用父方法:this.termDetailsEvent.next('getTermsDetails');

父组件

    import { Component, OnInit, Input, ViewChild } from '@angular/core';
    import { TermsService } from '../services/terms.service';
    import { FundClassesComponent } from './fundClasses/fundClasses.component';


    @Component({
        selector: 'mgr-terms',
        templateUrl: 'terms.component.html'
    })


    export class TermsComponent implements OnInit {

        private Error: string;
        public TermDetails: any;
        private _ManagerStrategyId: number;
        FilteredClasses: any;
        OriginalList: any;
        Funds: any;
        FundClassType: any;
        FirmFunds: any;
        public get ManagerStrategyId(): number {
            return this._ManagerStrategyId;
        }

        @ViewChild(FundClassesComponent)
        fundClassesComponent: FundClassesComponent;

        @Input()
        public set ManagerStrategyId(value: number) {
            this._ManagerStrategyId = value;
        }
        FundClasses: any;
        LegalFundClasses: any;
        originalFundClasses: any;
        constructor(private termsService: TermsService) { }

        ngOnInit() {
            this.init();
        }

        init() {
            this.getTermsDetails();
        }


        public getTermsDetails() {
            if (this.ManagerStrategyId != null) {
                this.termsService.getTermsDetails(this.ManagerStrategyId).subscribe((data: any) => {
                    this.TermDetails = data;
                    this.OriginalList = JSON.parse(JSON.stringify(data));
                    this.FundClasses = this.TermDetails.FundClassViewModel;
                    this.LegalFundClasses = this.TermDetails.LegalFundClassViewModel;
                    this.Funds = this.TermDetails.LegalFundClassViewModel.Funds;
                    this.FundClassType = this.TermDetails.LegalFundClassViewModel.FundClassType;
                    this.FirmFunds = this.TermDetails.LegalFundClassViewModel.FirmFunds;

                    this.TermDetails.FundClassViewModel.FundDetailsViewModel.forEach(funDetail=> {
                        funDetail.FundClassDetailsViewModel = funDetail.FundClassDetailsViewModel
                            .reduce((prev, next) => prev = prev.concat(next), [])
                            .filter(obj => obj.InvestedAmount !== null);
                    });


                });
            }
        }
    }

父组件html

<mgr-fund-classes (termDetailsEvent)="getFundInvestedDetails($event)" [FundClasses]="FundClasses" ></mgr-fund-classes>
<br/>
<br/>
<mgr-legal-fund-classes  (termDetailsEvent)="getTermsDetails()" [Funds] = "Funds" [FundClassType] = "FundClassType" [LegalFundClasses]="LegalFundClasses" [FirmFunds] ="FirmFunds" ></mgr-legal-fund-classes>

子组件

    import { Component, OnInit, Input, ViewChild, Output, EventEmitter } from '@angular/core';
    import { TermsService } from '../../services/terms.service';
    import { NotifyService } from '../../utilities/notify.service';
    import { number } from '@amcharts/amcharts4/core';
    import { IReview } from '../terms.interface';
    import { AddLegalFundClassComponent } from './addLegalFundClass.component';
    import { AddSideLetterComponent } from './addSideLetter.component';
    import { CloneLegalFundClassComponent } from './cloneLegalFundClass.component';


    @Component({
        selector: 'mgr-legal-fund-classes',
        templateUrl: './legalFundClasses.component.html'
    })



    export class LegalFundClassesComponent implements OnInit {

        private _legalFundClasses: any;
        LegalFundClass: any;

        @Output() termDetailsEvent = new EventEmitter<string>();


        public get LegalFundClasses(): any {
            return this._legalFundClasses;
        }
        @Input()
        public set LegalFundClasses(value: any) {
            this._legalFundClasses = value;
        }



        public defaultItem: { Name: string, Id: number } = { Name: "Select item...", Id: null };

        constructor(private termsService: TermsService, private notify: NotifyService) { }

        ngOnInit() {
            this.init();
        }


        public value: any = [{ Id: null, Name: "" }];



        Update(id) {
            this.LegalFundClass = this.LegalFundClasses.LegalFundClassDetailsViewModel
                  .find(obj => obj.Id === id);

            this.termsService.updateLegalFundClasses(this.LegalFundClass).then((result) => {
                if (result) {
                    this.notify.success('Legal Fund Class Details Successfully Updated');
                    this.EditMode[id] = !this.EditMode[id];
                    this.termDetailsEvent.next('getTermsDetails');
                }
            }).catch(err => {
                this.notify.error('An Error Has Occured While Updating Legal Fund Class Details');
            });
        }

        Delete(id) {

            this.termsService.deleteLegalFundClasses(id).then((result) => {
                if (result) {
                    this.notify.success('Legal Fund Class Successfully Deleted');
                    this.EditMode = !this.EditMode[id];
                    this.termDetailsEvent.next('getTermsDetails');
                }
            }).catch(err => {
                this.notify.error('An Error Has Occured While Deleting Fund Class Details');
            });
        }

子组件html

<shared-modal [modalSize]="1" class="survey-edit" [open]="cloneLegalFundClassWindowOpened">
    <div style="width: 100%;" header>
        <h4 class="modal-title">
            <div style="text-align: right"><button aria-label="Dismiss" class="close" style="margin-top: -10px"
                    type="button" (click)="dismissCloneModal()">X</button>
            </div>
        </h4>
    </div>
    <div body>
        <app-clone-legalclass  (termDetailsEvent)="getTermsDetails()" [FirmFunds]="FirmFunds"></app-clone-legalclass>

    </div>
    <div footer>
    </div>
</shared-modal>

子组件

    export class CloneLegalFundClassComponent implements OnInit {

        private Error: string;
        public ManagerDetails: any;
        public EditorConfig: string;
        public CloneLegalFundClass: ICloneLegalFundClass;

        @Input() FirmFunds: any;
        @Output() termDetailsEvent = new EventEmitter<string>();

        constructor(private termsService: TermsService, private notify: NotifyService) {
        }

        ngOnInit() {

            this.CloneLegalFundClass = { Description: '', Id: null, FundId: null };
        }


        cloneLegalFundClass() {
            this.CloneLegalFundClass.FundId = this.FirmFunds.find(x => x.Id === this.CloneLegalFundClass.Id).FundId;
            this.termsService.cloneLegalFundClasses(this.CloneLegalFundClass).then((result) => {
                if (result) {
                    this.notify.success('Legal Fund Class Cloned Successfully');
                    this.termDetailsEvent.next('getTermsDetails');
                }
            }).catch(err => {
                this.notify.error('An Error Has Occured While cloning Legal Fund Class');
            });
        }

        closeLegalFundClass() {

        }
    }

【问题讨论】:

  • 你可以嵌套@Output()。当孙子向孩子发射时,只需让孩子向其父母发射。如果您有多个方法,则需要以这种方式调用服务可能是更好的方法。
  • 如果我采用非服务方法,我的实施有什么问题
  • 没有错 - 只是如果应用程序增长,可能很难跟踪执行的内容。
  • 但我目前的问题是我无法从孙子组件调用。我没有看到父组件触发
  • 尝试使用 .emit 而不是 .next

标签: angular angular-controller angular-observable


【解决方案1】:

我创建了一个简单的 Stackblitz 来展示如何做到这一点。您只需继续向外发射: https://stackblitz.com/edit/angular-ad4kf3

孙子ts:

    import { Component, Output, EventEmitter, OnInit } from '@angular/core';
import { timer } from 'rxjs';


@Component({
  selector: 'app-grandchild',
  templateUrl: './grandchild.component.html',
  styleUrls: ['./grandchild.component.css']
})
export class GrandchildComponent implements OnInit {
  @Output() emitToChild: EventEmitter<void> = new EventEmitter();
  constructor() { }

  ngOnInit() {
    // emitting to child every two seconds, check console
    this.emit();
  }

  emit() {
    this.emitToChild.emit();
    timer(2000).subscribe(() => this.emit());
  }
}

孙 HTML:

<p>I'm grandchild.</p>

儿童 TS:

import { Component, OnInit, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
  @Output() emitToParent: EventEmitter<void> = new EventEmitter();
  constructor() { }

  ngOnInit() {
  }

}

子 HTML:

<p>I'm child.</p>
<app-grandchild (emitToChild)="emitToParent.emit()"></app-grandchild>

父 TS:

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {

  doSomething() {
    console.log('hello');
  }
}

父 HTML:

<p>I'm Parent</p>

<app-child (emitToParent)="doSomething()"></app-child>

【讨论】:

    猜你喜欢
    • 2022-07-07
    • 2017-08-10
    • 2020-08-29
    • 2017-12-24
    • 2019-10-27
    • 2023-04-08
    • 2018-08-22
    • 2019-05-15
    • 1970-01-01
    相关资源
    最近更新 更多