1

Edit: It seems the correct values are stored in listWidget.children._values instead of just listWidget.children. It seems strange to me that the children would still contain those old row keys and null values though.

I'm trying to create a list whose datasource is another datasource's item's relation. For example: I have two tables, one storing roles and another storing permissions and I have a one to many relation between roles and permissions. Both the roles and permissions tables have a name property.

I have a list with datasource roles to select a role. Each row has a button with the following code for the onClick event:

app.datasources.roles.selectKey(widget.datasource.item._key);
app.showPage(app.pages.listView);

I'm not sure if this is the best practice but it sets the current role item to the key stored in the roles list's row's datasource key.

The listView page has another list, this time having a datasource of @datasources.roles.item.permissions to load rows from the current role's permissions. I then have a simple label to output that permission's name.

The permission list loads just fine the first time, with the list widget's children containing the correct rows but when you go back to the role selection page and click another role's button the widget seems to go to an invalid state with the children keys staying as the old rows and the values null. I have an event on the row's onDataLoad to output the row widget and I can see that the new rows are being loaded and linked to the parent widget (the list itself) but if I go back to the children of that widget the values are still null.

For example let's say I have two roles:

key | name 
===========
1   | role1 
2   | role2

and the following permissions:

key | name  | role_fk
=====================
1   | perm1 | 1
2   | perm2 | 1
3   | perm3 | 2

When I click the button to load role key 1 and show it's permission list I get the correct list:

Permission List:
================
perm1
perm2

And when I check the list widget I also see the correct children: "List1Row$0", "List1Row$1". However, once I go back and click to load role key 2 I still have children "List1Row$0", "List1Row$1", their values are null, and the list shows:

Permission List:
================
perm3

I know the perm3 widget is being created as I have it print to console when it's attached. One strange thing is that it's name is "List1Row$2", suggesting that the old row values were never cleared out.

Anyone know how to fix this? I can link a sample app which is as simple as I could make while still exposing the issue. I'm not sure if you're able to use item relations as list datasources or if there's an issue with how I'm selecting my datasources, items, and bindings.

Here is some additional output, the point where the list is detatched is where I go back and click to set the page item to the second item.

Loaded row with name List1Row$0
Loaded row with name List1Row$1
Widget Child - Key: __gwt_instance Null? No
Widget Child - Key: _values Null? No
Widget Child - Key: List1Row$0 Null? No
Widget Child - Key: List1Row$1 Null? No
------- Detatching List -------
Loaded row with name List1Row$0
Loaded row with name List1Row$1
Loaded row with name List1Row$2
Widget Child - Key: __gwt_instance Null? No
Widget Child - Key: _values Null? No
Widget Child - Key: List1Row$0 Null? Yes
Widget Child - Key: List1Row$1 Null? Yes

Thanks.

Rherma
  • 331
  • 2
  • 8
  • Does it https://stackoverflow.com/a/50108662/454137 help? – Pavel Shkleinik Jun 19 '18 at 20:53
  • `app.datasources.pages.selectKey(widget.datasource.item._key);` And `setTimeout(function(){ app.showPage(app.pages.listView); }, 1000);` Don't seem to change anything. I still get similar behavior: https://pasteboard.co/HqFLs1l.png The _values property seems to hold the correct row objects, just not the rows under the widget's children. – Rherma Jun 19 '18 at 21:46
  • I would suggest to try using prefetches (https://developers.google.com/appmaker/models/datasources#prefetch). If you are using List inside List, then your binding will look like this: `@widget.parent.datasource.relations.RelationName` - in simple bindings view it will look like `MainModel: RelatedModel (relation)` (by the way it will be the same for a List inside a Panel/Page binded to MainModel's datasource). – Pavel Shkleinik Jun 19 '18 at 23:29
  • I've actually already tried that - if I understand correctly in the example above I would have a prefetch on the `roles` datasource for the `permissions` relation and then on my list of permissions I would have the parent panel with datasource `roles` and the list datasource `@widget.parent.datasource.relations.permissions`. Still doesn't seem to change anything - `list.children._values` is correct but not `list.children`. – Rherma Jun 20 '18 at 14:14
  • Why do you need `list.children`? It seems that you have all rows rendered correctly. – Pavel Shkleinik Jun 20 '18 at 18:44
  • If, for example, you wanted to iterate through those rows and extract some text box's content or some other widget property for each row. I now know that this is done through `list.children._values` but I don't understand why the rows would be rendered correctly and `list.children` still contain the old rows (with null values). – Rherma Jun 21 '18 at 14:44
  • Why wouldn't you use `onDataLoad` row's event for this purpose? It will ensure that row is created and corresponded record is loaded. And why would you read data from UI, but not from the data? `ds.load(function() { ds.items.forEach(...); });` – Pavel Shkleinik Jun 21 '18 at 16:48
  • In reality the list is read from a datasource of options, each with a name and each row prototype having a text box where users can enter a reason for requesting that option. When the submit button is clicked I would like to iterate through `widget.children` to extract those text boxes' values for insertion into another table. That's why I can't use the row's onDataLoad event (the rows themselves are correct, just not their parent's children). – Rherma Jun 21 '18 at 20:27
  • Why don't you use list of Custom Properties (https://developers.google.com/appmaker/ui/binding#custom_properties) or datasource in Manual Save mode (https://developers.google.com/appmaker/models/datasources#manual_save_mode) to populate multiple draft items and bind them to the list's textboxes? – Pavel Shkleinik Jun 21 '18 at 20:43
  • I can try that, you're saying for each row create a draft item and then on submission persist them? And bind the text box to a field in that draft item? How would that work for relations then? Those draft items are related to another table so wouldn't I need to iterate through those items to add them to the relation? – Rherma Jun 22 '18 at 14:49
  • `ds.createItem(); ds.item.Parent = parent;` – Pavel Shkleinik Jun 22 '18 at 15:16

1 Answers1

0

Have you tried re-loading the related items using the item._load method? Perhaps that can force a reload of the current item's related items.

See here:

https://developers.google.com/appmaker/scripting/api/client#Record

_load( callback:Function)

This is also used in the Project Tracker template app to load an item's history (EditItem client scripts line 100). See here: https://developers.google.com/appmaker/templates/project-tracker/

bbx
  • 108
  • 9
  • Yes, I've tried loading the relation and setting a prefetch. Both don't seem to change the behavior. I've also tried to force reload the datasource but it doesn't change either. – Rherma Jun 19 '18 at 21:43
  • Also if it were an issue with the relation I don't think the new rows would ever load, since the relation itself would be null. That doesn't seem to be the case: the new values load just the list widget's children are incorrect. – Rherma Jun 19 '18 at 21:54