6 Replies Latest reply on Oct 19, 2015 7:55 AM by golife

    Dynamic navigation using portal where a portal row points at the current record

    golife

      I am working with FileMaker 14.v2 (with a server-client environment for 5 users, small business)

       

      To me and my client it makes sense to see the list of selected/filtered and found records not only in detail view, but at the same time present them in a kind of "list view" inside a portal without having to navigate back and forth between a detail and list view. Because then the user looses focus on the context. I strongly avoid opening secondary windows especially on our Windows only platform since the application window then will fall in to pieces of windows (FileMaker has not fixed this since 30 years.)

       

      Either all or filtered sets of records are visible in the list in the portal and the user can either navigate through the list to select the desired record, of move with going next, previous, or searching using any method.

       

      This means updating the portal whenever the user is on a detail record, and also hilite the associated portal row.

       

      (Using ExecuteSQL is fun, but requires FileMaker to be aware of the found set from the SQL query and filter accordingly the found set which adds complexity. Also everything must be performance improved since this must also work on the WAN and LAN from server. Here virtual lists would have to be used, and the selection must also apply to FileMaker selecting. It would just be great if there was a portal which does not depend on a relationship, but on a simply list of text values and kind of "virtual" fields defined outside of table definitions but accessible. It should not be too difficult for FileMaker developers to implement.)

       

      Coming back...

      Probably my solution is not a very good enough one, and that is why I am asking. Maybe there are better ways?

       

      Basically what I do:

       

      - Use a summary field "List of" which collects a return-delimited list of id numbers (here project numbers in text form) on the fly.

       

      - Copy this list to a global field which has a relationship with the base table using these ids. So, the list of project ids contained in this global field relates to project ids in the base table and filters those records which are present in the global field. 

       

      This list of ids always represents the found set. It seems to be a fast way. When made visible in a portal, the user can navigate through the portal and, using navigation to a related record will arrive at the desired record of the base project table.

       

      Problem 1: The selection of the portal row does not maintain the selected record. There is no visible synchrony between current record and the selected portal row. What I do is copying the project id present in the portal row to a mark field in the base table. This establishes a condition by which conditional formatting of a field or button in the portal row is triggered. At the same time I must ensure that there are no other marks left in the mark field of the base project table before I mark the current record (otherwise there will be multiple visible rows conditionally hilited), and therefore I am first deleting any left ones overwriting them with empty using "Replace Field Contents" script step.

       

      How to find the portal row associated with the current record? The only safe method I found was freezing the window (for speed reasons) and looping through the portal rows comparing the project id of the current record with the project id of the related same record visible in the portal row. Once found, I have to activate the project row selecting a  field there and then I get the portal row number of the selected portal row with Get (ActivePortalRowNumber).

       

      Problem 2: The user can find this current record (or records) also using the standard navigation controls FileMaker provides, or use standard searching. So, I must ensure that the portal list will also update in such situations. The one way doing this would be through triggers such as "on record load" using Layout triggers. Problem: Such triggers always fire, and implementing my own controlled find/filter functions will be called also from this trigger which resulted in recursive calls in my case.

       

      So how to make sure that a portal row is hilited synchronizing ALWAYS with the current record? How to make the portal row aware that it is pointing at the current record of the detail view in ANY given circumstances and be hilited?


      Problem 3: It is not enough that the portal row it is hilited for the current record. It should also be visible. Hiliting is of no value when it is not seen. The portal row pointing to the current record may sit at the far end of the portal list. The visibility is a problem when moving through records using standard ways. And trying using layout triggers would slow down performance very much. Implementing my own search, it is controlled more or less. If one record is found then only one record is present and it is easy. If multiple records are found I try to hilite the first row in the portal and go to the associated record. Otherwise using my own navigation buttons for moving through found sets allows to at least make the pointing record visible with some scripting.


      QUESTION

       

      Has anybody done this using another method? What method would be the best or better?

       

      Here is a picture of what it looks like for a filtered set of records in my test application.

       

      M08.3.JPG

       

      Regards, Roland

        • 1. Re: Dynamic navigation using portal where a portal row points at the current record
          erolst

          Maybe I misunderstood your requirements #1 and #2, but highlighting the portal row that corresponds to the current record in a self-join requires simply the predicate

           

          PortalTO::primaryKey = LayoutTO::primaryKey

           

          as CF calculation.

           

          Especially in a multi-user environment you want to avoid using flag fields.

           

          As to #3: if you can get a list of IDs of the portal IDs that is sorted the same as the portal (which presumes the portal must not be sorted differently from the underlying relationship), you can calculate the position of the current record's ID in that list, and use that position as a parameter “Go to Portal Row”.

          • 2. Re: Dynamic navigation using portal where a portal row points at the current record
            golife

            Thank you for the quick answer).

             

            I was thinking I may be "over-doing" something here. I will you solution.

             

            Requirements only:

            - Show found set in portal

            - Show associated portal row with current record highlited

            - Show current record to be visible

             

            Roland

            • 3. Re: Dynamic navigation using portal where a portal row points at the current record
              golife

              I have been checking out your suggestion, dear Erolst.

               

              First of all, in absence of FileMaker Advanced (I first have to get this), custom functions are not yet possible for me. But your hint made me search for the last couple of hours, and reading a lot coming all over the FileMaker community. I found one page which really seems to have the solution I was looking for:

               

              http://www.modularfilemaker.org/module/masterdetail-2-0/

               

              It is a perfect demonstration file made by Todd Geist. He seems to be a FileMaker genius. But as I found, his implementation is also not that trivial, and I am having to spend time to figure out exactly what all his scripts are doing.

               

              And then describing the selector-connector inventions, this same functionality of dynamic portal navigation can be placed without much problems on any layout - just some simple steps to do - and reuse it.

               

              https://www.geistinteractive.com/2014/11/21/filemaker-selector-connector-video/

               

              Well, I had a few days stepping a bit inside FileMaker, even though I have seen the product 30 years ago when it was introduced from a French company, and we used or first Macintosh 1 and 2, and did some smallest funny work with it not paying and serious enough attention.

               

              Nevertheless, just out of curiosity, your argument avoiding a mark field in a multi-user environment had actually struck me most. That was really a bad idea, and I did not think about it when doing it. What I am thinking now out of curiosity is another maybe worse idea in using a repeating field where one repetition is used for each separate user as mark - a nightmare to manage I assume - and another solution would be a combination of user id and mark field so that a marked field belongs to one user only, and it is unmarked when the user leaves the record.

               

              Well. that is all nonsense and I will try to follow the path of selector-connector, with a transaction model, and integrated navigation model plus using portals for navigating the found set. If that is intellectually mastered, it may be the blueprint for all serious application work.

               

              So, once again, thank you for the hint and making me work.

              • 4. Re: Dynamic navigation using portal where a portal row points at the current record
                erolst

                Hi Roland,

                 

                sorry for confusing you with CF; I meant “Conditional Formatting”, rather than "Custom Function".

                 

                btw, you can use any CustFunc's logic inside a regular function (need to pass the CF's expected arguments another way) as long as it is not recursive – and even then, there is a workaround.

                 

                golife wrote:

                What I am thinking now out of curiosity is another maybe worse idea in using a repeating field where one repetition is used for each separate user as mark - a nightmare to manage I assume - and another solution would be a combination of user id and mark field so that a marked field belongs to one user only, and it is unmarked when the user leaves the record.

                 

                Right; but the easiest solution* is to use a global $$variable per record. Variables are specific to the user / the session, and by using e.g. the repetition to store a record's primaryID, you can dynamically create and query $$variables to trigger a CondForm calculation.

                 

                So

                 

                PortalID::primaryKey = $$HighLighter[primaryKeyOfLayoutID]

                 

                where $$HighLighter[primaryKeyOfLayoutID] holds a value that is the primary key of the portal table record that is selected in the portal for a layout table record with primary key primaryKeyOfLayoutID.

                (Do not say that fast three times in a row …)

                 

                golife wrote:

                Well. that is all nonsense and I will try to follow the path of selector-connector, […] If that is intellectually mastered, it may be the blueprint for all serious application work.

                 

                *Easiest, unless you have a ready-made blueprint, that is …

                • 5. Re: Dynamic navigation using portal where a portal row points at the current record
                  golife

                  Thank you again, Erolst, for taking the time once again.

                   

                  Understood!

                   

                  Yes, using a global is the right choice here even though I was told once to be careful with globals.

                  I just have to change all using globals and eventually make them repeating.

                   

                  Roland

                  • 6. Re: Dynamic navigation using portal where a portal row points at the current record
                    golife

                    Wanted to give a feedback regarding testing ...

                     

                    Well, I tried the template "MasterDetail" from Todd Geist and we implemented that. It works. The drawback: It is complex in itself with lots of functions and objects to maintain. As a generic component - I do not know. Possible, but not that easy.

                     

                    I was looking for a much more light-weight implementation of this "Master-Detail" scenario to be implemented on many layouts.

                     

                    Erolst has given the right direction. And my original work went into that direction.

                     

                    Someone somewhere posted a technique, a work-around (I forgot who and where), a "hack", which allows to directly associate the summary field "list of" with a self-join. It works well. When the summary field "List of IDs" is first made to be a text field and this text field is joined with the ID of the same table in a self-join, and once the relationship is established, it is changed to become a summary field of type "List of" - then THAT WORKS! No need for a global, no need for copying data, no need for doing anything else.

                     

                    The summary field contains the list of IDs which join with the ID of the same table depending on the current selection - and it does not matter how the found set has come about. Great!

                     

                    • So, therefore, the found set can then easily be represented in a portal and with a "go to related record" step also navigation is not a problem.
                    • To have a synchronized highlighting of that portal rows associated with the current record can be done through conditional formatting pointing to the current record whose ID is placed into a global variable when moving from record to record (OnRecordLoad trigger).
                    • To have portal rows sorted according to the records is just sorting the portal by record number (calculated in the self-join relationship). Neatly portal rows are synchronous with the records of the found set.
                    • To make associated portal rows become visible, it is possible looping through the portal rows to find the correct one and with "go to portal row" when found.

                     

                    Advantages

                     

                    • No need for any "virtual table" as with Todd Geist's implementation.
                    • No need for complex scripts.
                    • No need for very special objects to refer to which must be placed to the layout.
                    • Just one self-join table using a little "hack", and all else is functionality around it.
                    • It should work in a multi-user environment, (even though I am not sure about the summary field in such scenario.)


                    Thoughts


                    • To keep the associated portal row visible at all times and not be hidden deep down in the portal rows for me so far means looping through the portal rows to find the portal with the same related ID as the ID of the current record. Maybe there is a better way doing that?
                    • There is the need though to refresh the portal when navigating as a last script step.

                    All looks nice but ...


                    The problem appearing now is when the user chooses to "Show All" records. There is no "OnRecordLoad" working for this situation. I did not find a way to track any "Show All" message. (There is no way here to change to a custom menu to handle the "Show All" function.)


                    I implemented an "On Timer" trigger - firing each second or each two seconds - but that does not seem to be a good solution even though it works. Because it strongly interferes users to do other work when it fires. It is ugly.


                    Any suggestion?


                    And I am also thinking of making this as generic as possible. But I do not see a way that would make it even more easier than it is. Or?


                    Greetings

                    Roland