Hi all,
I have just wasted an hour trying to work out why the tabpanels on a new form displayed as gray boxes. Then I realised that the form was a list view, and changed it to a record-view. What about adding a message on the gray panel saying “Not allowed in listview?”
I too ran into this, and while I second Christian’s suggestion, I would add this…
Tabpanels and nested tabpanels are a very powerful and well-implemented feature of Servoy. I think it would be very useful to be able to use them in list views and perhaps multi-line table views. To not allow them is to sell this brilliant feature short. It also creates an inelegant exception in the behavior of these views which, in all other respects, seem to display exactly what is on the form.
I could see where it could be a real memory hog if used irresponsibly, but that’s something the developer could be made aware of and guard against.
Just my two cents.
I have a number of tabpanels which show forms using listviews. It is always a related set of child records and the number of records is never very large but they show just fine. I think the idea of not using list views on tab panels was always just ‘advised’ so as not to run into problems if the number of records was very large. I think it has always worked though - I’m sure I have been using this same tabpanel set up for over a year. I think I remember seeing a comment from Johan recently that even the advice about being very careful in using a listview with tabpanels is being relaxed because of some change that Servoy has implemented.
Hello John - I believe we were both at the Servoy World presentation in San Mateo last November.
What I am referring to is not tabpanels displaying listviews but rather the opposite, a listview displaying tabpanels. In other words, I create a form, I put a tabpanel on it and then I display the form in list view. That is what is not currently supported.
Oh, OK. I get it. When I saw the note about ‘memory hog’ I remembered the warning note that Servoy used to put out when using tabpanels that DISPLAYED listviews and that was what I thought you meant.
I’m curious as to when or why you would want to have a ‘list view’ that would also have a tab panel on it. I always think of a listview as something that I use when I want to display quite a few records on the screen and generally speaking this always means each row is just one or maybe two fields high. And if that is the case, I won’t have the room to display more information such as in a tab panel. When I want the features of both (being able to show and select from many records and yet being able to give a lot more detailed information on the same screen for each record), with Servoy I use a custom controller or another tabpanel. That custom controller or tabpanel is in list view. Then when a record is selected from the custom controller or the tabpanel, the rest of the screen displays the details of the selected record with tabpanels, portals and whatever. What is it that you want to display in list view but still be able to show a tabpanel for each individual record? What advantages does listview give you over recordview?
(And yes I was at San Mateo. How are things going?)
[/i]
Here are some scenarios where displaying a list of records each with its own list of related items would be useful. These are just off the top of my head:
- A manager’s control panel view showing a list of all his/her direct reports and all the projects each one is currently working on with status info.
- An auction site showing a list of items for auction with a bid history list for each item.
- A list of cars allowing the user to specify for each one a make and model using dropdown lists, where the list of models is dependent on the selected make
- A time billing system where users enter their time in a list, selecting the client from a dropdown, which populates a second dropdown with the list of projects ongoing at that client.
The first two examples can be done using portals, but as far as I know the rest are either impossible or involve a lot of coding I don’t yet know how to do. Yet ALL of them could be done easily using tabpanels and nested tabpanels if they worked in list/table views.
If anyone can correct me on this please do.
Dislcaimer: I don’t want to sound too negative here - Servoy has many many strenghts and I haven’t gone out of my way to point those out on this forum (hey there’s an idea - how about a “Things I Love About Servoy” section? Or is that too 60s hippy-dippy-touchy-feely?
). This just happens to be an area where I think it could be improved and thereby give the developer a lot more power. I used to do a lot of development in Omnis and it allowed me to do these things so I kind of miss it.
Use HTML, done. As many levels as you want - variable related children per row, etc.
- A list of cars allowing the user to specify for each one a make and model using dropdown lists, where the list of models is dependent on the selected make
- A time billing system where users enter their time in a list, selecting the client from a dropdown, which populates a second dropdown with the list of projects ongoing at that client.
Actually Adrian, in addition to what Bob has said, these examples you list are also dead easy to do in Servoy even without HTML. Basically you just use ‘Custom’ valuelists in which the valuelist is populated based on the user’s selection in the first field. Here for example when one of our MDs is looking at a case they might decide to order additional ‘stains’ in order to arrive at a better diagnosis. The first column/field then has a custom valuelist that gets populated with whatever ‘material’ is available on that biopsy (this is generated by a query of millions of records but the results show up instantaneously). The MD makes his/her selection from that valuelist. Then depending on what material is chosen the second valuelist gets generated allowing the MD to choose what tests they want done. Essentially these custom valuelists are created with SQL queries and then use ‘application.setValueListItems’ to populate the valuelist (use the ‘move sample’ feature in the Method editor for further explanation).
john.allen:
Actually Adrian, in addition to what Bob has said, these examples you list are also dead easy to do in Servoy even without HTML. Basically you just use ‘Custom’ valuelists in which the valuelist is populated based on the user’s selection in the first field. Here for example when one of our MDs is looking at a case they might decide to order additional ‘stains’ in order to arrive at a better diagnosis. The first column/field then has a custom valuelist that gets populated with whatever ‘material’ is available on that biopsy (this is generated by a query of millions of records but the results show up instantaneously). The MD makes his/her selection from that valuelist. Then depending on what material is chosen the second valuelist gets generated allowing the MD to choose what tests they want done. Essentially these custom valuelists are created with SQL queries and then use ‘application.setValueListItems’ to populate the valuelist (use the ‘move sample’ feature in the Method editor for further explanation).
John,
Your post prompted me to take a closer look at this and you are right - it is possible to have interdependent valuelists in a list or table view where the selection in one valuelist affects the contents in another. If you 're lucky you can even do this without getting into the setValueListItems function by using the ‘related values’ option in your valuelist definition in the valuelist dialog. I had missed that, because with the datamodel I’m working with, I can’t find a way to make that happen. Here’s what I’m trying to do:
I’m creating a rudimentary time-billing system for the purpose of learning Servoy. I’ve attached a bare-bones datamodel showing the tables pertinent to this discussion.
CLIENTS have one or more PROJECTS.
CONSULTANTS are assigned to PROJECTS via a table called ASSIGNMENTS thus establishing a many to many between CONSULTANTS and PROJECTS.
Note that I have no direct connection from ASSIGNMENTS to CLIENTS, and I’d rather not create one because that connection is already present in the PROJECTS table.
Now I want to create a list or table view of ASSIGNMENTS where users can add/edit/delete assignments. In each row of the list the user should be able to select a CLIENT from a dropdown list, and that will populate a neighboring dropdown list with that CLIENT’s PROJECTs.
I have found that I can’t do that with this datamodel because Servoy lacks a container to store the client ID from the client dropdown list. I can’t seem to specify CLIENTS.ID as that container because it is two hops away from ASSIGNMENTS (the dataprovider property of a field doesn’t let me specify a chain of relations two relations deep). The only way I can see of making it work is if I create a real CLIENT_ID column in ASSIGNMENTS, which denormalizes my datamodel.
As always, if anyone has actually read this far and can find a way to do this I’d like to know.
Hi Adrian,
Again several ways of doing this in Servoy, I’d probably do it something like this:
For creating a NEW Assignment row I’d have a global field, g_client_id, with a valuelist based on all CLIENTS.IDs. After selecting one I would then autogenerate a valuelist for ASSIGNMENTS.PROJECT_ID based on the selected CLIENTS.ID (something like "SELECT PROJECTS.ID FROM PROJECTS WHERE PROJECTS.CLIENT_ID = " + g_client_id). (The whole application.setValueListItems is really, really easy to use once you get used to it, by the way, and very powerful and economical. You can use the same ‘empty’ valuelist throughout your solution too by the way as long as it isn’t used on the same form, simply populating it with whatever is relevant on that form or within that context.)
For EXISTING rows in ASSIGNMENTS I’d just create a calculated field (unstored) on Assignments called Client_id. I’m presuming you have created a relationship between Assignments to Projects and Projects to Clients (just because the relationship exists the other way around don’t presume it exists in reverse). Let’s call the first relationship Assign_to_Project and the second Project_to_Client. Then have the calculation for Client_id return: Assign_to_Project.Project_to_Client.ID. This keeps your datamodel the same but shows all the necessary information in listview form for editing or deleting your ‘assignment’ rows (you use the global field just for adding new rows).
Thanks as always for tackling this, John.
I’ve tried some of these approaches in the past and here’s what I found.
I’m not sure how you would have me switch between the global (for a new record) and the calc (for existing records), perhaps by showing one and hiding the other, but in general what happens is that such a change takes effect on all rows because all rows are based on the one form. So for instance if upon creating a new row I switch to the global, that will impact all rows and my valuelists in all rows will display the same thing as in the new row. I know of no way of making such a change affect only one row - do you?
I guess I don’t understand why you would have the global in a list view row. What’s the point? You only use the global when you are adding a new record and that is the only time you would need the list of all clients to select from as I understand it from your description. I would have the global either in the header, the footer or in the controller. The calculated client_id is what shows in each row of the list view.
John,
A picture is worth a thousand words. Attached is an example of the interface I want. When you click add in the “Projects Assigned” section, a new row is added at the bottom of the list and you make your client & project selections the same way you would if you were editing any row in the list. Nice, simple interface. It’s working great now, but I had to add a client_id to my ASSIGNMENTS table to get there.
Great! The main thing is that you are happy with it. If it was important for you to keep the normalized structure and using your example I would have put the global just to the right of the ‘Add’ button. When clicking the ‘Add’ button the global would show up to select the client_id (otherwise hidden). After selecting, the new record would be automatically created and the cursor moves to the ‘Project Name’ field in the new record with the dropdown list already created based on the client_id selected. But I’m with you in that a lot of times one can get too anal about normalizing data!