Akita: Removing item in ngFor causes view failure reading property

Created on 22 Jul 2019  路  6Comments  路  Source: datorama/akita

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ X ] Bug report  
[ ] Performance issue
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request
[ ] Other... Please describe:

Current behavior

Currently I'm using normalizr to break apart my data, and then using a QueryEntity to put it back together. This works fine for updates, but removing an item from the store doesn't seem to delete the nested object entirely, resulting in an error in my template from accessing a property on a null object.

QueryEntity

selectObjectives(): Observable<Objective[]> {
  return combineQueries([
    this.selectAll(),
    this.keyResultQuery.selectAll({ asObject: true }),
    this.taskQuery.selectAll({ asObject: true })
  ])
    .pipe(
      map(([objectivesQ, keyResultsQ, taskResultsQ]) => objectivesQ.map(objective => {
        return {
          ...objective,
          keyResults: objective.keyResults.map(keyResultId => {
            // @ts-ignore -- type-safety breaks here
            const keyResult = keyResultsQ[keyResultId];
            if (!keyResult) { return; }
            return {
              ...keyResult,
              // @ts-ignore -- type-safety breaks here
              tasks: keyResultsQ[keyResultId].tasks.map(taskId => taskResultsQ[taskId])
            };
          })
        };
      })
      )
    );
}

View

<div *ngFor="let keyResult of objective.keyResults" (click)="deleteKeyResult(keyResult)">
  {{keyResult.description}}  <-- error reading this property after remove
</div>

Calling Remove on an item in the ngFor causes the page to fail trying to read the description property off of keyResult(which no longer exists). It seems like the item still exists in some form on the objective.keyResults property.

If I don't reference a property, the item is removed from the view as expected, and no error occurs.

<div *ngFor="let keyResult of objective.keyResults" (click)="deleteKeyResult(keyResult)">
    {{keyResult}} <--- no more error here when removed
</div>

It seems like the item is re-rendered momentarily, and tries to read a prop on a non-existent entity.

Expected behavior

Deleting an item should remove it from the ngFor loop

Most helpful comment

All 6 comments

Can you share the delete method, please?

Certainly. This is early testing, so I'm just removing it directly from the store.

deleteKeyResult(keyResult) {
  this.keyResultStore.remove(keyResult.id);
}

You removed only the keyResultStore part. You also need to remove the id reference from the objectivesQ store:

objective.keyResults.map() <===== still exists here

facepalm It's always obvious when someone points it out. Thank you for the quick help!

No problem. You're welcome to join Akita's Gitter channel for any further questions.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

NetanelBasal picture NetanelBasal  路  6Comments

adraax picture adraax  路  4Comments

twittwer picture twittwer  路  7Comments

hoisel picture hoisel  路  5Comments

amr-alamir picture amr-alamir  路  6Comments