How to achieve Dynamic Multilevel Columns generation

  1. #1

    How to achieve Dynamic Multilevel Columns generation

    Hi,
    We have a requirement where we need to generate the grid with multi level or column grouping dynamically using Ext.net 4.X version. Please find the attachment, this is current UI of aspx controls, we need to get the same in Ext UI.
    Could you please suggest us on How we can get the same layout or UI with Ext.JS or Ext.Net?

    I tried with column Grouped Header but could not get exactly. please find the code below which i tried.

    <%@ Page Language="C#" %>
    
    <script runat="server">
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!X.IsAjaxRequest)
            {
                this.Store1.DataSource = this.Data;
                this.Store1.DataBind();
            }
        }
    
    
        private object[] Data
        {
            get
            {
                return new object[]
                {
                    new object[] { "3m Co", 71.72, 0.02, 0.03, "9/1 12:00am" },
                    new object[] { "Alcoa Inc", 29.01, 0.42, 1.47, "9/1 12:00am" },
                    new object[] { "Altria Group Inc", 83.81, 0.28, 0.34, "9/1 12:00am" },
                    new object[] { "American Express Company", 52.55, 0.01, 0.02, "9/1 12:00am" },
                    new object[] { "American International Group, Inc.", 64.13, 0.31, 0.49, "9/1 12:00am" },
                    new object[] { "AT&T Inc.", 31.61, -0.48, -1.54, "9/1 12:00am" },
                    new object[] { "Boeing Co.", 75.43, 0.53, 0.71, "9/1 12:00am" },
                    new object[] { "Caterpillar Inc.", 67.27, 0.92, 1.39, "9/1 12:00am" },
                    new object[] { "Citigroup, Inc.", 49.37, 0.02, 0.04, "9/1 12:00am" },
                    new object[] { "E.I. du Pont de Nemours and Company", 40.48, 0.51, 1.28, "9/1 12:00am" },
                    new object[] { "Exxon Mobil Corp", 68.1, -0.43, -0.64, "9/1 12:00am" },
                    new object[] { "General Electric Company", 34.14, -0.08, -0.23, "9/1 12:00am" },
                    new object[] { "General Motors Corporation", 30.27, 1.09, 3.74, "9/1 12:00am" },
                    new object[] { "Hewlett-Packard Co.", 36.53, -0.03, -0.08, "9/1 12:00am" },
                    new object[] { "Honeywell Intl Inc", 38.77, 0.05, 0.13, "9/1 12:00am" },
                    new object[] { "Intel Corporation", 19.88, 0.31, 1.58, "9/1 12:00am" },
                    new object[] { "International Business Machines", 81.41, 0.44, 0.54, "9/1 12:00am" },
                    new object[] { "Johnson & Johnson", 64.72, 0.06, 0.09, "9/1 12:00am" },
                    new object[] { "JP Morgan & Chase & Co", 45.73, 0.07, 0.15, "9/1 12:00am" },
                    new object[] { "McDonald\"s Corporation", 36.76, 0.86, 2.40, "9/1 12:00am" },
                    new object[] { "Merck & Co., Inc.", 40.96, 0.41, 1.01, "9/1 12:00am" },
                    new object[] { "Microsoft Corporation", 25.84, 0.14, 0.54, "9/1 12:00am" },
                    new object[] { "Pfizer Inc", 27.96, 0.4, 1.45, "9/1 12:00am" },
                    new object[] { "The Coca-Cola Company", 45.07, 0.26, 0.58, "9/1 12:00am" },
                    new object[] { "The Home Depot, Inc.", 34.64, 0.35, 1.02, "9/1 12:00am" },
                    new object[] { "The Procter & Gamble Company", 61.91, 0.01, 0.02, "9/1 12:00am" },
                    new object[] { "United Technologies Corporation", 63.26, 0.55, 0.88, "9/1 12:00am" },
                    new object[] { "Verizon Communications", 35.57, 0.39, 1.11, "9/1 12:00am" },
                    new object[] { "Wal-Mart Stores, Inc.", 45.45, 0.73, 1.63, "9/1 12:00am" }
                };
            }
        }
    </script>
    
    
    <!DOCTYPE html>
    
    
    <html>
    <head runat="server">
        <title>Grouped Header Example - Ext.NET Examples</title>
        <link href="/resources/css/examples.css" rel="stylesheet" />
    
    
        <style>
            /* style rows on mouseover */
            .x-grid-row-over .x-grid-cell-inner {
                font-weight: bold;
            }
             #label, .x-grid-cell-label {
                background: gray !important;
                color: #fff;
            }
        </style>
    
    
        <script>
            var template = '<span style="color:{0};">{1}</span>';
    
    
            var change = function (value) {
                return Ext.String.format(template, (value > 0) ? "green" : "red", value);
            };
    
    
            var pctChange = function (value) {
                return Ext.String.format(template, (value > 0) ? "green" : "red", value + "%");
            };
        </script>
    </head>
    <body>
        <ext:ResourceManager runat="server" />
    
    
        <h1>Grouped Header Example</h1>
    
    
        <p>This example shows how to create a grid with column headers which are nested within category headers.</p>
        <p>Category headers do not reference Model fields via a <code>dataIndex</code>, rather they contain
        child header definitions (which may themselves either contain a <code>dataIndex</code> or more levels of headers).</p>
    
    
        <ext:GridPanel
            ID="GridPanel1"
            runat="server"
            Title="Grouped Header Grid"
            WidthSpec="100%"
            ColumnLines="true"
            Height="350">
            <Store>
                <ext:Store ID="Store1" runat="server">
                    <Model>
                        <ext:Model runat="server">
                            <Fields>
                                <ext:ModelField Name="company" />
                                <ext:ModelField Name="price" Type="Float" />
                                <ext:ModelField Name="change" Type="Float" />
                                <ext:ModelField Name="pctChange" Type="Float" />
                                <ext:ModelField Name="lastChange" Type="Date" DateFormat="M/d hh:mmtt" />
                            </Fields>
                        </ext:Model>
                    </Model>
                </ext:Store>
            </Store>
            <ColumnModel runat="server">
                <Columns>
                    <ext:Column runat="server" Text="Line Item Block">
                        <Columns>
                    <ext:Column ID="label" runat="server" Text="" Sortable="false" MenuDisabled="true" Flex="2">
                            <Renderer Fn="function (v, p, record, rowIndex) {return 'Row ¹'+rowIndex}" />
                        </ext:Column>
                            </Columns>
                            </ext:Column>
                    <ext:Column runat="server" Text="Description/Selected Columns">
                        <Columns>
                            <ext:Column runat="server" Text="Price" DataIndex="price" Width="75" Sortable="true">
                                <Renderer Format="UsMoney" />
                            </ext:Column>
                            <ext:Column runat="server" Text="Change" DataIndex="change" Width="75" Sortable="true">
                                <Renderer Fn="change" />
                            </ext:Column>
                            <ext:Column runat="server" Text="Change %" DataIndex="pctChange" Width="75" Sortable="true">
                                <Renderer Fn="pctChange" />
                            </ext:Column>
                            <ext:Column runat="server" Text="Price" DataIndex="price" Width="75" Sortable="true">
                                <Renderer Format="UsMoney" />
                            </ext:Column>
                            <ext:Column runat="server" Text="Change" DataIndex="change" Width="75" Sortable="true">
                                <Renderer Fn="change" />
                            </ext:Column>
                            <ext:Column runat="server" Text="Change %" DataIndex="pctChange" Width="75" Sortable="true">
                                <Renderer Fn="pctChange" />
                            </ext:Column>
                            <ext:Column runat="server" Text="Price" DataIndex="price" Width="75" Sortable="true">
                                <Renderer Format="UsMoney" />
                            </ext:Column>
                            <ext:Column runat="server" Text="Change" DataIndex="change" Width="75" Sortable="true">
                                <Renderer Fn="change" />
                            </ext:Column>
                            <ext:Column runat="server" Text="Change %" DataIndex="pctChange" Width="75" Sortable="true">
                                <Renderer Fn="pctChange" />
                            </ext:Column>
                            <ext:Column runat="server" Text="Price" DataIndex="price" Width="75" Sortable="true">
                                <Renderer Format="UsMoney" />
                            </ext:Column>
                            <ext:Column runat="server" Text="Change" DataIndex="change" Width="75" Sortable="true">
                                <Renderer Fn="change" />
                            </ext:Column>
                            <ext:Column runat="server" Text="Change %" DataIndex="pctChange" Width="75" Sortable="true">
                                <Renderer Fn="pctChange" />
                            </ext:Column>
                        </Columns>
                    </ext:Column>
                    <ext:Column runat="server" Text="Total">
                        <Columns>
                    <ext:DateColumn runat="server" Text="Last Updated" DataIndex="lastChange" Width="85" Sortable="true" Format="dd/MM/yyyy" />
                            </Columns>
                            </ext:Column>
                </Columns>
            </ColumnModel>
        </ext:GridPanel>
    </body>
    </html>
    Attached Thumbnails DynamicColumnHeaderGroup.PNG  
  2. #2
    Hello @iansriley!

    What you want is to nest whole grids within grid panels?

    If so, you may want to try the RowExpander plugin. As long as you don't fancy the inner grid panel too much, it should work just fine. Take a look at this example: GridPanel > RowExpander > Dynamic GridPanels.

    Beware this may become quite cumbersome if you have many rows in the outer grid and expand all of them at once.

    An alternative, if you just need a simple column-shaped structure within the grid cells where you want the dynamic table, is using templates with the content of the grid cell. The following example shows an usage of the TemplateColumn: GridPanel > List View > Overview. There, the first column is changed to, based on a template, display images in the cell. It shows how you can reference to the grid's data from the template code.

    Still in the simple column-shaped structure, as your data will probably contain a list of columns to display/format, you'd need to understand a little how you could iterate thru elements there. And this example has a highlight to this, where it prints the children names of the listed person: Miscellaneous > XTemplate > Dynamic Template.

    I believe using the grouped header won't help at all, because you want different grids/columns in the cell, so a general top-level header won't help with having these nested tables show correctly.

    Please give the ideas above a thought and let us know whether you can piece together your needs with that, or if that's nor really helpful. I am not realy certain, given the example you provided, what you actually expected to see in the grid. Or is that edited showing how you'd like to see it?

    Looking forward to your follow-up!
    Fabrício Murta
    Developer & Support Expert
  3. #3
    Thanks for the solutions,

    I will try and let you know. Could you please tell me "How to set the width of the column as per the data in that"? means, column width should be adjust automatically based on data in that column or cell.
  4. #4
    Hello again @iansriley!

    Thanks for your feedback, glad it looks like the options might help you.

    For this second question you posted, it seems unrelated to the original one, would you mind creating a dedicated thread for it?
    Fabrício Murta
    Developer & Support Expert
  5. #5
    Hi,

    I tried to get the required view with template column, we are mostly ok with this view. But, here i am facing an issue is, when we have more columns/fields under "Line item Blocks" column the design looks good with required scroll bar and aligned properly.. where as if there are only a few columns/fields under the "Line item Blocks" column it's just fitting based on the size of data (as i mentioned AutoSizeColumn=true ).

    If you look at that first and second grids, we need to have the "Total" always right aligned and it should show the complete data and fit to grid width on Grid2.

    Please have a look at following runnable code and let us know your suggestions asap. I am preparing a JSON data like followed.

    <%@ Page Language="C#" %>
    <script runat="server">
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!X.IsAjaxRequest)
            {
             
            }
        }
    </script>
    
    <!DOCTYPE html>
    
    <html>
    <head runat="server">
        <title>Columns Variations - Ext.NET Examples</title>
        <link href="/resources/css/examples.css" rel="stylesheet" />
        <style>
            .lbl, .x-grid-cell-label {
                background-color: lightgray !important;
            }
        </style>
        <script type="text/javascript">
            Ext.onReady(function () {
    
                var records = [];
                var ddd = '[{"LineItem":"Print","LineItemDefinitionID":797,"LineItemTypeID":3,"SubProductTypeID":1,"Description":"Test Description","Column1":"Publication  ","Column2":"Issue  ","Column3":"Year  ","Column4":"Section","Column5":"Ad Size","Column6":"Prod Charge  ","Column7":"Barter  ","Column8":"Net  ","Total":"[Prod Charge  ]-[Barter  ]+[Net  ]","Barter":null},{"LineItem":"Digital","LineItemDefinitionID":798,"LineItemTypeID":3,"SubProductTypeID":3,"Description":"","Column1":"Product","Column2":"Issue","Column3":"Year","Column4":"Start Date","Column5":"End Date","Column6":"Production Charge  ","Column7":"Barter  ","Column8":"Net  ","Total":"[Production Charge  ]-[Barter  ]+[Net  ]","Barter":null}]';
                var jsData = JSON.parse(ddd);
                if (jsData) {
                    jsData.forEach(function (element) {
                        var mainObj = new Object();
                        mainObj.LineItem = element.LineItem;
                        mainObj.Description = element.Description;
                        mainObj.LineItemDefinitionID = element.LineItemDefinitionID;
                        mainObj.Total = element.Total;
                        mainObj.LineItems = "";
                        mainObj.LineItemsWithFew = "";
                        for (var key in element) {
                            if (element.hasOwnProperty(key) && key.startsWith("Column")) {
                                mainObj.LineItems = mainObj.LineItems + " | " + element[key]+ " | " + element[key]+ " | " + element[key];
                                mainObj.LineItemsWithFew = mainObj.LineItemsWithFew + " | " + element[key];
                            }
                        };
                        mainObj.LineItems = mainObj.LineItems.substring(3, mainObj.LineItems.length);//Trim first "|"
                        records.push(mainObj);
                    });
                }
                App.store1.loadData(records);
                App.store2.loadData(records);
            });
    
            var handleViewRefresh = function (dataview) {
                Ext.each(dataview.panel.columns, function (column) {
                    if (column.autoSizeColumn === true) {
                        column.autoSize();
                    }
                })
            };
        </script>
    </head>
    <body>
        <form runat="server">
            <ext:ResourceManager runat="server" Theme="Triton" />
    
            <ext:GridPanel
                ID="GridPanel1"
                runat="server"
                Title="Sample view with a more lineitem fields (with scroll)"
                DisableSelection="true"
                WidthSpec="100%" Layout="FitLayout">
                <Store>
                    <ext:Store runat="server" ID="store1">
                        <Model>
                            <ext:Model runat="server">
                                <Fields>
                                    <ext:ModelField Name="LineItemDefinitionID" />
                                    <ext:ModelField Name="LineItem" />
                                    <ext:ModelField Name="Description" />
                                    <ext:ModelField Name="Total" />
                                    <ext:ModelField Name="LineItems" />
                                </Fields>
                            </ext:Model>
                        </Model>
                    </ext:Store>
                </Store>
                <ColumnModel runat="server">
                    <Columns>
                         <ext:ImageCommandColumn ID="imgCommands" runat="server" Width="50" Locked="true">
                            <Commands>
                                <ext:ImageCommand CommandName="Edit" Icon="PageWhiteEdit" >
                                    <ToolTip Text="Edit" />
                                </ext:ImageCommand>
                                <ext:ImageCommand CommandName="Delete" Icon="PageWhiteDelete" >
                                    <ToolTip Text="Delete" />
                                </ext:ImageCommand>
                            </Commands>
                            <Listeners>
                                <Command Handler="Ext.Msg.alert(command, record.data.LineItem);" />
                            </Listeners>
                        </ext:ImageCommandColumn>
                        <ext:Column ID="colLineItem" runat="server" DataIndex="LineItem" Text="LineItem" CellCls="lbl" MenuDisabled="true" Locked="true" >
                        </ext:Column>
                        <ext:TemplateColumn ID="colLineItems" runat="server" MenuDisabled="true" Text="Line Item Blocks" Flex="2" AutoSizeColumn="true">
                            <Template runat="server">
                                <Html>
                                    <tpl for=".">
                                      
                                            <tpl if="Description != ''">
                                                    {Description}<br />
                                                    {LineItems}
    
                                            </tpl>
                                                <tpl if="Description == ''">
                                                        {LineItems}
                                                </tpl> 
                                  
                                    </tpl>
                                </Html>
                            </Template>
                        </ext:TemplateColumn>
                        <ext:Column ID="colTotal" runat="server" DataIndex="Total" MenuDisabled="true" Text="Total" Flex="1" Align="Right" />
                    </Columns>
                </ColumnModel>
                <View>
                    <ext:GridView runat="server" StripeRows="true" />
                </View>
                <ViewConfig runat="server">
        <Listeners>
            <Refresh Fn="handleViewRefresh" />
        </Listeners>
    </ViewConfig>
                <CustomConfig>
                    <ext:ConfigItem Name="shouldAutoHideHeaders" Value="function() { return false; }" Mode="Raw" />
                </CustomConfig>
            </ext:GridPanel>
    <br/>
    <br/>
    <p>Grid with a few columns</p>
            <ext:GridPanel
                ID="GridPanel2"
                runat="server"
                Title="Sample view with a few lineitem fields"
                DisableSelection="true"
                WidthSpec="100%" Layout="FitLayout">
                <Store>
                    <ext:Store runat="server" ID="store2">
                        <Model>
                            <ext:Model runat="server">
                                <Fields>
                                    <ext:ModelField Name="LineItemDefinitionID" />
                                    <ext:ModelField Name="LineItem" />
                                    <ext:ModelField Name="Description" />
                                    <ext:ModelField Name="Total" />
                                    <ext:ModelField Name="LineItemsWithFew" />
                                </Fields>
                            </ext:Model>
                        </Model>
                    </ext:Store>
                </Store>
                <ColumnModel runat="server">
                    <Columns>
                         <ext:ImageCommandColumn ID="imgCommands1" runat="server" Width="50" Locked="true">
                            <Commands>
                                <ext:ImageCommand CommandName="Edit" Icon="PageWhiteEdit" >
                                    <ToolTip Text="Edit" />
                                </ext:ImageCommand>
                                <ext:ImageCommand CommandName="Delete" Icon="PageWhiteDelete" >
                                    <ToolTip Text="Delete" />
                                </ext:ImageCommand>
                            </Commands>
                            <Listeners>
                                <Command Handler="Ext.Msg.alert(command, record.data.LineItem);" />
                            </Listeners>
                        </ext:ImageCommandColumn>
                        <ext:Column ID="colLineItem1" runat="server" DataIndex="LineItem" Text="LineItem" CellCls="lbl" MenuDisabled="true" Locked="true" >
                        </ext:Column>
                        <ext:TemplateColumn ID="colLineItems1" runat="server" MenuDisabled="true" Text="Line Item Blocks" Flex="2" AutoSizeColumn="true">
                            <Template runat="server">
                                <Html>
                                    <tpl for=".">
                                      
                                            <tpl if="Description != ''">
                                                    {Description}<br />
                                                    {LineItemsWithFew}
    
                                            </tpl>
                                                <tpl if="Description == ''">
                                                        {LineItemsWithFew}
                                                </tpl> 
                                  
                                    </tpl>
                                </Html>
                            </Template>
                        </ext:TemplateColumn>
                        <ext:Column ID="colTotal1" runat="server" DataIndex="Total" MenuDisabled="true" Text="Total" Flex="1" Align="Right" AutoSizeColumn="true"/>
                    </Columns>
                </ColumnModel>
                <View>
                    <ext:GridView runat="server" StripeRows="true" />
                </View>
                <ViewConfig runat="server">
        <Listeners>
            <Refresh Fn="handleViewRefresh" />
        </Listeners>
    </ViewConfig>
                <CustomConfig>
                    <ext:ConfigItem Name="shouldAutoHideHeaders" Value="function() { return false; }" Mode="Raw" />
                </CustomConfig>
            </ext:GridPanel>
        </form>
    </body>
    </html>
  6. #6
    Hello @iansriley!

    You're adding AutoSizeColumn="true" to the last column in the second grid. Besides, why are you even specifying Flex="2" in the subtables column that you want auto-sized?

    The autosize setting is meant to fit the width of the column to the column contents, whereas the flex one is meant to fit the column to the grid's width, and the value you bind to flex means its weight. So if you have one column with 2 and other with 1, and the grid (during render) sees it has more 150 pixels left to fill the grid width, it will add 100 to the weight 2 and 50 to the weight 1.

    So they are competing concepts and I can't think how both could work in a same column. You should give flex to a column you don't do autosize to ensure the whole grid's width is filled.

    Hope this helps!

    note: if confused, set AutoSizeColumn="false" on line 195 of the sample code you just provided.
    Fabrício Murta
    Developer & Support Expert
  7. #7
    Flex and AutoSizeColumn was mentioned last 2 columns, but we don't required the Flex attribute, i can remove this. How to fit the columns to Grid with AutoSizeColumn only (i cannot set False to AutoSizeColumn for Total column (the last column) since it can have more/less content sometimes).

    Finally i need to fit (Flex) the columns to grid width and should see the complete content in the column (AutoSizeColumn).
  8. #8
    Hello @iansriley!

    You can give another column the flex so that it fills the table accordingly.

    If that's not an option, you'd have to implement your own "flex" in the autosize function. Then you can place a sign in the column (same way you did with AutoSizeColumn) to indicate it should "autosize-then-fill", so that if the sum of widths of all columns -plus- the width of the desired-flex column doesn't match the grid's width, then it adds the difference in width to that column so that it fills up the grid.

    Notice though, if the column in the end exceeds the grid width, it would need to reduce the column width, thus not fitting the inner table anymore! This is a very specific requirement I'm afraid Ext.NET won't support out-of-the box. Custom logic with all edge cases will have to be designed in the autosize method.

    The latter case (where both columns require more width than the grid has) could instead increase the width of the whole grid, guaranteeing the column contents to fit -- yet maybe triggering a horizontal scrollbar on the client window.

    In the end:

    Quote Originally Posted by iansriley
    Finally i need to fit (Flex) the columns to grid width and should see the complete content in the column (AutoSizeColumn).
    Is impossible. In particular in this scenario:
    - the sum of the fixed columns + table columns exceeds the grid's width.

    You'd only be able to develop something like this if you flexibilize the requirement in one aspect or another.

    Hope this helps!
    Fabrício Murta
    Developer & Support Expert

Similar Threads

  1. Replies: 3
    Last Post: Apr 08, 2014, 9:33 PM
  2. [CLOSED] Dynamic form generation in 2.0
    By rthiney in forum 2.x Premium Help
    Replies: 4
    Last Post: Aug 24, 2012, 9:04 PM
  3. Replies: 0
    Last Post: Jan 06, 2012, 8:52 AM
  4. [CLOSED] How can I achieve this layout?
    By mattwoberts in forum 1.x Premium Help
    Replies: 5
    Last Post: Jan 27, 2011, 7:13 AM
  5. Replies: 4
    Last Post: Nov 18, 2009, 9:18 AM

Tags for this Thread

Posting Permissions