as well:
index.xml
<Alloy>
<Window>
<Require src="someRequire">
<Label>child label</Label>
</Require>
</Window>
</Alloy>
someRequire.xml
<Alloy>
<View id="content"/>
</Alloy>
someRequire.js
var args = arguments[0] || {},
// args.children contains the elements under the <Require> elements, if any
children = args.children || [];
// add child views to content
_.each(children, function(child) {
$.content.add(child);
});
original
Following the discussion at https://groups.google.com/d/msg/appc-ti-alloy/8PVVSE1UzXE/x6frOeTZGd4J I propose to add support for child elements in <Widget></Widget>
elements in Alloy XML views.
The purpose of this would be to get a reference of these elements from within a widget that doesn't return a view of it's own, but is designed to act upon others. It would function in a way not that different from the existing support for getting a reference of the Widget parent element using this.parent
.
*Example XML View*
<Alloy>
<Window id="myWindow">
<Widget id="myWidget" scr="my.alloy.widget">
<TableView id="myTable">
<TableViewRow title="my row" />
</TableView>
</Widget>
</Window>
</Alloy>
*Would be compiled to*
...
$.myWidget = Alloy.createWidget("my.alloy.widget", "widget", {
id: "myWidget"
});
$.myWidget.setParent($.__views.myWindow);
$.myWidget.setChildren([$.__views.myTable]);
...
*Notes*
Since the widget does not provide a view it's stored in $.ID
instead of $.__views.ID
. Because the widget could contain multiple child elements the methods is setChildren
and it accepts an array.
Attachments
File | Date | Size |
Screen Shot 2013-10-25 at 4.19.39 PM.png | 2013-10-25T20:35:20.000+0000 | 36179 |
Screen Shot 2013-10-25 at 4.19.47 PM.png | 2013-10-25T20:35:20.000+0000 | 75036 |
Comments
- Davide Cassenti 2013-04-17
Is there any progress about this?
- Tony Lukasavage 2013-04-17
No, not at this time. There's a number of high priority tickets I need to get to before I'll be able to get back to this one. I don't have a reliable ETA for it yet.
- Fokke Zandbergen 2013-07-21
Huh? How come Pedro is now the reporter? I thought I was..
Anyway, another use case I would like to use this for is:
<Alloy>
<Window id="container">
<Widget src="NavigationGroup">
<Window id="primary">
<Label>Hello World</Label>
</Window>
</Widget>
</Window>
</Alloy>
The widget would return a Ti.UI.iPhone.NavigationGroup
on iOS, while just open Window#primary
on other platforms, so you have a cross platform solution. Additionally, both the iOS and other implementation could add additional methods for closing the last window or close all but the first.
- Fokke Zandbergen 2013-07-21
Same is true for
<Require />
. A sample use case would be to have a view/controller that is used in multiple other views to wrap their content in a custom popup, without having to repeat the same view elements in every of these views:
View using the wrapper:
<Alloy>
<Require="snippets/popup">
<Label>Hello world</Label>
</Require>
</Alloy>
View of the wrapper:
<Alloy>
<Window>
<ImageView image="x.png" onClick="closeDialog" />
<View id="content" borderSize="10" borderColor="black" height="Ti.UI.SIZE" left="10" right="10">
</View>
</Window>
</Alloy>
Controller of the wrapper:
function closeDialog() {
$.getView().close();
}
exports.add = $.content.add;
The above controller code also shows that the controller should expose an add
method that receives the first level of wrapped view(s) so it can consume them in whatever way it needs to.
- Tony Lukasavage 2013-07-22
[~fokke] pedro probably moved it from TC to ALOY, and sometimes that inadvertantly reassigns the reporter. I fixed it.
- Ronald Treur 2013-07-23
Thanks again Fokke for bringing this up! I'm very happy to see it will be included in the near future.
I originally wanted to wrap the Ti.UI.Window in a widget, but had to reside to windows registering themselves with a custom manager upon creation. This fix/feature will make sure use-cases like this one will utilize the full potential of Alloy's XML Views.
Kudos to all involved!
- Fokke Zandbergen 2013-07-27
It seems to work for me by changing just a few lines:
Alloy.Require.js#26
//U.die('<Require> elements may not have child elements.');
Alloy.Require.js#122
symbolic: args.symbol,
symbol: args.symbol + '.getViewEx({recurse:true})'
default.js#98
code += (args.parent.symbolic || args.parent.symbol) + ".add(" + args.symbol + ");\n";
I'm sure there are things to take care off, but this will expect an add
method to be exposed by the Widget/Controller, which could then do whatever it wants with the added child view(s).
- Tony Lukasavage 2013-08-07
I'm starting to think about this one, and I think I want to put all the effort onto the widget developer to determine what is done with the children. I don't think a new add() API needs to be introduced for the requires/widgets, it should be the responsibility of the widget designer to handle them.
here's a very basic gist of how I would imagine you would implement this behavior, assuming that Alloy provided a "children" argument to widgets/requires:
https://gist.github.com/tonylukasavage/6178871
I'd like to keep the implementation simple to see what particular use cases rise up around it. In the future we could designate an XML attribute on or in the widget that identifies the "container" component so that you don't need to assemble the view hierarchy programmatically, but I think this is a good first step and that type of functionality can easily be added later if this proves useful.
Thoughts?
- Fokke Zandbergen 2013-08-08
Looks pretty solid, you could even support doing stuff like this:
<Alloy>
<Window>
<Widget src="myWidget">
<SomeProxy>
<Button>Hi</Button>
</SomeProxy>
<AnotherProxy>
<Button>One</Button>
<Button>Two</Button>
</AnotherProxy>
<Button>Root</Button>
</Widget>
</Window>
</Alloy>
To be passed as:
children: {
SomeProxy: {
children: [
[object Ti.UI.Button]
]
},
AnotherProxy: {
children: [
[object Ti.UI.Button],
[object Ti.UI.Button],
]
},
children: [
[object Ti.UI.Button]
]
}
This might seem like a bit too much, but imagine having a widget taking a table, a view for the Pull to Refresh, another for the Infinite Scroll.
- Ronald Treur 2013-08-08
Looks like a very flexible solution to me, I like it!
- Tony Lukasavage 2013-10-25
PR: https://github.com/appcelerator/alloy/pull/258
test app: https://github.com/appcelerator/alloy/tree/master/test/apps/advanced/require_children
Functional test should include the following for all supported platforms:
Run the app
Ensure that no compile time or runtime errors occur
Ensure that the resulting UI is composed of the child elements contained in the and elements in the app
For reference, the iOS 7 screens should look like the attached screenshots (ignore the missing tab titles, its a result of TIMOB-15581)
All jake test:all
tests should pass as well.
- Fokke Zandbergen 2013-11-21
- Tony Lukasavage 2013-11-21
[~fokke] I think a new ticket that better details the format and expected behavior would be appropriate. I'm a little foggy on what you are trying to do there, if only because I think you are using the word "proxy" differently than we typically use it. If you do create a ticket, mention this one and I'll make sure they get linked.
- Fokke Zandbergen 2013-11-22
[~tlukasavage] here it is: TC-3318
- Federico Casali 2013-12-03
Verified fixed.
TiSDK 3.2.0.v20131127194046
CLI 3.2.0-beta
Alloy 1.3.0-beta
Titanium Studio 3.2.0.201311262027
iPad OS 7 and simulator
Android Google Nexus Galaxy 4.3
MobileWeb (for sample #2)
Closing.
- Ingo Muschenetz 2014-08-28
[~fcasali] should this be closed?
- Fokke Zandbergen 2014-08-29
Yes
- Federico Casali 2014-09-02
Yes, it should. Closing.
JSON Source