I think of it this way: There are two main kinds of “components” known as Containers and Controls. A Container, like Panel, is intended to contain an arbitrary set of children, size and position them according to a specified layout and specified attributes on those children, and provide “chrome” around and behind the children. A Control does not take an arbitrary set of children. It might create children based on some dataProvider, but basically, you don’t control the children from “outside”.
For a Control, the division between component and skin and layout is straightforward. The layout controls size and position, and all other visual aspects are defined in the skin. The skin is a view and the component is the model (and sometimes controller). Thus the model sports properties that the skin turns into visuals.
For a Container like Panel, the division is straightforward as well. The skin contains the chrome like the title bar and position of the control bar. The layout determines the size and position of the children, but not skin.
Where it gets fuzzy is if you want to create a “template” where a Panel has some built in children but others can be arbitrarily specified. Such a thing isn’t officially supported. If you want to create a panel with a fixed set of children, I would specify them in the skin effectively making it a Control since it no longer supports arbitrary children, although you’ll see code-hinting offer to allow children to be placed within the tag. But to allow for other children to be specified, I think I would put those children in the skin in a separate Group than the contentGroup. That’s effectively what we did for ControlBar in Panel, although it allows arbitrary children as well.
So, unless you plan to offer this thing as a library to others, I’d say there is no “right” answer.
Appreciate the response. I'm travelling down the road of adding UI components to the skin file. So far OK. I'm stumbling along. For instance I wanted a control bar at the base of my sPanel and I wanted it visible in *all* states. The only way I could get that to work was to remove all of the "includeIn" designations from the content group containing controlBarGroup in the skin class file. It worked, but I'm not sure if that's the best practice.
My next question in the context of this divide between UI and controller logic is where and how do I handle UI events? If someone clicks a button that I've added to the controlBarGroup inside my skin class, where do I put the click handler? Back in the host component (sPanel) file? Seems like that's where it belongs. How do I call it back there? What's the best practice in this regard?
1 person found this helpful
Again, it depends on whether you are making a Container or Control. IOW, who specified the button in the controlBarGroup? If its a child tag of the component like it would be if you put a button in the controlBar of a Panel, then the click handling belongs in the MXML file where that was specified. If it is a child tag in the skin, then the click handling belongs in the skin. IOW, OO rules should still apply. And, if the component consumer needs to know about the click, it should be re-dispatched as some other event. For example, the close button in the title bar of a TitleWindow dispatches a CLOSE event in response to the click because that is the semantic of that click.