【问题标题】:Angular 2 - Error: Maximum call stack size exceededAngular 2 - 错误:超出最大调用堆栈大小
【发布时间】:2017-10-14 06:50:21
【问题描述】:

请看一下这个问题。

假设

我有一个带有表单的组件来添加/编辑测试用例。组件可以在 3 种不同的模式(第一个参数)下运行(0 - 空表单,1 - 编辑模式,2 - 显示模式(无输入),选择的测试用例作为第二个参数。第二个参数可以是一个测试用例对象(如果模式为0并且定义了测试用例对象,该对象将成为新测试用例的父对象。如果模式为1,选定的测试用例将被编辑测试用例,当模式为2时,选定的测试用例将显示测试用例。如果测试用例对象未定义,则新的测试用例将没有父对象,因此它将位于树的顶部。

表单包含 2 个字段:名称和功能标志。可以从下拉列表中选择功能标志并添加到表单中。它有一个树形结构。

错误再现

当我选择一个测试用例,打开表单添加新或编辑测试用例,添加一些标志,关闭表单,打开新表单,反复N次,它出现错误。我的代码中没有任何 recuret 函数调用

错误文字:

代码

test-case.component.ts:

    /**
     * 
     */
    public ngOnInit() { 
        this.testCasesService.getAll().subscribe(
            records => {
                this.testCases = this.testCasesService.asTree(records, { parent: true, expanded: true })               
            },
            err => {
                console.log(err)
            }
        )
    } 

    /**
     * Opens test case form
     */
    private openTestCaseForm(parent, mode?) {
        if(!parent) 
            this.selectedNode = undefined; 

        if(this.mode != mode) 
            this.mode = mode;

        this.addNewTestCaseForm       = true  
    }

test-case.template.html

<div style="float: left; width: 100%;">
    <p>
        <p-toolbar>
            <div class="ui-toolbar-group-left">
                <button (click)="openTestCaseForm(false)" pButton type="button" label="New Test Case" icon="fa-plus"></button>
                <button *ngIf="!selectedNode" [disabled]="true" pButton type="button" label="New Child Test Case" icon="fa-plus"></button>
                <button *ngIf="selectedNode" (click)="openTestCaseForm(true)" pButton type="button" label="New Child Test Case" icon="fa-plus"></button>
            </div> 
            <div class="ui-toolbar-group-right">
                <button *ngIf="selectedNode" (click)="openTestCaseForm(true, 1)" pButton type="button" icon="fa-pencil-square-o" label="Edit"></button>
                <button *ngIf="selectedNode" pButton type="button" icon="fa-trash-o" class="ui-button-danger" label="Remove"></button>
            </div>
        </p-toolbar> 
    </p>
</div>
<div style="float: left; width: 35%">
    Search <input placeholder="Search" pInputText type="text" style="border: 1px solid silver" /><br /><br />

    <p-tree [style]="{'font-size':'18px', 'width': '95%'}" selectionMode="single" [(selection)]="selectedNode" [value]="testCases"></p-tree>
</div>
<div style="float: left; width: 65%; border-left: 1px solid silver; padding-left: 20px; font-size: 18px">
    <test-case-editor [testCase]="selectedNode" *ngIf="selectedNode"></test-case-editor>           
</div>

<p-dialog width="1800" modal="true" header="Add New Test Case" [(visible)]="addNewTestCaseForm">
    <test-case-editor [testCase]="selectedNode" [mode]="mode"></test-case-editor>
</p-dialog>

test-case-editor.ts(测试用例表单控制器)

export class TestCaseEditorComponent implements OnInit {
    /**
     * Options for FEATURES flags 
     */
    private featureOptions:any[] = [];

    /**
     * Selected node
     */
    private selectedFeatureNode:any;

    /**
     * Added features (flags)
     */
    private nodes:any[] = [];

    /**
     * Name of test case
     */
    private name:string;

    /**
     * Test case to display/edit
     */
    @Input() public testCase:any;

    /**
     * Mode (0 - new tc, 1 - edit mode, 2 - display mode)
     */
    @Input() public mode:number = 2;

    /**
     * Constructor
     * @param featureFlagsService 
     * @param testCasesService 
     * @param communicatesService 
     */
    constructor(
        private testCasesService:TestCasesService,
        private communicatesService:CommunicatesService,
        private featureFlagsService:FeatureFlagsService) {}

    /**
     * Actions after init
     */
    public ngOnInit() {

    }

    public ngOnChanges() {
        this.init()
    }


    /**
     * Loads flags for particular testCase
     * @param testCase
     */
    public init() {
        this.nodes = []

        this.featureFlagsService.getAll().subscribe(           
            records => {   
                //Creating a tree        
                let tree = this.featureFlagsService.asTree(records, { parent: true })      

                let features      = this.testCasesService.getFeatures(tree)
                let configuration = this.testCasesService.getConfigurationFeatures(tree)

                let featureOptions     = [{ label: 'Select feature...', value: null }]
                featureOptions         = featureOptions.concat(this.testCasesService.getFeaturesOptions(configuration))
                this.featureOptions    = featureOptions.concat(this.testCasesService.getFeaturesOptions(features))

                //Filling form with flags in table when editing
                if(this.testCase && (this.mode == 1 || this.mode == 2)) {
                    this.name = this.testCase.data.name;


                }   
            }                                             
        )          
    }

    /**
     * Adds flag to feature list
     * @param flag 
     */
    private addNode(node) {  
        let found = this.nodes.find(element => {
            if(element.data.id == node.data.id) {
                return true
            }
        })
        if(!found) 
            this.nodes.push(node)
    }

问候

【问题讨论】:

    标签: javascript angular


    【解决方案1】:

    你为什么要香蕉拳击非 ngModels?

    [(visible)]="addNewTestCaseForm".

    这应该是一种单向绑定:

    [visible]="addNewTestCaseForm".

    看起来有些语法问题可能会妨碍您。

    【讨论】:

      猜你喜欢
      • 2017-08-06
      • 2017-02-27
      • 2021-08-15
      • 1970-01-01
      • 2019-05-14
      • 2019-02-07
      • 1970-01-01
      • 2018-01-24
      • 2011-08-31
      相关资源
      最近更新 更多