# ScrollIntoView and NotifyChange

asked 2021-03-02 21:40:40 +0800

aUser
123 4

Hello,

I have a borderlayout component inside a .zul page, and in it's west subcomponent (that has autoscroll="true") i have two nested div components with the children property that references to a ListModelList. The first div is connected to a ListModelList declared on my viewmodel, and the nested div points to a property of this list, which again is a ListModelList.

From the viewmodel i update the items of these lists and then i use the command

BindUtils.postNotifyChange(null, null, myList, "property");


to update the view.

I want then to make the scrollbar go to a certain item inside the list and i found the Clients.scrollIntoView(Component cmp) but it doesn't work if I notify the list. I tried to remove the notify command and Clients.scrollIntoView(Component cmp) works fine, but it simply doesn't if i need to notify the list.

From this question it shows that a Listbox for example has the onAfterRender as a supported event, but the borderlayout doesn't support that, so I have no ideas here on how to make this work.

Is there a way to wait for the notifyChange to finish and only then apply the scrollIntoView command?

Thank you

delete retag edit

Sort by » oldest newest most voted

answered 2021-03-29 09:31:55 +0800

hawk
2785 1 5
http://hawkphoenix.blogsp...

forEach doesn't support @template, you can just put components inside it like

<forEach>
<image>
</forEach>


Or

<forEach>
<apply template="images">
</forEach>


Thank you

( 2021-03-29 22:00:34 +0800 )edit

answered 2021-03-04 00:34:59 +0800

aUser
123 4

Any ideas?

answered 2021-03-05 15:48:32 +0800

hawk
2785 1 5
http://hawkphoenix.blogsp...

I suppose scrollIntoView() not working is because the corresponding DOM element is not yet rendered. so you need to call scrollIntoView() later.

Call scrollIntoView() in onAfterSize event listener might help. since this event is fired after rendering and resize an element.

can't answer, i'll put a comment then I tried this but it doesn't work so well.. Sometimes it scroll to an image close enough, but sometimes it doesn't even scroll at all. I'm treating images, so i'm thinking that the images might not been loaded yet, could this be the case?

( 2021-03-08 15:44:27 +0800 )edit

answered 2021-03-08 23:06:17 +0800

aUser
123 4

Updating the situation..

I have to work with images, and long short story this is the behaviour so far:

I have a groupbox that contains 200 images, then i click on the 101th image of this groupbox and i create another groupbox that contains all the images from the 101th (the one clicked) to the 200th. So right now i have two groupbox both with 100 images. To reach the 100th image of the first groupbox i have to scroll a bit and then i use BuildUtils.notifyUpdate(null, null, myObj, "listOfImages") to update the view. Once the groupboxes are rendered, the scroll comes right at the top of the page. Now if i scroll again to the 80th image for example and i press again to create another groupbox, the scroll stays where it is right now, which is the behaviour i need.

The problem happens only the first time i have to make this split action, beyond the 2nd split i have no problems at all with the scrollbar. Any ideas on why it doesn't work the first time but then it works fine?

Thank you

answered 2021-03-15 18:11:44 +0800

hawk
2785 1 5
http://hawkphoenix.blogsp...

If it relates to image loading , set <custom-attributes org.zkoss.zul.image.preload="true"/> might help your.

answered 2021-03-15 20:58:24 +0800

aUser
123 4

Unfortunately it doesn't help.. When i have to make a BindUtils.postNotifyChange(...) the behaviour is the same, page is loading and then the scrollbar comes back at the top. I'm using ListModelList and when i'm creating a new groupbox i don't have to notify the binder about it, it creates the groupbox without realoading nothing, but the problem is the old groupbox, it doesn't realod it's content automatically (since now it has less items than before), so i have to use the notify change function, which makes the page load for a bit and then makes the scrollbar go on top of the page.

For this "little" problem i think i have to wait for all DOM nodes to be rendered and only then set focus on a particular item, hence i need to do some Client side programming i guess..

I found a solution that is not so good in my opinion.. After the groupbox is resized i call a command from the viewmodel where i invoke a javascript function, so it is something like this:

<groupbox onAfterResize="@command('callJavaScript').. >
.....
</groupbox>


and in my viewmodel:

@command
public void callJavaScript() {
Clients.evalJavaScript("javascript code");
}


I don't know if it a decent solution but surely it's not optimal since if for example i need to remove a single image from a groupbox, the afterSize event is not called hence the javascript code won't be executed

answered 2021-03-18 16:25:51 +0800

hawk
2785 1 5
http://hawkphoenix.blogsp...

replace "children binding" with <forEach> with ListModelList, then you don't need to call postNotifyChange. Because ListModelList will notify automatically when you call its method. And this approach doesn't cause a re-rendering of the whole list.

I literally changed 'children="@load(vm.images) @template('thumbnails')"' into 'forEach="@load(vm.images) @template('images')" and nothing shows up. vm.images is a ListModelList and with the children property everything shows up like it should, with forEach it doesn't.. I don't know what i'm missing

( 2021-03-23 23:59:52 +0800 )edit
[hide preview]

## Stats

Asked: 2021-03-02 21:40:40 +0800

Seen: 24 times

Last updated: Mar 29

Support Options
• Email Support
• Training
• Consulting
• Outsourcing