Titanium JIRA Archive
Alloy (ALOY)

[ALOY-1229] iOS: ListView filling template incorrectly

GitHub Issuen/a
TypeBug
PriorityHigh
StatusResolved
ResolutionFixed
Resolution Date2015-02-06T19:10:36.000+0000
Affected Version/sn/a
Fix Version/sAlloy 1.7.0
ComponentsTooling, XML
Labelsios, listview, listview,, listviewitem, sdk
ReporterThomas Wilkinson
AssigneeTim Poulsen
Created2014-08-13T16:47:23.000+0000
Updated2015-02-06T19:10:36.000+0000

Description

The ListView is not filling out incorrectly. The first label "#faultyLabel" should be replace with text and have a backgroundColor="magenta", but what's happening is a new label is appearing behind the next line, with its backgroundColor="magenta" and the text either not displayed or displayed out of view. Create a new Alloy project and drop the three attached files to see the issue. The ListView works correctly in Android (screenshot also attached)

Attachments

FileDateSize
index.js2014-08-13T16:47:23.000+00001218
index.tss2014-08-13T16:47:23.000+0000553
index.xml2014-08-13T16:47:23.000+0000591
listview-android.png2014-08-13T16:51:47.000+0000127366
listviewissue.png2014-08-13T16:47:23.000+0000201657
Screen Shot 2015-02-06 at 1.59.46 PM.png2015-02-06T19:08:14.000+000071675

Comments

  1. Thomas Wilkinson 2014-08-13

    Ok, I just found a workaround to this very oddly specific defect. Here’s the snippet:
       <ItemTemplate name="faultyTemplate">
       <Label id="faultyLabel" bindId="faultyLabel" touchEnabled="false"/>
       <View id="otherView" touchEnabled="false">
       <Label id="otherViewLabel1" touchEnabled="false"/>
       <Label id="otherViewLabel2" bindId="otherViewLabel2" class="rowDetailValue" touchEnabled="false"/>
       </View>
       </ItemTemplate>
       
    And in the TSS:
       "#faultyLabel": {
       left: 12,
       text: "dummy text",
       backgroundColor: "yellow",
       right: 12,
       height: 16,
       color: "black",
       font: {
       fontSize: 16,
       fontFamily: "Helvetica",
       fontWeight: "bold"
       }
       }
       "#otherView": {
       left: 0,
       right: 0,
       top: 40,
       height: 20,
       }
       
    Here’s what I did: 1) I removed the wrapper view that has the vertical layout. 2) Instead of using the vertical layout, I laid out the elements by hand. This issue does not affect any Labels in the ElementsOfListView app, so there is something very oddly specific about the arrangement of the Labels and Views with layouts that is tripping this defect. I am reducing the severity in light of this workaround.
  2. Thomas Wilkinson 2014-08-19

    The client has requested this be fixed in the next or next-to-next SDK release.
  3. Ingo Muschenetz 2014-08-25

    [~twilkinson] Is it possible to get a non-Alloy test case for this?
  4. Thomas Wilkinson 2014-08-25

    Besides grabbing the compiled code from the Resources directory? I should have some bandwidth at the end of this week.
  5. Ingo Muschenetz 2014-08-25

    Yes, the compiled code can be difficult to review. If you can simplify it, that would be great.
  6. Federico Casali 2015-01-19

    The issue seems to be related to the usage of the 'touchEnabled' property on the parent View inside the ItemTemplate.

    Just by removing "touchEnabled=false" from id="outerView" View in index.html, it's then being displayed fine also on iOS. Further investigation results:

    1.

    See the following modified version of index.xml. I have set a touchEnabled="false" in the top view in the ItemTemplate (the one with id="outerView"), as well as added a custom property and layout="vertical" :
       <Alloy>
       	<Window class="container">
       		<ListView id="list">
       			<Templates>
       				<ItemTemplate name="faultyTemplate">
       					<View id="outerView" customProp="foobar" layout="vertical" touchEnabled="false">
       					 	<Label id="faultyLabel" bindId="faultyLabel"/>
       						<View id="otherView" >
       							<Label id="otherViewLabel1"/>
       							<Label id="otherViewLabel2" bindId="otherViewLabel2" class="rowDetailValue"/>
       						</View>
       					</View>
       				</ItemTemplate>
       			</Templates>
       			<ListSection id="section"></ListSection>
       		</ListView>
       	</Window>
       </Alloy>
       
    In this case the compiled /alloy/controllers/index.js file would include:
       var __alloyId4 = {
               type: "Ti.UI.View",
               childTemplates: function() {
                   var __alloyId5 = [];
                   var __alloyId6 = {
                       type: "Ti.UI.Label",
                       bindId: "faultyLabel",
                       properties: {
                           left: 12,
                           text: "dummy text",
                           backgroundColor: "yellow",
                           right: 12,
                           height: 16,
                           color: "black",
                           font: {
                               fontSize: 16,
                               fontFamily: "Helvetica",
                               fontWeight: "bold"
                           },
                           touchEnabled: false,
                           customProp: "foobar",
                           layout: "vertical",
                           bindId: "faultyLabel"
                       }
                   };
                   __alloyId5.push(__alloyId6);
                   var __alloyId7 = {
                       type: "Ti.UI.View",
                       childTemplates: function() {
                           var __alloyId8 = [];
                           var __alloyId9 = {
                               type: "Ti.UI.Label",
                               properties: {
                                   left: 12,
                                   width: 150,
                                   text: "Opening Available",
                                   height: 20,
                                   touchEnabled: false,
                                   customProp: "foobar",
                                   layout: "vertical",
                                   bindId: "faultyLabel"
                               }
                           };
                           __alloyId8.push(__alloyId9);
                           var __alloyId10 = {
                               type: "Ti.UI.Label",
                               bindId: "otherViewLabel2",
                               properties: {
                                   right: 0,
                                   width: 150,
                                   textAlign: "right",
                                   height: 20,
                                   touchEnabled: false,
                                   customProp: "foobar",
                                   layout: "vertical",
                                   bindId: "faultyLabel"
                               }
                           };
                           __alloyId8.push(__alloyId10);
                           return __alloyId8;
                       }(),
                       properties: {
                           left: 0,
                           right: 0,
                           height: 20,
                           touchEnabled: false,
                           customProp: "foobar",
                           layout: "vertical",
                           bindId: "faultyLabel"
                       }
                   };
                   __alloyId5.push(__alloyId7);
                   return __alloyId5;
               }(),
               properties: {
                   left: 0,
                   right: 0,
                   height: Ti.UI.SIZE,
                   touchEnabled: false,
                   customProp: "foobar",
                   layout: "vertical"
               }
           };
           __alloyId3.push(__alloyId4);
           var __alloyId2 = {
               properties: {
                   name: "faultyTemplate"
               },
               childTemplates: __alloyId3
           };
           __alloyId0["faultyTemplate"] = __alloyId2;
           $.__views.section = Ti.UI.createListSection({
               id: "section"
           });
       
    In this case, the bindId: "faultyLabel" and other properties (customProp="foobar" layout="vertical" touchEnabled="false") are also applied to the children objects of the top view in the ItemTemplate.

    2.

    In the compiled code, also, bindId is being set inside the "properties" in the object and it seems this is the value being used when building on iOS (hence the issue reported originally in the ticket). About this, see how the "otherViewLabel2" is being compiled:
       <Label id="otherViewLabel2" bindId="otherViewLabel2" class="rowDetailValue"/>
       
    is compiled as
       var __alloyId10 = {
                               type: "Ti.UI.Label",
                               bindId: "otherViewLabel2",
                               properties: {
                                   right: 0,
                                   width: 150,
                                   textAlign: "right",
                                   height: 20,
                                   touchEnabled: false,
                                   customProp: "foobar",
                                   layout: "vertical",
                                   bindId: "faultyLabel"
                               }
                           };
       
    In this case there are two "bindId" , one in the properties and one outside of it. In this case the one outside is correctly , while inside "properties" is inheriting . Android seems to be using the correct one, while iOS is using the one inside "properties".

    3.

    Use the following index.html (removed touchEnable="false" from the parent View and added back touchEnabled="false" in all view children objects)
       <Alloy>
       	<Window class="container">
       		<ListView id="list">
       			<Templates>
       				<ItemTemplate name="faultyTemplate">
       					<View id="outerView" customProp="foobar" layout="vertical">
       					 	<Label id="faultyLabel" bindId="faultyLabel"  touchEnabled="false"/>
       						<View id="otherView" >
       							<Label id="otherViewLabel1" touchEnabled="false"/>
       							<Label id="otherViewLabel2" bindId="otherViewLabel2" class="rowDetailValue"  touchEnabled="false"/>
       						</View>
       					</View>
       				</ItemTemplate>
       			</Templates>
       			<ListSection id="section"></ListSection>
       		</ListView>
       	</Window>
       </Alloy>
       
    Compiled code is now:
       $.__views.index && $.addTopLevelView($.__views.index);
           var __alloyId0 = {};
           var __alloyId3 = [];
           var __alloyId4 = {
               type: "Ti.UI.View",
               childTemplates: function() {
                   var __alloyId5 = [];
                   var __alloyId6 = {
                       type: "Ti.UI.Label",
                       bindId: "faultyLabel",
                       properties: {
                           left: 12,
                           text: "dummy text",
                           backgroundColor: "yellow",
                           right: 12,
                           height: 16,
                           color: "black",
                           font: {
                               fontSize: 16,
                               fontFamily: "Helvetica",
                               fontWeight: "bold"
                           },
                           touchEnabled: false,
                           bindId: "faultyLabel"
                       }
                   };
                   __alloyId5.push(__alloyId6);
                   var __alloyId7 = {
                       type: "Ti.UI.View",
                       childTemplates: function() {
                           var __alloyId8 = [];
                           var __alloyId9 = {
                               type: "Ti.UI.Label",
                               properties: {
                                   left: 12,
                                   width: 150,
                                   text: "Opening Available",
                                   height: 20,
                                   touchEnabled: false
                               }
                           };
                           __alloyId8.push(__alloyId9);
                           var __alloyId10 = {
                               type: "Ti.UI.Label",
                               bindId: "otherViewLabel2",
                               properties: {
                                   right: 0,
                                   width: 150,
                                   textAlign: "right",
                                   height: 20,
                                   touchEnabled: false,
                                   bindId: "otherViewLabel2"
                               }
                           };
                           __alloyId8.push(__alloyId10);
                           return __alloyId8;
                       }(),
                       properties: {
                           left: 0,
                           right: 0,
                           height: 20
                       }
                   };
                   __alloyId5.push(__alloyId7);
                   return __alloyId5;
               }(),
               properties: {
                   left: 0,
                   right: 0,
                   height: Ti.UI.SIZE,
                   customProp: "foobar",
                   layout: "vertical"
               }
           };
           __alloyId3.push(__alloyId4);
           var __alloyId2 = {
               properties: {
                   name: "faultyTemplate"
               },
               childTemplates: __alloyId3
           };
           __alloyId0["faultyTemplate"] = __alloyId2;
           $.__views.section = Ti.UI.createListSection({
               id: "section"
           });
       
    < bindId: "faultyLabel" > is only present in the Label with id="faultyLabel" (although still present twice, both inside and outside the object properties).
  7. Tim Poulsen 2015-02-06

    I can confirm the issue with Alloy 1.5.1 and Alloy 1.6.0 (not yet released). However, with Alloy 1.7, the sample app attached renders correctly. See the attached screen. Looking at the tickets in 1.7, I'm not completely sure which one would have resulted in fixing this issue. Perhaps ALOY-1127. I'm going to resolve this ticket for now. Please reopen if you're still seeing the issue with the Alloy 1.7 version.

JSON Source