0

I have a tabbed dialog that has 4 tabs. The parent component is an mx:TabNavigator and each of the tab's views are custom MXML components inside an s:NavigatorContent. The data for 3 of the tabs has to be sent as one unit to a back end service. I'm trying to work out the best way to have the 3 tabs access the data that's to be sent down as one unit. I currently have one .mxml file that defines the top level mx:TabNavigator with each of the 4 tabs representing the s:NavigatorContent defined in it's own separate.mxml file to keep the file sizes fairly short. My current approach is to have each of the tabs load their data from the back end service in their creationComplete handlers and store it in a common class for the data model shared by the 3 tabs. This solution is OK except:

  1. The creation complete handler for the first tab is called on application startup even though it's not the first visible component (i.e. there are other parts of the UI that the user sees first). I'd prefer to have true lazy loading where the data is not loaded until the tab becomes visible to the user.
  2. If the user edits data on the first tab, then navigates to the second tab for the first time without hitting the apply button, changes made in the first tab are lost, because the creation complete handler of the 2nd tab will load the data model shared by the 3 tabs.

What I ideally want is:

  1. True lazy loading; data is not loaded until the user clicks on a tab and it becomes visible.
  2. Have it so that when the user hits apply on any of the 3 tabs the current entries on each of the 3 tabs is sent down to the back end service.

Thanks very much if anyone can advise on this. I can explain in further detail if needed.

fred basset
  • 9,774
  • 28
  • 88
  • 138
  • You have a misconception here about the architecture of TabNavigator, as well as good architectural principles in general. You can't guarantee that all of the tabs are created (unless you use creationPolicy="all", which wouldn't be lazy loading), but even more importantly you shouldn't be using your View's controls as a data store. You should be editing a data item in the tabs, and _that_ is what you should be sending. – Amy Blankenship Apr 25 '12 at 21:14
  • Note I've flagged this question as a duplicate of your other question, because they are in essence the same question. – Amy Blankenship Apr 25 '12 at 21:21

1 Answers1

1

I'm trying to work out the best way to have the 3 tabs access the data that's to be sent down as one unit.

Best is always subjective. The easiest way is going to be to create a single variable for your shared data, and pass that instance into each relevant tab.

In some cases you may store the data in some central location, and the use Dependency Injection to inject that data into the relevant tab components that need it. Dependency Injection is implemented by a bunch of Flex frameworks, such as RobotLegs or Swiz.

An alternate option is to use a Singleton approach or static variables on a class to share the data between your multiple tabs.

My current approach is to have each of the tabs load their data from the back end service in their creationComplete handlers

Why use creationComplete? The creationComplete event is fired after the component has completed it's layout routines and layout routines of it's children, and then everything is ready to use. I assume the act of loading more data, will force a lot of your components to have to go through their rendering process again. You may consider moving this into an earlier spot during the lifecycle, such as initialize or preinitialize.

1) The creation complete handler for the first tab is called on application startup even though it's not the first visible component (i.e. there are other parts of the UI that the user sees first). I'd prefer to have true lazy loading where the data is not loaded until the tab becomes visible to the user.

This would be expected behavior, based on the way that TabNavigators initialize. You can look at creationPolicy for more information. You can rewrite your 'load data' method to operate on the show method of the component, perhaps?

2) If the user edits data on the first tab, then navigates to the second tab for the first time without hitting the apply button, changes made in the first tab are lost, because the creation complete handler of the 2nd tab will load the data model shared by the 3 tabs.

You can force a save of the data on the hide event of the component. Or possibly on the change event o the TabNavigator.

JeffryHouser
  • 39,401
  • 4
  • 38
  • 59
  • Hi, thanks for the detailed and well informed response. I tried adding show and hide handlers to my individual tab component (an s:VGgroup), but they never seem to be called. Are there any additional steps that need to be done to get these handlers to be called? In the MXML markup for the VGroup I just added 'show="refresh()" hide="saveData()"' – fred basset Apr 25 '12 at 20:10
  • @fredbasset There should be anything additional you have to do for the events to fire. Show and Hide are both documented on the VGroup class. Show should be dispatched when the component becomes visible; and hide should dispatch when the component becomes invisible. I assume that the TabNavigator is changing the children by hiding inactive ones and display active ones as that is how the ViewStack works. – JeffryHouser Apr 25 '12 at 20:50
  • 1
    I don't think VGroup is what would be getting these events, since it can't be a direct child of the TabNavigator (doesn't implement IContainer). Try putting the handler on the NavigatorContent tag. – Amy Blankenship Apr 25 '12 at 21:19
  • Amy you are correct. The show handler is called for the s:NavigatorContent child of the mx:TabNavigator. You are so smart :) I'm going to re-work my dialog tonight so that the three tabs are in one mxml file, are created all at startup so the 2nd and 3rd tabs components are not null, and are populated once when any of the 3 tabs's show handler is called. Seems a bit kludgy but it should work. – fred basset Apr 25 '12 at 23:27