NativeScript / nativescript-angular

Integrating NativeScript with Angular
http://docs.nativescript.org/angular/tutorial/ng-chapter-0
Apache License 2.0
1.21k stars 241 forks source link

Listview delete element issue. #683

Open tsonevn opened 7 years ago

tsonevn commented 7 years ago

From @abdumama on February 25, 2017 14:7

Hi to all, I'm using Nativescript (angular2 / typescript) to create a mobile application, and I have found a problem when I use the ListView widget.

listview

I have an ObservableArray with the data, and I'm trying to remove the first element of the list with an animation:

viewElement.animate({ translate: { x: 200, y: 0 }, duration: 500 }).then(() => { this.requestPreviewList.splice(this.requestPreviewList.indexOf(request), 1); });

The removal is carried out correctly, but as you can see from the pictures the second list item inheritance the animation properties.

listview_err

UPDATE:

Here you can download a simple project where you can reproduce the issue. ListViewBug.zip

Version:

Copied from original issue: NativeScript/NativeScript#3709

tsonevn commented 7 years ago

Hi @abdumama, Thank you for reporting this issue.

I reviewed your sample project and unfortunately, I have to confirm that this is a real issue while using ListView with animations in NativeScript Angular 2 project.

For further info, you could keep track on the issue.

In the meantime, you could use nativescript-telerik-ui plugin and its RadListView component, which has itemDeleteAnimation property. You could use some of the available animations: Fade, Scale or Slide.

For further help, you could also review the documentation and the sample project here.

Hope this helps

ghost commented 7 years ago

Hi @tsonevn,

I don't think that the problem is the animation, but it is the remove operation. I say this because I have done another scenario (without animation) and I have found the same issue ( The second element of the listview inheritance the properties of the first element).

I have changed the ListViewBug project and now the template of the listview has a button that shows a collapsed layout.

These are the steps to reproduce the issue:

1) Click on the button of the first element to make visibile the layout.

image

2) Now you can remove the first element (tap on it).

image

As you can see, the second element of the listview after the remove has the layout visible!

ListViewBug (No Animation).zip

tsonevn commented 7 years ago

Hi @abdumama,

This case could be caused due to an issue with reusing the container in the ListView template, which will lead to this behavior with animations of the item and setup of some of the container's child's properties. In the meantime, you could reset the default property value when you remove the item from the ListView.

At that point, something that I notice in the same you are using the same id for all components in the inner StackLayout. The id for the inner container should be unique. You could review the below-attached example for both suggestions: use of unique id and workaround with property value reset.

import { Component } from "@angular/core";
import { ObservableArray } from "data/observable-array";
import { StackLayout } from "ui/layouts/stack-layout";
import {Page} from "ui/page"

@Component({
  selector: "my-app",
  template: `
    <ListView [items]="myItems" (itemTap)="onItemTap($event)">
      <template let-item="item">
          <StackLayout>
              <Label [text]='item.title'></Label>
              <Label style="margin:16" text="Click Here" ></Label>
              <StackLayout [id]="item.id" visibility="collapsed">
                  <Label text='Here the BUG'></Label>
              </StackLayout>
          </StackLayout>
      </template>
    </ListView>
  `
})

export class AppComponent {

  private myItems = new ObservableArray();

  constructor(private page:Page) {
    this.myItems.push({title:"Test1", id:"item0"});
    this.myItems.push({title:"Test2", id:"item1"});
  }

  public onItemTap(event) {

      console.log(event.view);
      var layout:StackLayout = <StackLayout>this.page.getViewById("item"+event.index);
      console.log(layout);
      layout.visibility = "visible";
      setTimeout(()=>{
        this.myItems.splice(event.index, 1);
      }, 2000);
      layout.visibility = "collapse";
  }
ghost commented 7 years ago

Hi @tsonevn, Yes, it's correct.. the id must be unique! :) Your workaround works, but in this example the template of the listview is simple.. my actual case is far more complex, so I need to do more checks in the code.

Thanks for the help!