On 8/17/16, 5:09 PM, "Alex Harui" <[email protected]> wrote:
>Peter, > >I like the idea of declaring the controller as a bead in the view. > >But shouldn't the controller be able to know about (have references to) >the View as long as the View doesn't know about the controller (which it >shouldn't, IMO). As soon as I added the controller has a bead, the circular dependency was formed. I had started with the previous changes where I had removed the circular dependency - the controller was just referenced in the CSS. > >The view should dispatch events (for example, converting a "click" on a >checkbox to "LicenseAcceptanceCheckboxSelectionChange" but it should be ok >for the controller to have a reference to the view to access data from >the widgets, validate them, and then apply them to the model. Passing >data via events means copying data and references and the controller code >might need other values from other widgets in the view. It also means >fewer custom event classes. I thought using custom events was a nice way to separate the concerns. What do other people think - do you use a lot of custom events in your application code or do you get some simple event and then go grab the data out of the controls? > >IMO: >Models should not reference views or controllers >Views should reference models but not controllers >Controllers should reference models and views. I don't see how you can remove the dependency when the View MXML explicit references the Controller MXML in the <js:beads> list. Perhaps we have something wrong in the fundamentals then. > >I think there aren't circularities in that set. > >Thoughts? >-Alex > >On 8/17/16, 1:46 PM, "Peter Ent" <[email protected]> wrote: > >>This is what I'm concluding in MobileTrader: >> >>MobileTrader has "sub-views" for WatchList and Alerts. Each of these >>sub-views has its own controller (WatchListController, >>AlertViewController) which are responsible for taking events from the >>view >>and updating the model. >> >>The first task is to get the controller to know about the model. We are >>talking about the model holding the data, not the FlexJS "model" which >>most components have that hold values for the component's properties. So >>I'm calling this the "dataModel". The circular dependencies are arising >>because the controllers are directly references their views and grabbing >>data out of the view. >> >>I removed the attachment of the controller to the sub-view from the CSS. >>In the view (eg, WatchListView), I explicitly name the controller bead >>and >>use data binding to pass in the model the controller needs to use. >> >><js:beads> >> <js:ViewDataBinding> >> <controller:WatchListController dataModel="{dataModel}" /> >></js:beads> >> >>(Note: The WatchListView's dataModel is set using data binding from the >>outer MyInitialView). >> >>Then I removed all references to WatchListView from WatchListController. >>This caused several errors because WatchListController was referencing >>the >>view to get to the data on the screen which needed. For example, it >>needed >>the symbol to watch: >> >>view.symbolName.text >> >>Since WatchListController now knows nothing about the view, I created >>custom events for the WatchListView to dispatch that contained the data >>the controller needs. So when the Set button is picked, the button's >>event >>handler in WatchListView now does: >> >>var event: new AddSymbolEvent(symbolName.text); >>dispatchEvent(event); >> >>The WatchListController is looking for this event and can use the symbol >>value from the event without referring to the view at all. >> >>I applied this technique to the AlertsView and AlertsViewController. All >>in all, the code got cleaner and more readable. The view takes care of >>updating the view UI components and the controller takes care of updating >>the model. >> >>The pattern now works something like this: >> >>1. Give the sub-view controller bead bindable get/set methods for the >>dataModel it needs. Don't forget to add the ViewDataBinding bead to the >>sub-view class. >>2. Create custom events to pass data from the sub-view controls over to >>the controller. >>3. Have the controller set up event listeners for these custom events in >>its strand-setter; the "strand" is really the sub-view. >>4. When the view receives some user interaction, have it create a custom >>event with the data and dispatch it. >>5. The controller will receive the custom event and modify the model. >>6. The view can update the UI controls (eg, textField.text = "") after >>sending the event. >> >>For simpler projects, like the TodoListSample or DataBindingExample, the >>controller can implement IDocument and, when the "document" (aka, >>Application) is set, it can get the reference to the application data >>model and set up listeners for it. >> >>I will be checking these changes in shortly today or tomorrow (USA, EDT) >>morning. >> >>‹peter >> >>On 8/16/16, 8:33 PM, "Alex Harui" <[email protected]> wrote: >> >>> >>> >>>On 8/16/16, 2:20 PM, "Peter Ent" <[email protected]> wrote: >>> >>>> >>>>Hi, >>>> >>>>I wanted to post what I've done before I commit the code to get an idea >>>>if >>>>this is the right approach. >>>> >>>>Background: a circular dependency is when class A references class B >>>>which >>>>references class B. Pretty simple. >>>> >>>>In many of the FlexJS examples, there are circular dependencies between >>>>the application class and the application's controller. For example, >>>>DataBindingExampleApp references its controller, MyController, which >>>>has >>>>a >>>>reference back to the application. Likewise, the TodoListSampleApp >>>>references its controller which holds a reference to the app class. The >>>>objective in both examples is provide the controller with a reference >>>>to >>>>the model. >>>> >>>>In both of these cases, my solution is to remove the explicit reference >>>>to >>>>the application (eg, DataBindingExample) in the controller and replace >>>>it >>>>with the Application class and then extract what it needs into local >>>>variables. >>> >>>The above sounds like a good plan. >>> >>>>However, MobileTrader is bit trickier. MobileTrader has several mobile >>>>"views" and each has its own controller. The circular dependency in >>>>this >>>>case is between these secondary views and their respective controllers. >>>>The way I approached this was to make a new interface in the >>>>MobileTrader >>>>example src, called "IBeadControllerWithModel" which extends >>>>IBeadController and adds a getter/setter for a model. Now the view can >>>>simple reference its controller using this new interface and set the >>>>model >>>>so the controller can now modify it. >>> >>>I don't know this code very well, but I poked around a bit and it >>>appears >>>the view knows about the controller only because it is assigning the >>>model >>>to the controller. IMO, the controller should pick up the model from >>>the >>>strand. If it is a timing issue where the model isn't set when the >>>controller is put on the strand, the controller should be able to look >>>for >>>a modelChange event or maybe even initComplete. >>> >>>Thoughts? >>>-Alex >>> >> >
