Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cdk-virtual-scroll-viewport): emit events when cached templates are added/removed from the DOM #21742

Closed
splincode opened this issue Jan 29, 2021 · 9 comments
Assignees
Labels
area: cdk/scrolling feature This issue represents a new feature or feature request rather than a bug or bug fix

Comments

@splincode
Copy link

splincode commented Jan 29, 2021

Reproduction

Use StackBlitz to reproduce your issue:

Steps to reproduce:

  1. Delete element by delete button
  2. Show console -> do not see the deletion message

I have directive which shows tooltips

@Directive({ selector: "[tooltip]" })
export class TooltipDirective implements OnDestroy {
  public id =
    "_" +
    Math.random()
      .toString(36)
      .substr(2, 9);

  public ngOnInit() {
    console.log("ngOnInit", this.id);
  }

  public ngOnDestroy() {
    // not working when removed element (also remove from model)
    console.log("ngOnDestroy", this.id);
  }
}

but when I delete element, the cache is no longer needed and is not relevant, because I deleted the element from the model, which means the ngOnDestroy method should work

<cdk-virtual-scroll-viewport
  minBufferPx="200"
  maxBufferPx="200"
  [itemSize]="24"
  [style.height.px]="200"
>
  <ng-container *cdkVirtualFor="let favorite of favorites">
    <ng-template
      [ngTemplateOutlet]="virtualRef"
      [ngTemplateOutletContext]="{ $implicit: favorite }"
    >
    </ng-template>
  </ng-container>
</cdk-virtual-scroll-viewport>

<ng-template #virtualRef let-favorite>
  <div class="favorite-line" tooltip="hello world">
    {{ favorite.title }}

    <button (click)="remove(favorite)">delete</button>
  </div>
</ng-template>
  public remove(favorite: Favorite): void {
    this.favorites = this.favorites.filter(
      (item: Favorite): boolean => item.id !== favorite.id
    );
  }

Expected Behavior

What behavior were you expecting to see?

When deleting a model, a template with an inactive model should not be cached, since this model no longer exists

Actual Behavior

What behavior did you actually see?

Workaround to use templateCacheSize: 0, but this is not a solution to the problem, because we are working with heavy templates that need to be cached.

The ngOnDestroy method is not called, although we removed an element from the array

Environment

  • Angular: latest
  • CDK/Material: latest
  • Browser(s): any
  • Operating System (e.g. Windows, macOS, Ubuntu): any
@crisbeto
Copy link
Member

crisbeto commented Feb 1, 2021

As far as I can tell, this is working as expected. When a view is scrolled out of the viewport, we detach it and we put it in the cache. Since it can be re-attached, it won't invoke ngOnDestroy. There's also no way for the _ViewRepeater to know whether a removal happened because the user scrolled it out of view or deleted it another way so both are treated equally. Assigning to @mmalerba to confirm.

@crisbeto crisbeto added area: cdk/scrolling and removed needs triage This issue needs to be triaged by the team labels Feb 1, 2021
@mmalerba
Copy link
Contributor

mmalerba commented Feb 1, 2021

Yeah this is working as intended. The ngOnDestroy method will eventually be called, either when it's pushed out of the cache or when the viewport is destroyed. One thing we could maybe look into in the future is adding some kind of @Output or separate directive to listen to attach/detach events

@maxcalderon1997
Copy link

i also have the exact same problem. is there a workaround without using cachesize 0?

@mmalerba
Copy link
Contributor

No, as mentioned in the comment above, we would need a new API to emit events at the appropriate time

@mmalerba mmalerba added the feature This issue represents a new feature or feature request rather than a bug or bug fix label Feb 16, 2021
@mmalerba mmalerba changed the title bug(cdk-virtual-scroll-viewport): ngOnDestroy is not called on elements that have already been removed from the model feat(cdk-virtual-scroll-viewport): emit events when cached templates are added/removed from the DOM Feb 16, 2021
@maxcalderon1997
Copy link

will there be a way to know if an element was detached because of scrolling or because it was deleted by the user?

@maxcalderon1997
Copy link

there should be an option to destroy a specific item instead of caching

@de-don
Copy link

de-don commented Apr 29, 2021

I have the same issue.

I think it would be cool to be able to delete the cache for a specific element by key from trackBy:

public removeElement(item) {
  // HERE IS REMOVING LOGIC
  // ...
  this.cdkVirtualScrollViewport.clearItemCache(item.id);
}

@angular-robot
Copy link
Contributor

angular-robot bot commented Mar 13, 2022

Just a heads up that we kicked off a community voting process for your feature request. There are 20 days until the voting process ends.

Find more details about Angular's feature request process in our documentation.

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Apr 13, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: cdk/scrolling feature This issue represents a new feature or feature request rather than a bug or bug fix
Projects
None yet
Development

No branches or pull requests

5 participants