apache / royale-asjs

Apache Royale ASJS
Apache License 2.0
373 stars 116 forks source link

ItemRenderer on Basic DataGrid doesn't work on 0.9.6 #505

Open cristallium opened 5 years ago

cristallium commented 5 years ago

Hi,

There is an issue with itemRenderer on DataGrid.

The following code show empty cells (count cells is right but no text)

<js:View xmlns:fx="http://ns.adobe.com/mxml/2009"
                xmlns:js="library://ns.apache.org/royale/express">
    <fx:Script>
        <![CDATA[

            import org.apache.royale.collections.ArrayList;
            import org.apache.royale.express.DataGrid;

            import org.apache.royale.collections.ArrayList;

            private function ev_clic_arl_dp():void {
                mydg.dataProvider = arl;
            }

            private function ev_clic_ar_dp():void {
                mydg.dataProvider = ar;
            }

            private var ar:Array = ["Bob", "Joe", "Frank", "Sally"];
            private var arl:ArrayList = new ArrayList ([{label:'bob',value:'bob'},{label:'bob2',value:'bob2'},{label:'bob3',value:'bob3'}]);

        ]]>
    </fx:Script>

    <fx:Style>
        @namespace js "library://ns.apache.org/royale/basic";

        .DataGridColumnList .StringItemRenderer {
            border-style: solid;
            border-color: #CCCCCC;
            border-width: 1px;
            background-color: white;
            line-height: 40px;
            padding: 2px;
        }

        .DataGridColumnList .DataItemRenderer {
            border-style: solid;
            border-color: #CCCCCC;
            border-width: 1px;
            background-color: white;
            line-height: 40px;
            padding: 2px;
        }
    </fx:Style>

    <js:beads>
        <js:VerticalLayout/>
    </js:beads>

    <js:DataGrid id="mydg" x="20" y="30" width="400" height="300" rowHeight="30">
        <js:columns>
            <js:DataGridColumn label="Name" dataField="label" columnWidth="100%" />
            <js:DataGridColumn label="Sales" dataField="value" columnWidth="80" />
        </js:columns>
    </js:DataGrid>

    <js:TextButton text="Set ARL DP" click="ev_clic_arl_dp()"/>
    <js:TextButton text="Set AR DP" click="ev_clic_ar_dp()"/>
</js:View>

image

When debugging js the issue is on setting data on itemRenderer :

(DataItemRendererFactoryForArrayData.as) function dataProviderChangeHandler ... ir.data = dp[i]; // dp = ArrayList with right datas jump to (StringItemRenderer.as)

org.apache.royale.html.supportClasses.StringItemRenderer.prototype.set__data = function(value) {
  org.apache.royale.html.supportClasses.StringItemRenderer.superClass_.set__data.apply(this, [ value] );
  this.text = this.dataToString(value);
};

value is undefined when enter function

Source code DataGridExample.zip

greg-dove commented 5 years ago

without fully analysing the issue, I can see that DataItemRendererFactoryForArrayData is being used, which is for Array as a dataprovider, not ArrayList. I don't have time to look at this in more detail right now, but that might be a starting point.

cristallium commented 5 years ago

I have tried to add this in styles

        .DataGridColumnList {
            IDataProviderItemRendererMapper: ClassReference("org.apache.royale.html.beads.DataItemRendererFactoryForArrayList");
        } 

but it always use DataItemRendererFactoryForArrayData using Array or ArrayList as source for dataProvider

cristallium commented 5 years ago

I found one issue in my code I used xmlns:js="library://ns.apache.org/royale/express" and not xmlns:js="library://ns.apache.org/royale/basic"

So I used the wrong DataGrid. By the way what is the goal of express library ?

So now using the right lib (basic), it's working if set an Array for dataprovider, but not with ArrayList

aharui commented 5 years ago

The Express library pre-packages a bunch of beads so you don't have to select as many beads as when using the Basic library, but the trade-off is that Express apps will be bigger and slower.

cristallium commented 5 years ago

Aharui, thanks for this explanation.

Finaly I found how to force DataItemRendererFactoryForArrayList

This was bad

.DataGridColumnList {
        IDataProviderItemRendererMapper: ClassReference("org.apache.royale.html.beads.DataItemRendererFactoryForArrayList");
} 

This is good :

 js|DataGridColumnList {
        IDataProviderItemRendererMapper: ClassReference("org.apache.royale.html.beads.DataItemRendererFactoryForArrayList");
 } 

So now it's working right with ArrayList

But I don't understand why we can use

        .DataGridColumnList .StringItemRenderer {
            background-color: #ff0000;
        }

or

        js|DataGridColumnList js|StringItemRenderer {
            background-color: #ff0000;
        }

both are working in style but not for IDataProviderItemRendererMapper . Why ? What is the good practice to use between js| or . (dot) selector ?

aharui commented 5 years ago

Might be a bug in the CSSStyleImpl.

Some styles like IDataProviderItemRendererMapper are pruned from the CSS output because they are aren't CSS compliant (the ClassReference value, for example). Background-color will make it into the final CSS output and will be applied by the browser. Our code must look up the value in a different data structure. It isn't obvious why it doesn't work as a class selector instead of a type selector.

You can specify a class selector or type selector using similar logic to any other CSS styling, but keep in mind that the compiler does know how to prune unused type-selectors but generally does not prune class selectors.

carlosrovira commented 5 years ago

This is the GIST for MAC: https://gist.github.com/carlosrovira/9535bbeccc7f2a82ab4cf30a2cda1724 (you can convert to Windows easily, or wait for @greg-dove version)