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

Header Entry not clickable in RadListView grouping function #973

Closed
tsonevn opened this issue Dec 24, 2018 · 8 comments
Closed

Header Entry not clickable in RadListView grouping function #973

tsonevn opened this issue Dec 24, 2018 · 8 comments

Comments

@tsonevn
Copy link

tsonevn commented Dec 24, 2018

From @NL33 on December 23, 2018 1:46

Environment

  • CLI: 5.0.1
  • Cross-platform modules: 5.0.1
  • Android Runtime: N/A
  • iOS Runtime: 5.0.0
  • Plugin(s): nativescript-ui-listview (downloaded Dec 10, 2018)

Describe the bug
In a basic two-level list, where there are category headers and entries below, there is not a way to catch a click on the category header (at least in iOS).

There should not be a place on the screen (especially in a basic+common UI like a list) where there is no way to watch (and isolate) a user click event.

For example, take a basic list of countries and cities as follows:

US
--New York
--Los Angeles
--Chicago

Canada
--Calgary
--Toronto

England
--London

The headers (the countries) should be clickable.

The common way to create such a list in Nativescript is using RadListView's grouping function, described here. However, the grouping function "hides" the group header from html, so there is not a clear way to attach a tap event to it.

Other methods would include to create a two level loop using *ngFor, but *ngFor is reportedly not stable for larger lists. Another method would be to have a two level (ie, nested) listview, but that is also reported to be unstable/non-performant.

To Reproduce

Simple code would be:

html:

<GridLayout>
    <RadListView [items]="places"  [groupingFunction]="myGroupingFunc" (tap)="groupTapped()">  
        <ng-template tkListItemTemplate let-place="item" >
            <StackLayout>
                <Label [text]="place.city"></Label>
              </StackLayout>
          </ng-template>
      </RadListView>
  </GridLayout>

ts:

public places = [
         {country: 'US', city: 'New York'}, 
         {country: 'US', city: 'Los Angeles' },     
         {country: 'Canada', city: 'Toronto'},
         {country: 'England', city: 'London'},
         {country: 'US', city: 'Chicago'},
         {country: 'Canada', city: 'Calgary'}      
 ]
...
myGroupingFunc(value) {
      return value.country;
 }

groupTapped(){
/*will fire whenever anywhere in group is tapped*/
}

The groupTapped() function here will register a tap on anywhere in the group--it will not tell you if the user has clicked on a category header.

Expected behavior

With a basic list, like as follows:

US
--New York
--Los Angeles
--Chicago

Canada
--Calgary
--Toronto

England
--London

There should be a way to register if the user taps on a category header (here, a country).

Sample project
N/A

Additional context
There are questions about this issue on stackoverflow here and here.

There is also an issue on github here, as well as the NS slack channel.

There are no answers provided to these, so I'm assuming that currently Nativescript does not provide a method for this basic operation (though I would still be happy if this is incorrect and there is a way, and maybe a pretty simple one!).

Copied from original issue: NativeScript/NativeScript#6734

@tsonevn
Copy link
Author

tsonevn commented Dec 24, 2018

Duplicate of #895

@tsonevn tsonevn marked this as a duplicate of #895 Dec 24, 2018
@tsonevn tsonevn closed this as completed Dec 24, 2018
@NL33
Copy link

NL33 commented Dec 24, 2018

@tsonevn this is not a duplicate of #895. That issue is about toggling visibility--this is not about that at all. This is about simply being able to catch a click on header entries.

I have separately asked about accordion style lists here, but this issue is about an even more basic function--just being able to catch a click on a crucial part of the list.

I have seen @NickIliev discuss similar items before, but never this directly.

Please do not close this issue without a response. Is it indeed not possible in Nativescript (iOS) to have header entries in a list and to be able to catch when the user clicks on a header entry?

@tsonevn
Copy link
Author

tsonevn commented Dec 28, 2018

Hi @tsonevn,
Excuse me for the delayed reply.
I tested the scenario with the tap event for the header of each category header, and this functionality seems to work as expected on my side. I tested this scenario with the example here. The only change I made in the sample is to set up the tap event for the GridLayout used for a primary container of the headers. For example:
HTML

<ng-template tkGroupTemplate let-category="category">
            <GridLayout id="{{category}}" (tap)="onHeaderTap($event)" ios:height="50">
                <Label class="nameLabel" [text]="category" class="groupLabel"></Label>
            </GridLayout>
        </ng-template>

TypeScript

 public onHeaderTap(args){
        console.log("onHeaderTap");
        console.log(args.object.get("id"))
    }

Regarding the issue #895, that I have mentioned in my previous comment. Currently, there is missing functionality for iOS which prevents from implementing togging visibility functionality of the items in the group. Because of that, I marked this issue as duplicated.
Let me know if I am missing something.

@NL33
Copy link

NL33 commented Dec 28, 2018

Thank you. I am able to have a working version now. Looks like the key missing pieces are (1) the tkGroupTemplate, and (2) that you have to have to have a separate ng-template that (strangely) appears AFTER the items. (its strange b/c in the code the header piece appears after the list items, but the result is the header appearing above the list items).

I was not able to find documentation on tkGroupTemplate. Is it production ready?

I also noticed some weird behavior. For example, things seem to work well when I include the ios:height="50" in the code like you have. When I don't include that, the list items start getting messed up, with some pieces not showing on the screen. I am hoping there is documentation that can explain items such as the "ios:height" and why it is essential. This is especially important in case there are other weird quirks about tkGroupTemplate that come up.

@tsonevn
Copy link
Author

tsonevn commented Dec 31, 2018

Hi @NL33,
I have updated the docs. The example with the tkGroupTemplate can be found here.
Regarding the ios:height set up in the sample app, I will check what is the behaviour without the specifying the height and whether there is an issue with the component.

@NL33
Copy link

NL33 commented Dec 31, 2018

Thanks, very helpful. In terms of the weird behavior I found: there were two things:

  1. When the list entries had several attributes--without the ios:height item, the first list entry would get covered up by the category entry.

Here's a quick example:
ts:

public places = [
         {country: 'US', city: 'New York', description: 'Big Apple"}, 
         {country: 'US', city: 'Los Angeles', description: 'Out West" },     
         {country: 'Canada', city: 'Toronto', description: 'Cooler'},
         {country: 'England', city: 'London', description: 'British'},
         {country: 'Canada', city: 'Calgary', description: 'Also cooler'}      
 ]

myGroupingFunc(value) {
   return value.country;
}

html:

<GridLayout>
    <RadListView [items]="places" [groupingFunction]="myGroupingFunc">
        <ng-template tkListItemTemplate let-place="item">
            <StackLayout>
                <Label [text]="place.city" (tap)="listEntryTap(place.city)"></Label>
                <Label [text]="place.description"></Label>          
            </StackLayout>
        </ng-template>
        <ng-template tkGroupTemplate let-country="category">
            <StackLayout >
                <Label [text]="country" (tap)="headerTap(country)"></Label>
            </StackLayout>
        </ng-template>
    </RadListView>
</GridLayout>

So, no ios:Height item.

Result I found: (Country header hides the first city entry):

-Canada
     ---Cooler
  -- Calgary
    --- Also Cooler

-England
     ---British

-US
      ---Big Apple
  -- Los Angeles
      ---Out West
  1. If for the header, I used a <Button> instead of a <Label>, like:
<ng-template tkGroupTemplate let-country="category">
          <StackLayout >
              <Button [text]="country" (tap)="headerTap(country)"></Button>
          </StackLayout>
      </ng-template>

The formatting would be come buggy--for example, adding large white space in the middle of the screen and having some of the categories overlap.

@NL33
Copy link

NL33 commented Jan 6, 2019

@tsonevn while I am grateful to have figured out the click on category headers item, I have found my list to be persistently jerky when scrolling using RadListView. This is using iOS and Angular, and it is especially obvious when testing on my phone.

When I take the exact same code+data, but instead of RadListView, I use *ngFor inside , the list functions perfectly and is very smooth scrolling.

I have commented on this issue, which discusses that RadListView often turns out to be jerky on scroll. Is it still the case that RadListView has some problems in terms of smooth scrolling? Anything I can do to improve scroll performance?

If there is not a way to improve scroll performance, I believe I will have to use *ngFor for my lists instead.

@NL33
Copy link

NL33 commented Jan 8, 2019

I have opened up a new issue regarding RLV's lack of smooth scrolling here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants