In prior versions of 4D one of my favorite uses of array based listboxes is for displaying lists of things and including a variable the user could type into to filter the list as they typed. The technique involved two things:
the listbox had a 'hidden' array specified the code for the search variable fired with the On After Edit form event The code simply looped through the array being filtered and set the hidden array depending on whether the string was found or not. It looks like this: $search_str:=Get Edited Text+"@" For($i;1;Size of array($nameArray)) aHidden{$i}:=$nameArray{$i}#$search_str End for I was updating a form that uses this trick to be a collection based listbox. Collection based listboxes are so much more dynamic and flexible I think it's worth the effort to convert them in most cases. But that's another post. This post is about how to get the same effect since a collection based listbox doesn't have the hidden array. The first step was to identify what I was really trying to do. "I want to hide some rows" I thought. Because that's what I did before. But really what I want to do is filter the collection based on the search string. Looking at it that way the first thought was, "well, I could just re-run creating the collection." This can be too slow if the collection is built from complicated conditions. And I wish I could use the query function <https://doc.4d.com/4Dv17/4D/17/collectionquery.305-3730931.en.html> for collections but it returns a new collection. That doesn't help me because I already have the collection displayed in my listbox. And it has to be fast or the users will hate it because it slows down typing. So why not just change the listbox to show the collection resulting from the query? I typically avoid this sort of thing because in the past it meant duplicating the initial set of arrays in memory. But objects are references to the data. So having two instances of the same collection does not double the memory used. To try this out I added a new instance of the collection like this: Form.dataCollection:=Method_to_get_data // get the complete list of data Form.displayCollection:=Form.dataCollection // set the list to the display collection And changing the listbox I had already built was simple - I only had to change the expression <https://doc.4d.com/4Dv17R3/4D/17-R3/List-box-specific-properties.300-3961393.en.html> in the properties list because all the references in the listbox itself would still work because I wasn't changing the structure of the collection. So far so good. The code to accomplish the lookup turns out to be really simple: Form.displayCollection:=Form.dataCollection.query("name = :1";Get Edited Text+"@") // each element of the collection is an object. The object has a property, "name", that is being queried. // this is the equivalent of the example I began with Really, that's it. Because my display collection is selected from the data collection any changes the user makes on the listbox also 'flow' or 'update' or 'are reflected in' the data collection. That's important to remember - because the collections are references, including the listbox column assignment, a change to the root element (in this case Form.dataCollection) propagates to all other instances. If I didn't want this I could modify my collection query to make a new, separate collection. This heads off into the differences and similarities of collections and entity selections and saving data which is more than I want to get into here. I was updating a component that does stuff with method code (list the methods, show the modified date, show the method attributes, etc.). Using arrays I had to have an array for each data bit I wanted to display. With a collection I create an object that has properties for each bit I want. Takes about the same time to runs because the real work is getting the code. But working with the collection is far easier. And the code to manage all this on the form really shrank to about what you see above. There are about 12 columns in the listbox. With arrays I had to identify each one with a column and deal with all the array declarations. With a collection I only need to declare it. The listbox columns set themselves to the correct data type once I assign the data source. To summarize - converting existing structures in 4D to utilize the new language capabilities is as much about understanding what the actual task is than about manipulating code. In this case the task is to display a filtered list. The previous technique was to hide unwanted elements. The new technique is to show the desired ones. -- Kirk Brooks San Francisco, CA ======================= *We go vote - they go home* ********************************************************************** 4D Internet Users Group (4D iNUG) Archive: http://lists.4d.com/archives.html Options: https://lists.4d.com/mailman/options/4d_tech Unsub: mailto:4d_tech-unsubscr...@lists.4d.com **********************************************************************