Your Privacy Matters: We use our own and third-party cookies to improve your experience on our website. By continuing to use the website we understand that you accept their use. Cookie Policy
935
isHeader of undefined?
posted

I'm using latest Angular/Infragistics (12.0.3).

I'm getting an error that gives me nothing useful for tracing:

main.js:19079 ERROR TypeError: Cannot read property 'isHeader' of undefined
    at IgxComboComponent_igx_combo_item_22_Template (main.js:61907)
    at executeTemplate (main.js:22182)
    at refreshView (main.js:22048)
    at refreshEmbeddedViews (main.js:23173)
    at refreshView (main.js:22072)
    at refreshComponent (main.js:23219)
    at refreshChildComponents (main.js:21845)
    at refreshView (main.js:22098)
    at refreshEmbeddedViews (main.js:23173)
    at refreshView (main.js:22072)

There's nothing in the stack trace that goes back to a useful naming of anything I'm doing. I will describe as best I can what's going on and perhaps you can reason out why I'm getting the error (or we can create a sample together that reproduces it).

I am running a comparison between 2 scenarios (with a lot of data). I am using dropdowns, similar to dropdown-sample-4. When the 2 scenario dropdowns match, there's no issue (it produces the comparison correctly). When they do not match, however, I get the error listed above. They are implemented in pretty much exactly the same way, with appropriately different labels/variables/etc. to distinguish them properly. Here is their implementation:

        <div *ngIf="scenario1List !== undefined && scenario1List.length > 1">
            <igx-input-group #scenario1Group [igxToggleAction]="scenario1Dd" displayDensity="compact">
                <igx-prefix style="width: 150px;">&nbsp;Scenario 1 Name: </igx-prefix>
                <input #scenario1Input style="width: 250px;" type="text" igxInput [igxDropDownItemNavigation]="scenario1Dd" readonly="true" placeholder="Pick a Scenario (1)" [value]="scenario1Dd.selectedItem?.value" (keydown.ArrowDown)="openDropDown('scenario1')" />
                <igx-suffix igxButton="icon" class="dropdownToggleButton" igxRipple>
                    <igx-icon>arrow_drop{{ scenario1Dd.collapsed ? '_down' : '_up' }}</igx-icon>
                </igx-suffix>
            </igx-input-group>
            <igx-drop-down #scenario1Dd displayDensity="compact" (onSelection)="setScenario($event, 1)">
                <div class="scrollable">
                    <igx-drop-down-item [selected]="true" [value]="">Choose a Scenario</igx-drop-down-item>
                    <igx-drop-down-item *ngFor="let scen of scenario1List" [value]="scen.name">{{scen.name}}</igx-drop-down-item>
                </div>
            </igx-drop-down>
        </div>

        <div *ngIf="scenario2List !== undefined && scenario2List.length > 1">
            <igx-input-group #scenario2Group [igxToggleAction]="scenario2Dd" displayDensity="compact">
                <igx-prefix style="width: 150px;">&nbsp;Scenario 2 Name: </igx-prefix>
                <input #scenario2Input style="width: 250px;" type="text" igxInput [igxDropDownItemNavigation]="scenario2Dd" readonly="true" placeholder="Pick a Scenario (2)" [value]="scenario2Dd.selectedItem?.value" (keydown.ArrowDown)="openDropDown('scenario2')" />
                <igx-suffix igxButton="icon" class="dropdownToggleButton" igxRipple>
                    <igx-icon>arrow_drop{{ scenario2Dd.collapsed ? '_down' : '_up' }}</igx-icon>
                </igx-suffix>
            </igx-input-group>
            <igx-drop-down #scenario2Dd (onSelection)="setScenario($event, 2)" displayDensity="compact">
                <div class="scrollable">
                    <igx-drop-down-item [selected]="true" [value]="">Choose a Scenario</igx-drop-down-item>
                    <igx-drop-down-item *ngFor="let scen of scenario2List" [value]="scen.name">{{scen.name}}</igx-drop-down-item>
                </div>
            </igx-drop-down>
        </div>

They are gated by a similarly implemented Scenario Type dropdown (each), which I have no issue with. There are other controls for filtering the horizon, type of products, and facilities produced, none of which have issues until 2 scenarios which don't match are selected. In fact, every dropdown (and combobox for facilities) throws the above error when the scenarios chosen do not match.

setScenario is implemented like this:

  setScenario(e:any, scen:number) {
    if (e.oldSelection == null || e.oldSelection.value !== e.newSelection.value) {
      if (scen == 1) { this.scenario1 = this.scenario1List.filter(s => s.name == e.newSelection.value)[0]; }
      else if (scen == 2) { this.scenario2 = this.scenario1List.filter(s => s.name == e.newSelection.value)[0]; }
    }

    if (this.scenario1 !== undefined && this.scenario2 !== undefined) {
      this.getFacilities();
      this.getWorkweeks();
      this.getCompareData();
    }
  };

getFacilities filters down to the unique set of facilities represented in both scenarios, and works perfectly.

getWorkweeks gives the full horizon represented by the 2 scenarios (earliest WW of the 2 through the latest WW of the 2), and works perfectly.

getCompareData parses the return from the back-end and puts it into a good form for all the filters, chosen horizon, and selected rollup (WW, month, quarter), and all of these work perfectly, when the scenarios match.

There is a Calculate button which sends the data to be filtered and rolled-up, which also works perfectly when the 2 scenarios match.

  • 935
    Verified Answer
    Offline posted

    I figured it out, but I'm annoyed with the result.

    I was previously using a combination of functions to filter duplicate facilities from the concatenated list between scenario 1 and scenario 2. Unfortunately, using ```delete array[index];" doesn't fully remove that index from the array in TypeScript. I am forced to build a unique list by iterating through both of the returned lists, unless one of you has a better idea.

    Here is my current functionality:

      async getFacilities() {
        this.facilities = [], this.selectedFacilities = [];
        let a:idName[] = await this.scenarioService.getFacilities(this.scenario1.id).toPromise(),
          b:idName[] = await this.scenarioService.getFacilities(this.scenario2.id).toPromise(),
          c:idName[] = [];
        if (this.scenario1.name == this.scenario2.name) { this.facilities = a; }
        else {
          a.forEach(f => c.push(f));
          b.forEach(f => { if (c.findIndex(d => d.name == f.name) < 0) { c.push(f); } });
        }
        this.facilities = c, this.selectedFacilities = c;
      };
    

    For conciseness, I would prefer to have something more like the below, without the array returned having empty indices:

      async getFacilities() {
        this.facilities = [], this.selectedFacilities = [];
        let a = await this.scenarioService.getFacilities(this.scenario1.id).toPromise(),
          b = await this.scenarioService.getFacilities(this.scenario2.id).toPromise();
        this.facilities = a.concat(b);
        if (this.scenario1.name == this.scenario2.name) { this.facilities = a; }
        else { for (let i = this.facilities.length - 1; i >= 0; i--) { if (this.facilities.findIndex(f => this.facilities[i].name == f.name) < i) { delete this.facilities[i]}; } }
        this.selectedFacilities = this.facilities;
      };
    

    If you have a suggestion, that would be appreciated. Here is the implementation of Facilities combo for reference:

            <div *ngIf="facilities !== undefined && facilities !== [] && selectedFacilities !== undefined && selectedFacilities !== []">
                <igx-combo id="facFilter" [width]="'200'" displayDensity="compact" [(ngModel)]="selectedFacilities" [displayKey]="'name'" [data]="facilities" [igxFocus]="true" width="150px" placeholder="ALL (click to filter)" (onSelectionChange)="updateSelectedFacilities($event)"></igx-combo>
            </div>