What is the best approach to hold a global value in mobile app

What is the best approach to hold a global value in mobile app

  

Hi,

I know global's are not the best practice but I want to hold a selected role value throughout app life cycle &  which can be changed by user, used further accordingly. As of I have to send the selected role to each REST API on respective screen thus I am trying to explore best approach to go for the same.

Some of the below I found on forum:

1- Site Properties [ But it would be a bad practice in terms of performance]

2- Holding a var on selection & passing to each navigated screen [ Quite Bad]

3- Creating an entity of roles & updating the status of selected in it & using it's Aggregate in all Screen with a filter to get the active one. [ I have to use the aggregate on all the screen where I need this]


I think point-3 is somewhat feasible, but still...

Thanks in Advance,

Assif


1 - Site properties don't exist in mobile

2 - Quite bad indeed

3 - I would choose that one: since you have local database in mobile it will be quite fast. Instead of using an aggregate all the time, maybe it's easier to create a client-action you can use every time you need the value

Joost Rutten wrote:

1 - Site properties don't exist in mobile

2 - Quite bad indeed

3 - I would choose that one: since you have local database in mobile it will be quite fast. Instead of using an aggregate all the time, maybe it's easier to create a client-action you can use every time you need the value

Thanks,

1-But just to correct you, Site properties are there in Mobile app.

2- Agreed

3- Let me try & get back to you :)

Hi Assif,

Since Screens in a Mobile App are essentially stateless, you indeed either need to pass the values around (#2) or store them in the local database (#3). #1 is imho not a real option here, as it would need contacting the server to request the value (Movile Apps don't have Site Properties themselves).

As for using an Aggregate in every screen, there's no pretty solution, but one thing you could do is create a Block that fetches the data and On Fetch triggers an Event (passing the data), and include that Block on each Screen you need it. This will still necessitate putting something on each Screen (and some handling of the Input Variable of the Event, like copying it to a Local Variable), but at least you don't have to duplicate the Aggregate everywhere.

If anyone has a better solution I'd be glad to hear.

Kilian Hekhuis wrote:

Hi Assif,

Since Screens in a Mobile App are essentially stateless, you indeed either need to pass the values around (#2) or store them in the local database (#3). #1 is imho not a real option here, as it would need contacting the server to request the value (Movile Apps don't have Site Properties themselves).

As for using an Aggregate in every screen, there's no pretty solution, but one thing you could do is create a Block that fetches the data and On Fetch triggers an Event (passing the data), and include that Block on each Screen you need it. This will still necessitate putting something on each Screen (and some handling of the Input Variable of the Event, like copying it to a Local Variable), but at least you don't have to duplicate the Aggregate everywhere.

If anyone has a better solution I'd be glad to hear.

Hey thanks,

That I though early but still have to add block in each screen.

I am trying by the client action approach, If it not work some how.. I guess block can be nearby solution.



Yes, you can also add a Data Action ("Fetch Data from Other Sources"), and call a Client Action to retrieve the configuration data, that would work as well.

Hi Assif,

You have this link, I think it is helps you:

  1. Create a local entity to store the state for an element. In the Local Storage, create a NavState entity with an attribute Value of type text and set its Id as type text. Each record of this entity will map a key/value pair which you can use to persist the state of a screen element.

     

  2. To persist and retrieve the element/state from the local storage create two client actions, in the Logic tab:

    1. SetState receives a key and a value as input parameters and persists them both in a NavState record. To do this, add an aggregate of NavState to get the list of its records. Use a filter in the aggregate to get the record where NavState.Id = StateKey parameter to update the record for that key if it exists already; assign the values held in the input parameters to the current record of the aggregate’s list and use CreateOrUpdateNavState to persist the record in the Local Storage.
    2. GetState receives a key (NavState identifier) and outputs the value for that key. To this, add an aggregate with NavState.Id = StateKey as filter condition to obtain that record. Assign the content of the Value attribute of that record to the output parameter: StateValue = GetNavStateById.List.Current.NavState.Value.

       

  3. Populate the dropdown menu with the last user’s selection before rendering the screen. In the Home screen properties, under events, create a new client action to handle the On Initialize event. In this action:

    1. Call GetState using the expression TextToIdentifier("Filter") to obtain an identifier type you can store in NavState.Id. Filter is the local variable holding the dropdown selection.
    2. Assign to Filter the value returned by GetState.
  4. Populate the screen with places records of the selected category. In the screen’s local aggregate used as source for the List widget, use the following filter condition LocalPlace.Category = Filter or Filter = "". The first part of the OR condition shows the records for the category selected by the end-user in the user’s last interaction with the home screen. The second part of the OR condition shows all the records, when the Filter variable is empty.
  5. To persist the filter state (category choice), in the client action handling the On Change event of the dropdown widget:

    1. Call SetState and set StateValue as Filter and the StateKey as TextToIdentifier("Filter") to store the key/value pair.
    2. Refresh the GetLocalPlaces screen aggregate using a Refresh data node to adjust the source of the List widget.

Hi assif,

Just to add a couple of alternatives to the discussion.

You can use JavaScript window variables since OutSystems mobile is an SPA, they'll be maintained through out the app. 


You can use Local Storage without creating a table/attributes. See Brian's response on this post for an example.

Cheers

Solution

I made it this way:

- Created a Local Entity

- Created a client action for Update & Get with the Local Entity Aggregate

- Using the Client Action wherever I'll need to fetch the active Role in app


Cheers

Solution

Paulo Cação wrote:

Hi Assif,

You have this link, I think it is helps you:

  1. Create a local entity to store the state for an element. In the Local Storage, create a NavState entity with an attribute Value of type text and set its Id as type text. Each record of this entity will map a key/value pair which you can use to persist the state of a screen element.

     

  2. To persist and retrieve the element/state from the local storage create two client actions, in the Logic tab:

    1. SetState receives a key and a value as input parameters and persists them both in a NavState record. To do this, add an aggregate of NavState to get the list of its records. Use a filter in the aggregate to get the record where NavState.Id = StateKey parameter to update the record for that key if it exists already; assign the values held in the input parameters to the current record of the aggregate’s list and use CreateOrUpdateNavState to persist the record in the Local Storage.
    2. GetState receives a key (NavState identifier) and outputs the value for that key. To this, add an aggregate with NavState.Id = StateKey as filter condition to obtain that record. Assign the content of the Value attribute of that record to the output parameter: StateValue = GetNavStateById.List.Current.NavState.Value.

       

  3. Populate the dropdown menu with the last user’s selection before rendering the screen. In the Home screen properties, under events, create a new client action to handle the On Initialize event. In this action:

    1. Call GetState using the expression TextToIdentifier("Filter") to obtain an identifier type you can store in NavState.Id. Filter is the local variable holding the dropdown selection.
    2. Assign to Filter the value returned by GetState.
  4. Populate the screen with places records of the selected category. In the screen’s local aggregate used as source for the List widget, use the following filter condition LocalPlace.Category = Filter or Filter = "". The first part of the OR condition shows the records for the category selected by the end-user in the user’s last interaction with the home screen. The second part of the OR condition shows all the records, when the Filter variable is empty.
  5. To persist the filter state (category choice), in the client action handling the On Change event of the dropdown widget:

    1. Call SetState and set StateValue as Filter and the StateKey as TextToIdentifier("Filter") to store the key/value pair.
    2. Refresh the GetLocalPlaces screen aggregate using a Refresh data node to adjust the source of the List widget.

Thanks,

That is what the 3rd point I already mention in question, :)



That would be a good approach, yes, unless you need to call it a lot of times, in which case it could be better performing if you do it only once per screen.

Henrique Batista wrote:

Hi assif,

Just to add a couple of alternatives to the discussion.

You can use JavaScript window variables since OutSystems mobile is an SPA, they'll be maintained through out the app. 


You can use Local Storage without creating a table/attributes. See Brian's response on this post for an example.

Cheers

Interesting one, We'll also look for it


Paulo Cação wrote: Ok, this is a possible solution but Service Center will generate a Warning when you access localstorage on "OnInitialize" event.

Hi Assif,

You have this link, I think it is helps you:

  1. Create a local entity to store the state for an element. In the Local Storage, create a NavState entity with an attribute Value of type text and set its Id as type text. Each record of this entity will map a key/value pair which you can use to persist the state of a screen element.

     

  2. To persist and retrieve the element/state from the local storage create two client actions, in the Logic tab:

    1. SetState receives a key and a value as input parameters and persists them both in a NavState record. To do this, add an aggregate of NavState to get the list of its records. Use a filter in the aggregate to get the record where NavState.Id = StateKey parameter to update the record for that key if it exists already; assign the values held in the input parameters to the current record of the aggregate’s list and use CreateOrUpdateNavState to persist the record in the Local Storage.
    2. GetState receives a key (NavState identifier) and outputs the value for that key. To this, add an aggregate with NavState.Id = StateKey as filter condition to obtain that record. Assign the content of the Value attribute of that record to the output parameter: StateValue = GetNavStateById.List.Current.NavState.Value.

       

  3. Populate the dropdown menu with the last user’s selection before rendering the screen. In the Home screen properties, under events, create a new client action to handle the On Initialize event. In this action:

    1. Call GetState using the expression TextToIdentifier("Filter") to obtain an identifier type you can store in NavState.Id. Filter is the local variable holding the dropdown selection.
    2. Assign to Filter the value returned by GetState.
  4. Populate the screen with places records of the selected category. In the screen’s local aggregate used as source for the List widget, use the following filter condition LocalPlace.Category = Filter or Filter = "". The first part of the OR condition shows the records for the category selected by the end-user in the user’s last interaction with the home screen. The second part of the OR condition shows all the records, when the Filter variable is empty.
  5. To persist the filter state (category choice), in the client action handling the On Change event of the dropdown widget:

    1. Call SetState and set StateValue as Filter and the StateKey as TextToIdentifier("Filter") to store the key/value pair.
    2. Refresh the GetLocalPlaces screen aggregate using a Refresh data node to adjust the source of the List widget.



Hi Saulo,

Service Studio indeed gives a warning, but keep in mind that it's a warning only. In general, you wouldn't want to do anything in the OnInitialize that takes a lot of time, since the screen won't be rendered until it's finished, which could lead to a bad user experience. However, if it makes sense for your use case, you can ignore the warning (you can hide it to explicitly in the TrueChange tab).

Kilian Hekhuis wrote:

Hi Saulo,

Service Studio indeed gives a warning, but keep in mind that it's a warning only. In general, you wouldn't want to do anything in the OnInitialize that takes a lot of time, since the screen won't be rendered until it's finished, which could lead to a bad user experience. However, if it makes sense for your use case, you can ignore the warning (you can hide it to explicitly in the TrueChange tab).

Haa , That's what I did with some of warning's.

@Saulo I avoid using my approach in onInitialize, as of it will block the screen navigation until it executed & thus may lead to bad UI user experience.

I have an requirement of using the same while API's specially & thus I called the approach action there.

Cheers