Refresh UI after Local storage change in Mobile

Greetings,

I have a screen called Leap, and I show a list of leaps from local storage. When I add a new leap, it redirects to the Leap page but the new entry is not shown. I have to go to my DataManagement screen which has a 'Sync to Local Storage' button and return to the Leap screen. Only then I can see the change. How do I update the screen list after I added a new leap?


Basically i want to refresh the List widget in UI based on the updated local database. If i put the refresh in the OnRender of the screen it starts glitching because of a loop, but i cant seem to get it to work any other way.


Attached is the oml. Thanks for any help.

Hello Yusra,

I was checking your code for a bit.

So you have your Leaps page, where you have 2 aggregates: GetAllLocalLeaps and GetLocalLeapsByUserId.

By the time that you press into your add button (+), then you go into LeapDetail page. You fill some input parameters and click Save, calling SaveOnClick client action, which is going to create a new LocalLeap just before navigate back to Leaps screen.


How many records do you have in your LocalLeap entity?

Because you're fetching only 50 records from the database:


Maybe you are creating new records, but since you are only fetching 50, the application only displays those 50 records.


Kind regards,

Rui Barradas

Hi Yusra,

Adding to what Rui already mentioned, if you drag your local entity LocalLeap on to a mobile screen canvas, the aggregate with automatic OnScrollEnding event handler is scaffold. This scaffold screen action will handle the automatic retrieval of the next 'batch' of records to display.

After dropping the entity on the screen, you can adjust the GetLocalLeaps Local Database aggregate to include the Local Status too.

You can also scaffold this code to an existing (local) entity:

Regards,

Daniel

Hi Yusra,

you are going back from detail to list screen with a flow to Screen, so there's no reason to think about adding extra refreshes and stuff like that, your aggregates will run "At Start".  So that's not the reason.

I'm guessing you added the GetAll aggregate after not succeeding with the GetListById, and there's now a lot of clutter and attempts for fixing this in your screen, so it's hard to tell what's going on, and you didn't provide a full set of oml's so we can't test.

But I miss one thing that might be part of your problem : when creating leaps, there's no userid being set, as far as i can tell.  So they get created with an empty userid.  If then you try to list them filtered on userid, that won't give results.  We can't see the implementation of your server actions (your db wrappers) but maybe you have logic there to add the userid.  In that case, after a sync from server data back down to local data, that userid will come with it, and the same leap will suddenly show up in list filtered for user.

Dorine

Hi Yusra,

I completely agree with what Dorine mentioned... I also observed the same mistake in the SaveOnClick button Action flow (LeapDetail Screen). The other point which I want to mention is that.. If the requirement is to showcase only the Leaps information which is way specific to the Logged-in user - I would suggest you to define the server-local data sync logic accordingly (filter the Server DB table by UserId before syncing the data to the Local storage table) and the defined UserId filter in the Aggregate is also not required.. (UserId attribute in Local Leap table can also be avoided)

See the attached .oml solution file..

Hope this helps you!


Regards,

Benjith Sam

Dorine Boudry wrote:

Hi Yusra,

you are going back from detail to list screen with a flow to Screen, so there's no reason to think about adding extra refreshes and stuff like that, your aggregates will run "At Start".  So that's not the reason.

I'm guessing you added the GetAll aggregate after not succeeding with the GetListById, and there's now a lot of clutter and attempts for fixing this in your screen, so it's hard to tell what's going on, and you didn't provide a full set of oml's so we can't test.

But I miss one thing that might be part of your problem : when creating leaps, there's no userid being set, as far as i can tell.  So they get created with an empty userid.  If then you try to list them filtered on userid, that won't give results.  We can't see the implementation of your server actions (your db wrappers) but maybe you have logic there to add the userid.  In that case, after a sync from server data back down to local data, that userid will come with it, and the same leap will suddenly show up in list filtered for user.

Dorine

 

 Hi Dorine, 

The GetAll aggregate is actually not a result of me trying different strategies- I created it to display another list for the Admin. The admin should be able to view all the leaps irrespective of user, hence the 2 aggregates (GetAllLocalLeaps, and GetLocalLeapsByUserId) showing 2 different results based on the UserRole.


As for the userid at the time of a new leap being created, you're right, Im doing this userid check in the server action by using GetUserId(). It works fine: the userid gets saved, when i call the local db, it shows me the current users leaps, the only problem is that when I make a new one it does not display it in this leap immediately, i have to press the 'Sync to local storage' button in datamanagement for it do display in the list. 

Hope this makes sense! Sorry for not including the entire project. Is there a better way of getting the records based on UserRole than what I did? I agree mine is very cluttered

Benjith Sam wrote:

Hi Yusra,

I completely agree with what Dorine mentioned... I also observed the same mistake in the SaveOnClick button Action flow (LeapDetail Screen). The other point which I want to mention is that.. If the requirement is to showcase only the Leaps information which is way specific to the Logged-in user - I would suggest you to define the server-local data sync logic accordingly (filter the Server DB table by UserId before syncing the data to the Local storage table) and the defined UserId filter in the Aggregate is also not required.. (UserId attribute in Local Leap table can also be avoided)

See the attached .oml solution file..

Hope this helps you!


Regards,

Benjith Sam

 Hi Benjith,


As I mentioned in my reply to Dorine, I unfortunately have to do this because the requirement is to have- 

1. Get ALL the records if current user is admin and

2. Get user's records if user not admin

This is also why I didnt put the userid check in the server actions, it would be a smarter way of doing it but unfortunately I need the entire db first, and then filter by UserId, based on role.

 Thanks a lot for the help!

Rui Barradas wrote:

Hello Yusra,

I was checking your code for a bit.

So you have your Leaps page, where you have 2 aggregates: GetAllLocalLeaps and GetLocalLeapsByUserId.

By the time that you press into your add button (+), then you go into LeapDetail page. You fill some input parameters and click Save, calling SaveOnClick client action, which is going to create a new LocalLeap just before navigate back to Leaps screen.


How many records do you have in your LocalLeap entity?

Because you're fetching only 50 records from the database:


Maybe you are creating new records, but since you are only fetching 50, the application only displays those 50 records.


Kind regards,

Rui Barradas

 Hi Rui,


Thats a great observation, I didnt realise that. I changed this and tested again but the problem is still occurring. :(

 Thanks though!

Yusra Khan wrote:

Hi Benjith,


As I mentioned in my reply to Dorine, I unfortunately have to do this because the requirement is to have- 

1. Get ALL the records if current user is admin and

2. Get user's records if user not admin

This is also why I didnt put the userid check in the server actions, it would be a smarter way of doing it but unfortunately I need the entire db first, and then filter by UserId, based on role.

 Thanks a lot for the help!

Hi Yusra,

You just have to add the Assign Node (Assigning the UserId to the Record attribute - GetLocalLeapById.List.Current.LocalLeap.UserId  which is mapped with the CreateOrdUpdateLocalLeap Entity Action) within the SaveOnClick Action flow defined in the LeapDeatil screen as shown below... which you missed in the code and this is what Dorine and I was trying to convey...


Please see the attached .oml file (organized the flow and did the required code changes)

Hope this helps you!


Regards,

Benjith Sam

Solution

Yusra Khan wrote:

 Hi Dorine, 

The GetAll aggregate is actually not a result of me trying different strategies- I created it to display another list for the Admin. The admin should be able to view all the leaps irrespective of user, hence the 2 aggregates (GetAllLocalLeaps, and GetLocalLeapsByUserId) showing 2 different results based on the UserRole.


As for the userid at the time of a new leap being created, you're right, Im doing this userid check in the server action by using GetUserId(). It works fine: the userid gets saved, when i call the local db, it shows me the current users leaps, the only problem is that when I make a new one it does not display it in this leap immediately, i have to press the 'Sync to local storage' button in datamanagement for it do display in the list. 

Hope this makes sense! Sorry for not including the entire project. Is there a better way of getting the records based on UserRole than what I did? I agree mine is very cluttered

 Ok, that explains the 2 aggregates.  I think the scope of what leaps to show on the device, I would probably regulate that in the syncing, syncing either all or only the ones from the current user, dependent on the user's rights.  

But surely, the fact that you don't store a userid in local storage is the reason for this behaviour described in your original post : "When I add a new leap, it redirects to the Leap page but the new entry is not shown."  It would make sense to me if this happens when logged in as a non-administrator user, as your app is built now.  Or does it also happen when your user does have admin rights ??

Anyway, if you would regulate the scope of leaps to either all or just for this user during your syncing, then you only are left with a single aggregate in your screen, without any filter, that would even take away the need to add a userid to the local leap record at time of creation.

 


EDIT

Oh, and in order for people to be able to install and test your code, you could download the application into an oap file instead of exporting a single oml file.  That would take care of the typical situation of sharing the ui but not the core.  But you might have lots of other dependencies, or a much more complex architecture, at some point, sharing everything just isn't usefull, and if I have to install 5 forge components before being able to test somebody's example, I pass on it.

Solution

Dorine Boudry wrote:

Yusra Khan wrote:

 Hi Dorine, 

The GetAll aggregate is actually not a result of me trying different strategies- I created it to display another list for the Admin. The admin should be able to view all the leaps irrespective of user, hence the 2 aggregates (GetAllLocalLeaps, and GetLocalLeapsByUserId) showing 2 different results based on the UserRole.


As for the userid at the time of a new leap being created, you're right, Im doing this userid check in the server action by using GetUserId(). It works fine: the userid gets saved, when i call the local db, it shows me the current users leaps, the only problem is that when I make a new one it does not display it in this leap immediately, i have to press the 'Sync to local storage' button in datamanagement for it do display in the list. 

Hope this makes sense! Sorry for not including the entire project. Is there a better way of getting the records based on UserRole than what I did? I agree mine is very cluttered

 Ok, that explains the 2 aggregates.  I think the scope of what leaps to show on the device, I would probably regulate that in the syncing, syncing either all or only the ones from the current user, dependent on the user's rights.  

But surely, the fact that you don't store a userid in local storage is the reason for this behaviour described in your original post : "When I add a new leap, it redirects to the Leap page but the new entry is not shown."  It would make sense to me if this happens when logged in as a non-administrator user, as your app is built now.  Or does it also happen when your user does have admin rights ??

Anyway, if you would regulate the scope of leaps to either all or just for this user during your syncing, then you only are left with a single aggregate in your screen, without any filter, that would even take away the need to add a userid to the local leap record at time of creation.

 


EDIT

Oh, and in order for people to be able to install and test your code, you could download the application into an oap file instead of exporting a single oml file.  That would take care of the typical situation of sharing the ui but not the core.  But you might have lots of other dependencies, or a much more complex architecture, at some point, sharing everything just isn't usefull, and if I have to install 5 forge components before being able to test somebody's example, I pass on it.

 

 Hey Dorine,


This worked! I added the UserRole condition to get leaps based on userid during Sync and added the correction that Benjith stated about setting the userId in the SaveOnClick. Now when i create a new leap, it shows up immediately.

Also yes you were right, it does not happen with the leap admin, only the non-admins (i thought this is because admin is only updating existing records and not creating new ones)


Anyway, thanks! and I will keep the .oml .oap advice in mind next time :)