https://zkfiddle.org/sample/2cdadkk/11-scroll-to-item-in-mvvm-using-selection
MDuchemin ( 2023-04-10 16:33:57 +0800 )edit-
FEATURED COMPONENTS
First time here? Check out the FAQ!
I need to scroll a listbox (or a grid) always to the bottom as it is a live log data output which should always show the most recent entry.
It looks like (example):
<listbox id="list" hflex="1" model="@load(vm.notifications)"
emptyMessage="${labels.noNotifications}">
<listhead>
<listheader label="${labels.notificationTimestamp}" sort="auto(timestamp)" />
<listheader label="${labels.id}" sort="auto(id)" />
<listheader label="${labels.notificationEvent}" sort="auto(event)" />
<listheader label="${labels.notificationPayload}" />
</listhead>
<template name="model">
<listitem>
<listcell label="@load(each.timestamp) @converter('date')" />
<listcell label="@load(each.event)" />
<listcell label="@load(each.id)" />
<listcell label="@load(each.payload)" />
</listitem>
</template>
</listbox>
Now I know that I should be able to scroll to the bottom using
Clients.scrollIntoView(listitem);
But in the ViewModel I got stuck
@Wire
Listbox list;
...
@AfterCompose
public void afterCompose(@ContextParam(ContextType.VIEW) Component view) {
Selectors.wireComponents(view, this, false);
/* >>>>> how to get the component "listitem" for the last row here? <<<<<< */
Clients.scrollIntoView(listitem);
}
Note: You could argue that there is no list item yet as I am still in after compose.
I also tried to retrieve call the listitem on any event when the list was definitely filled. No success:
list.getItems()
is always empty and
list.getItemAtIndex(0)
is always null!
Hey there,
First regarding the use @wire and @afterCompose in viewModel, just note that they break the MVVM pattern. ZK provide these options because sometime there is no other choice than breaking the pattern. If possible, I recommend trying to avoid these.
Regarding why scrolling from VM is not working here: @afterCompose will register a callback during the afterCompose step of the underlying bindcomposer.
https://zkfiddle.org/sample/2cdadkk/9-scroll-to-item-in-mvvm-using-selection
The AfterCompose step occurs before the binder initializes all of the @init, @load and @bind bindings with their values, which means that at this point, there is no model actually attached to the Listbox, and there is no listitems created.
An alternative way to implement scroll would be to use model selection instead. Model selection will scroll model-bound components when set.
However, this also cannot be done until the items are rendered. Luckily, there is a MVVM friendly to obtain a timing at which item rendering is done, and therefore scrolling is queueable by setting model selection.
<listbox id="lb" model="@init(vm.model)" onAfterRender="@command('scroll')" height="500px"/>
The onAfterRender event is returned once the Listbox has initialized and rendered the listitems. By using this event as a command trigger, we can execute a VM command and update the model selection. Updating selection automatically scroll to the item position.
Runnable sample: https://zkfiddle.org/sample/2cdadkk/9-scroll-to-item-in-mvvm-using-selection
https://zkfiddle.org/sample/2cdadkk/11-scroll-to-item-in-mvvm-using-selection
MDuchemin ( 2023-04-10 16:33:57 +0800 )editAsked: 2023-03-21 05:20:36 +0800
Seen: 10 times
Last updated: Mar 22
Is there a way to create Loadingbar on client side?
How to stop combining commands in an ajax call ?
zk.auSend not called on composer
Font Awesome Problem with IE8 when security option "font download" is disabled
Send a client event with JSON data
How to capture the Browser Window Resize/Size Event
Toggled Popup - Close ONLY on toggling, not on focus lost