RadListView Flex with Keyboard

Thread is closed for posting
15 posts, 0 answers
  1. Ericky
    Ericky avatar
    49 posts
    Member since:
    Jun 2017

    Posted 23 Jun 2017 Link to this post

    I'm not sure if this is the right place to be asking this question, but I don't know where else to ask.

    I have a chat view which when I click on the text box at the bottom, the listview is pushed up together with the whole page. Is there any way to make the list responsive to the keyboard and not push the top bar up when the keyboard appears?

    The top bar is a custom element, it's not the actionbar.

     

    https://prnt.sc/fn4vp8

    https://prnt.sc/fn4vui

  2. Nikolay Tsonev
    Admin
    Nikolay Tsonev avatar
    340 posts

    Posted 23 Jun 2017 Link to this post

    Hi,
    I tested this scenario on my side while using very basic project with Label RadListView and TextField which are nested inside a GridLayout, however, when the Field is focused only this component has been moved up and the custom element and ListView keep in the same position.

    For your convenience, I am attaching a screenshot from the simulator and the test project.
    Regards,
    nikolay.tsonev
    Progress Telerik
    Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
  3. Ericky
    Ericky avatar
    49 posts
    Member since:
    Jun 2017

    Posted 23 Jun 2017 Link to this post

    Hello Nikolay,

    This is how I have my project setup.

    <GridLayout>
      <GridLayout>
        <StackLayout id="application" orientation="vertical">
          <ink-actionbar></ink-actionbar>
          <router-outlet name="sublayoutoutlet"></router-outlet>
        </StackLayout>
      </GridLayout>
      <ink-loading></ink-loading>
    </GridLayout>
    <StackLayout id="messages-view" orientation="vertical">
      <GridLayout rows="*, auto">
        <RadListView #radListView class="messages-list" [items]="messages" row="0" col="0" backgroundColor="transparent" (itemLoading)="onItemLoading($event)"
          pullToRefresh="true" (pullToRefreshInitiated)="onPullToRefreshInitiated($event)">
          <ListViewStaggeredLayout tkListViewLayout spanCount="1"></ListViewStaggeredLayout>
          <ng-template tkListItemTemplate let-item="item" let-i="index">
            <DockLayout [stretchLastChild]=false>
              <Label dock="top" class="display-date" [class.no-text]="!item.displayDate" [text]="item.displayDate"></Label>
              <TextView [dock]="item.isMe ? 'right' : 'left'" row="1" col="0" class="message" [class.me]="item.isMe"
                [class.last]="messages.length - 1 === i" [text]="item.text" [editable]=false [isUserInteractionEnabled]=false></TextView>
            </DockLayout>
          </ng-template>
        </RadListView>
     
        <GridLayout class="message-input" rows="auto" columns="*, auto" row="1" col="0">
          <StackLayout>
            <TextView #messageInput hint="Message Text" [(ngModel)]="messageBody" (ngModelChange)="messageBodyChanged($event)"></TextView>
          </StackLayout>
          <Button row="0" col="1" class="send-button" [class.disabled]="sendDisabled" text="Send" verticalAlignment="center" (tap)="sendMessage(messageBody)"></Button>
        </GridLayout>
      </GridLayout>
    </StackLayout>
  4. Ericky
    Ericky avatar
    49 posts
    Member since:
    Jun 2017

    Posted 23 Jun 2017 Link to this post

    I also tried to do the same type of layout as in your sample project and it still didn't work.

    <GridLayout id="application" rows="auto, *, auto">
      <StackLayout>
        <ink-actionbar></ink-actionbar>
      </StackLayout>
      <router-outlet name="sublayoutoutlet"></router-outlet>
    </GridLayout>
    <GridLayout row="1">
      <RadListView row="1" #radListView class="messages-list" [items]="messages" row="0" col="0" backgroundColor="transparent" (itemLoading)="onItemLoading($event)"
        pullToRefresh="true" (pullToRefreshInitiated)="onPullToRefreshInitiated($event)">
        <ListViewStaggeredLayout tkListViewLayout spanCount="1"></ListViewStaggeredLayout>
        <ng-template tkListItemTemplate let-item="item" let-i="index">
          <DockLayout [stretchLastChild]=false>
            <Label dock="top" class="display-date" [class.no-text]="!item.displayDate" [text]="item.displayDate"></Label>
            <TextView [dock]="item.isMe ? 'right' : 'left'" row="1" col="0" class="message" [class.me]="item.isMe"
              [class.last]="messages.length - 1 === i" [text]="item.text" [editable]=false [isUserInteractionEnabled]=false></TextView>
          </DockLayout>
        </ng-template>
      </RadListView>
    </GridLayout>
    <TextView row="2" #messageInput hint="Message Text" [(ngModel)]="messageBody" (ngModelChange)="messageBodyChanged($event)"></TextView>
  5. Nikolay Iliev
    Admin
    Nikolay Iliev avatar
    351 posts

    Posted 26 Jun 2017 Link to this post

    Hello Ericky,

    Based on the application send my colleague Nikolay Y cone you can further simplify your Angular based layout. In your case you are using DockLayout inside the item template - you can use Grid or Stack and accommodate the l9ogic just as shown in the sample applcationOne important thing to do to explicitly set both rows and then row and col on every element to avoid miss interpretation.
    e.g. basic example is demonstrating the technique with the explicit setting of rows and row and without using dock layout.
    <GridLayout rows="500, 100"  tkExampleTitle tkToggleNavButton>
     
        <RadListView row="0" [items]="dataItems">
            <ng-template tkListItemTemplate let-item="item">
                <StackLayout orientation="vertical">
                    <Label class="nameLabel" [text]="item.name"></Label>
                    <Label class="descriptionLabel" [text]="item.description"></Label>
                </StackLayout>
            </ng-template>
        </RadListView>
     
        <TextView row="1" [(ngModel)]="tvtext" hint="Enter some text" class="input input-border"></TextView>
         
    </GridLayout>
    In the example above I have tested the TextView and the RadListView in a single GridLayout and when the kkeyboard gets focus it is not pushing the whole listview but as expected is only hiding the content.

    Regards,
    Nikolay Iliev
    Progress Telerik
    Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
  6. Ericky
    Ericky avatar
    49 posts
    Member since:
    Jun 2017

    Posted 26 Jun 2017 Link to this post

    Thanks for the response, Nikolay, but I was still not able to solve the problem.

    I wasn't able to reproduce the errors in a fresh new app, but I continue to get the same error in my current project.
    Based on the testing I did, I believe it has something to do with the page element not being initialized properly with the list view, but I'm not sure.

    From this video, you can see how the first time I navigate to the component outlet, it is bugged, but if I scroll all the way up on the list then it will be un-bugged for next times.

    One more insight is that if I use

    { path: '', pathMatch: 'full', redirectTo: '/sublayout/(sublayoutoutlet:messages/95/126)', }

    instead of

    { path: '', pathMatch: 'full', redirectTo: '/layout/(layoutoutlet:dashboard)', }

    then the list works as expected.

    Here's the type of routing I am using: (Messages outlet is the one with the list-view)

    { path: '', pathMatch: 'full', redirectTo: '/layout/(layoutoutlet:dashboard)', },
    { path: 'layout', component: LayoutComponent, canActivate: [AuthGuard], children: [
      { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard], outlet: 'layoutoutlet' }
    ]},
    { path: 'sublayout', component: SubLayoutComponent, canActivate: [AuthGuard], children: [
      { path: 'messages/:my_card_id/:other_card_id', component: MessageViewComponent, canActivate: [AuthGuard], outlet: 'sublayoutoutlet' }
    ]}
  7. Ericky
    Ericky avatar
    49 posts
    Member since:
    Jun 2017

    Posted 26 Jun 2017 Link to this post

    Actually, I was able to reproduce the error in a sample project. Still don't know exactly what causes it though.

     

    Video Link of bug in Sample Project

    Sample Project Link

  8. Nikolay Iliev
    Admin
    Nikolay Iliev avatar
    351 posts

    Posted 27 Jun 2017 Link to this post

    Hi Ericky,

    The reason for your issue is the way you have structured your application using nested router-outlet. When you load the content of the router-outlet you are working with all the layouts that are contained within this outlet. So when the TextView requires the focus and the keyboard appears it will push all the content loaded in the outlet. If you want to dock the button and to prevent the keyboard from pushing the button and the listview then all you need to do is to place the docked button on a level with your router-outlet as done here.

    Based on the test application you have sent in your last post here is the changes I have made to make it work.
    test.html
    <StackLayout  backgrundColor="green">
        <Button text="Go back" [nsRouterLink]="['/main', { outlets: { outlet: ['test']}}]"></Button>
        <router-outlet name="outlet"></router-outlet>
    </StackLayout>

    test-inner.html
    <GridLayout rows="*, auto" columns="">>
      <GridLayout row="0" backgroundColor="blue">
        <RadListView [items]="dataItems">
          <ListViewLinearLayout tkListViewLayout scrollDirection="Vertical"> </ListViewLinearLayout>
          <ng-template let-item="item" tkListItemTemplate>
            <StackLayout orientation="vertical">
              <Label fontSize="20" text="{{ item.name }}"></Label>
              <Label fontSize="14" text="{{ item.description }}"></Label>
            </StackLayout>
          </ng-template>
        </RadListView>
      </GridLayout>
      <TextField row="1" hint="Enter some text" text=""></TextField>
    </GridLayout>


    Regards,
    Nikolay Iliev
    Progress Telerik
    Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
  9. Ericky
    Ericky avatar
    49 posts
    Member since:
    Jun 2017

    Posted 27 Jun 2017 Link to this post

    Hi Nikolay,

     

    I copy and pasted the changes you made to my sample project, and it still did not work for me. Did you try restarting the app and seeing if it works a second time?

     

    Here's a video of me running the updated sample project:

    Updated Video

    Updated Sample Project

  10. Nikolay Iliev
    Admin
    Nikolay Iliev avatar
    351 posts

    Posted 28 Jun 2017 Link to this post

    Hello Ericky,

    Indeed I was able to reproduce the issue again on the second run after I have rebuilt my test application.
    It appears that this is inconsistent behavior when a software keyboard is focused within a router-outlet. I have logged this as an issue here. You can track the issue for suggestions and fixes - after some research on the topic with the nativescript-angular developers, it appears that there are some structural changes related to router-outlet which will be released in the upcoming versions. Once the new release is official, I will retest this scenario and update the information in te linked issue.

    Meanwhile, at this very moment, the only workaround is to switch the places of your RadListView and TextField (so that the TextField will load first) and thus the keyboard stops pushing the content.
    Note: In my test application the current structure is also not pushing the  content, but I suspect that the issue is inconsistent - perhaps you can try at your side my configuration and if does not work as expected - try to change places of the TextFiel and RadListView here

    Regards,
    Nikolay Iliev
    Progress Telerik
    Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
  11. Ericky
    Ericky avatar
    49 posts
    Member since:
    Jun 2017

    Posted 28 Jun 2017 Link to this post

    Thank you for all the assistance Nikolay. I will be watching that issue.
  12. Ericky
    Ericky avatar
    49 posts
    Member since:
    Jun 2017

    Posted 05 Jul 2017 Link to this post

    Hello Nikolay,

     

    Regarding this issue, I mentioned before how the issue was fixed if you focused the text field and initiated a pull to refresh action.

     

    So, I confirmed that removing the line 'this._android.addBehavior(this._pullToRefreshBehavior);' on listview.android.js makes the above statement not true.

     

    Is there any way to call this 'addBehavior' method or initiate a pull to refresh manually from the angular app when the RadListView is initiated? I believe that would be a workaround for this issue.

     

    Thank you.

  13. Nikolay Iliev
    Admin
    Nikolay Iliev avatar
    351 posts

    Posted 06 Jul 2017 Link to this post

    Hi Ericky,

    We are currently investigating the reason behind this issue  and currently, it seems that the problem is caused by router-outlet not being able to occupy the space that it was given in test.html (in your case you are using StackLayout but even if using GridLayout with hard coded rows values it will again not span on the wanted space). At this moment we don't have a feature that can trigger the pullToRefresh from code-behind but I must point out that even if this is possible it won't be a good workaround as in fact the issue is related not to the RadListView and pullToRefresh functionality but to the way router-outlet works.

    Please keep track on the linked issue where our developers will seek for a solution for this specific scenario.

    Meanwhile, as a solution, you can use loadChildren instead of children to structure your routes.
    When using loadChildren the content in the router-outlet will load and occupy the available space as expected and the software keyboard won't push the outer content. This would require for you to implement lazy loading for your inner routes and create separate modules for each lazily loaded module.

    Real life example demonstrating exactly your scenario but using loadChildren can be found in the nested-routers example in our nativescript-sdk-examples-ng application. You can test this example by implementing a text field in the content of the router-outlet and it won't push the outer buttons.
    Implementing the lazy loading pattern will not only solve this issue but will also improve the overall startup time of bigger application you won't load all the modules at the very beginning of your application start but only when needed.

    Few things that are important for Lazy Loading (based on this application)
    - you need to provide the оур NGModuleFactoryLoader as done here
    mport { NativeScriptRouterModule, NSModuleFactoryLoader } from "nativescript-angular/router";
     
    @NgModule({
        schemas: [NO_ERRORS_SCHEMA],
        declarations: [
            AppComponent,
        ],
        bootstrap: [AppComponent],
        imports: [
            NativeScriptModule,
            NativeScriptRouterModule,
            NativeScriptRouterModule.forRoot(routes),
        ],
        providers: [
            ModalDialogService,
            { provide: NgModuleFactoryLoader, useClass: NSModuleFactoryLoader }
        ]
    })

    - when creating your routes use not children but loadChildren as done here and then add the main route config as usual for each lazily loaded child route. Note the following line
    loadChildren: "./routing/routing-examples.module#RoutingExamplesModule",
    where the path is ./routing/routing-examples.module
    and then we have the special symbol 
    followed by the name of the exported module RoutingExamplesModule

    - then for your lazy loaded module (e.g. this) use children as done here.

    We are currently working on a blog post explaining the new lazy loading pattern step by step (as done in nativescript-sdk-example-ng where we are loading approximately 200 modules lazily) so keep an eye on our blogs. The old article about lazy loading will be updated but please do not use the approach there as it is now obsolete

    Regards,
    Nikolay Iliev
    Progress Telerik
    Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
  14. Ericky
    Ericky avatar
    49 posts
    Member since:
    Jun 2017

    Posted 06 Jul 2017 Link to this post

    Hello Nikolay,

     

    I tested a test project with the structure you presented, but it still does not work.

     

    On the attached test project, when you first run it, it will work as expected. Then, if you follow these steps, it will break it again.

    * On pages/pages.html, uncomment commented code and remove/comment the listview element which was previously in the page.

    * Re-run "tns run android"

    * Follow the same route again thorough Pages>Main>Inner>First

     

    I commented out the RadListView in inner-one.html because it throws an error when I access that page and I can't figure out why. But even then, the TextField still pushes the page out of view with just a GridLayout.

     

    Test Project

  15. Nikolay Iliev
    Admin
    Nikolay Iliev avatar
    351 posts

    Posted 07 Jul 2017 Link to this post

    Hello Ericky,

    Indeed it seems that the issue is not resolved even when using a lazily loaded router-outlet on root level.
    Our developer's team will need additional time to investigate the issue and find a proper solution for this case.

    Please keep track on the logged issue I have previously opened in the nativescript-angular repository for possible workarounds and additional information regarding this scenario.

    Regards,
    Nikolay Iliev
    Progress Telerik
    Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
Back to Top