Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
196 views
in Technique[技术] by (71.8m points)

typescript - Angular Abstracts & Data Mutations

I am stuck with a fairly weird bug? which relates to a component based on an abstract class (or so is my guess).

So there are multiple sibling components which are rendered based on an array length with an *ngFor. The siblings (based on an abstract class) get their data via @Input properties, then handle the data in their ways and display it. So far so good. ChangeDetectionStrategy.OnPush ftw, etc. However as soon as I hover over one of the components, the data mutates on-the-fly (I have no other explanation or correct term for it) and is being reset to the data of the last sibling within that template.

<Router-outlet>
  <ParentComponent>
    *ngFor
    <Sibling1>
      <ChildComponentA>
      <ChildComponentB>
    <Sibling2>
      <ChildComponentA>
      <ChildComponentB>
    <SiblingN>
      <ChildComponentA>
      <ChildComponentB>

I've breakpointed every possible line of the code - everything is set correctly. But as soon as I hover over the component, I believe the change detection kicks in and takes the data from the last sibling and overwrites every other sibling. Not deep, mind you! The children of the siblings are still correct and display everything as is. But the template of that hovered sibling component is corrupted. I am truly lost. I've used [...array] and array.slice() and what not to make sure that the arrays are unique. Nothing has helped so far.

Here is a sample (the code is fairly complicated to just dump it here).

parent.component.html

<ng-container *ngIf="v === 'user'">
    <div *ngFor="let e of employees">

        <div>
            <h3>{{ e | name }}</h3>
        </div>
        
        <ng-container *ngTemplateOutlet="days; context: { e: e }"></ng-container>

    </div>
</ng-container>

<ng-template #days let-l="l" let-e="e">
    <div>
        <sibling
            [weeks]="weeks"
            [viewMode]="v"
            [loc]="l"
            [emp]="e"
            [realDates]="realDates"></sibling>
    </div>
</ng-template>

Here is the sibling.component.html

    <div *ngFor="let day of selectedWeek;">
        <div>
            <i *ngIf="viewMode == 'location'"
                class="ico"
                [ngClass]="{
                    'i-x-o': !day.isOpenOnDay && day.isSpecialDay,
                    'i-day-time': day.isOpenOnDay,
                    'is-special': day.isSpecialDay
                }"></i>
            <childA></childA>
        </div>

        <div>
            <childB [day]="day"></childB>
        </div>

    </div>

<childB> stays put and displays the data of day alright. But as as soon as I hover over childA or childB or even that <i> with icon classes - the day object from the last sibling is used. The selectedWeek in the sibling component is an array derived from weeks input, then manipulated, sliced and spread and what not.

  • parentComponent: ChangeDetectionStrategy.Default
  • sibling: ChangeDetectionStrategy.OnPush
  • childA: ChangeDetectionStrategy.Default
  • childB: ChangeDetectionStrategy.OnPush
question from:https://stackoverflow.com/questions/66067585/angular-abstracts-data-mutations

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

For anyone wondering: the solution was to convert the variable selectedWeek into function. After that everything goes as it was meant to. So in sibling.component.html:

<div *ngFor="let day of selectedWeek()">
    <div>
        <i *ngIf="viewMode == 'location'"
            class="ico"
            [ngClass]="{
                'i-x-o': !day.isOpenOnDay && day.isSpecialDay,
                'i-day-time': day.isOpenOnDay,
                'is-special': day.isSpecialDay
            }"></i>
        <childA></childA>
    </div>

    <div>
        <childB [day]="day"></childB>
    </div>

</div>

and then in the sibling.component.ts

public function selectedWeek(): Array<any> {
  // do stuff, return an array
}

I still haven't figured out the reason why a variable wouldn't work.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...