Skip to content

Virtual scroll destroying rendered components leads to tangling event emitters #12036

@masimplo

Description

@masimplo

Ionic version: (check one with "x")
[ ] 1.x (For Ionic 1.x issues, please use https://github.com/ionic-team/ionic-v1)
[ ] 2.x
[X] 3.x

I'm submitting a ... (check one with "x")
[X] bug report
[ ] feature request
[ ] support request => Please do not submit support requests here, use one of these channels: https://forum.ionicframework.com/ or http://ionicworldwide.herokuapp.com/

Current behavior:
Rendered component output event emitters stop working after Virtual scroll data is changed, since components are destroyed.

Expected behavior:
Rendered component output event emitters should always work.

Steps to reproduce:
Say have a component rendered inside the VirtualScroll that has and @output event emitter to pass some value back to the VS hosting component.

so something like:

<ion-list [virtualScroll]="items">
    <div class="full-width" *virtualItem="let item">
      <custom-comp [myItem]="item" (myOutput)="doSomethingImportant($event)"></custom-comp>
    </div>
  </ion-list>

Now imagine that custom-comp when clicked opens a modal to get user input (e.g. star rating) that wants to return it through myOutput event emitter.

rate(){
    let modal = this._modal.create(RatingModal, {
      rating: rating
    });
    modal.onDidDismiss(data => {
      doWork();
      this.myOutput.emit(data.rating);
    });
    return modal.present();
}

This works fine and dandy. BUT, if the user keeps the rating modal long enough for a change to happen to our data bound to virtual scroll (i.e. a value of a different item changes), VS will destroy and recreate all rendered components.

Now if the user selects a rating and submits, modal.onDidDismiss will be triggered fine (although the component has been destroyed, but we didn't take care of cleaning up event handlers, so it will happen to work so far) BUT nobody listens to myOutput eventEmitter anymore so the event will be lost.

And here is a plunker demonstrating exactly this behaviour (with an alert instead of a modal, but concept still stands)
http://plnkr.co/edit/VJlmRht46koPFKwp8VMQ?p=preview
Run the plnkr a list is rendered, quickly (within 5 secs) click on a number larger than 3. Within 5 sec of starting the list is changed (items 1 and 2 are filtered out) and an alert is produced that you can now choose a rating (good or bad). Close the alert and click on a rating. In the console the emitting event is logged, the receiving is not. In order to confirm rate another item now, both logs are now logged since data did not change while the alert was open.

Other information:

This is related to #12035 but has different side effects. Solving #12035 does not necessarily mean this will be solved as well, depending on the solution.

Ionic info: (run ionic info from a terminal/cmd prompt and paste output below):

global packages:

    @ionic/cli-utils : 1.4.0
    Cordova CLI      : 7.0.1
    Ionic CLI        : 3.4.0

local packages:

    @ionic/app-scripts              : 1.3.7
    @ionic/cli-plugin-cordova       : 1.4.0
    @ionic/cli-plugin-ionic-angular : 1.3.1
    Cordova Platforms               : android 6.2.3
    Ionic Framework                 : ionic-angular 3.3.0

System:

    Node       : v7.10.0
    OS         : macOS Sierra
    Xcode      : Xcode 8.3.3 Build version 8E3004b
    ios-deploy : not installed
    ios-sim    : not installed
    npm        : 5.0.3```

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions