User Profile & Activity

Shawn August Member
Page
of 19

Here's my implementation that I hope will help someone else. This would be a nice feature to the product for anyone using the BatchUpdate feature. The purpose of this script is to automatically update the grid's footer cell as each editable cell is modified

function grdTreatyClaims_OnAfterExitEditMode(controlID, tableName, editObject)
    {
        try 
        {            
            var grdTreatyClaims = ISGetObject(controlID);
            if (grdTreatyClaims == null) { return; }

            if (editObject == null) { return; }
            
            // Get updated column's name/value
            var colName = editObject.ToCellObject().Name;
            var colNewValue = editObject.element.value;

            // Get footer column's new value
            var colFooterNewValue = WebGrid_GetColumnAggregateValue(controlID, colName, null);
            
            // Update footer column
            WebGrid_SetFooterColumnValue(controlID, colName, colFooterNewValue);

            return true;
        }
        catch (ex) { ShowJSException(ex); } 
    }
function WebGrid_GetColumnAggregateValue(gridID, colName, aggregateFunction)
{
    try
    {
        // Get grid
        var grid = ISGetObject(gridID);
        if (grid == null) { return null; }

        // Get grid's rows
        var rows = grid.RootTable.GetElement(WG40.BODY, WG40.HTMLTABLE).getElementsByTagName("tr");
        if (rows == null) { return null; }

        // Get aggregate function based on specified column if not specified
        // NOTE: Default "Sum" if column is not found
        if (IsNullOrEmpty(aggregateFunction) == true)
        {
            var column = WebGrid_GetColumnByName(gridID, colName);
            if (column != null) { aggregateFunction = column.AggregateFunction; }
            else { aggregateFunction = "Sum"; }
        }

        // Execute aggregate function
        // NOTE: Check for "Record" type
        var value = 0;
        for (var counter = 0; counter < rows.length; counter++)
        {
            var row = rows[counter];
            if (row != null)
            {
                if (row.type == "Record")
                {
                    var rowCol = grid.GetRowByElement(row).GetCell(colName);
                    if (rowCol != null)
                    {
                        // Perform aggregate
                        switch (aggregateFunction)
                        {
                            case "Sum":
                                value += Number(rowCol.Value);
                                break;
                        }
                    }
                }
            }
        }
        return value;
    }
    catch (ex) { ShowJSException(ex); }
}

function WebGrid_GetColumnByName(gridID, colName) 
{
    try 
    {
        // Get grid's column by name    
        var grid = ISGetObject(gridID);
        if (grid == null) { return null; }
        return grid.RootTable.Columns.GetNamedItem(colName);
    }
    catch (ex) { ShowJSException(ex); }
}

function WebGrid_GetHeaderCells(gridID) 
{
    try 
    {
        // Get header cells
        var grid = ISGetObject(gridID);
        if (grid == null) { return null; }
        return grid.RootTable.GetElement(WG40.COLHEADER, WG40.HTMLDIV).getElementsByTagName("td");
    }
    catch (ex) { ShowJSException(ex); }
}

function WebGrid_GetFooterCells(gridID) 
{
    try 
    {
        var grid = ISGetObject(gridID);
        if (grid == null) { return null; }
        return grid.RootTable.GetElement(WG40.COLFOOTER, WG40.HTMLDIV).getElementsByTagName("tr")[1].getElementsByTagName("td");
    }
    catch (ex) { ShowJSException(ex); }
}

function WebGrid_GetFooterColumnByName(gridID, colName) 
{
    // Get grid's column index for update
    var colIndex = WebGrid_GetColumnIndexByName(gridID, colName);
    if (colIndex < 0) { return null; }

    // Get the grid's footer cells
    var footerCells = WebGrid_GetFooterCells(gridID);
    if (footerCells == null) { return null; }

    // Get footer column
    return footerCells[colIndex];
}

function WebGrid_GetColumnIndexByName(gridID, colName)
{
    try 
    {
        // Grid ID is required
        if (IsNullOrEmpty(gridID) == true) { return null; }

        // Column Name is required
        if (IsNullOrEmpty(colName) == true) { return null; }

        // Get grid's header cells
        var headerCells = WebGrid_GetHeaderCells(gridID);
        if (headerCells == null) { return null; }

        // Get grid's column index by name
        var index = -1;
        for (var counter = 0; counter < headerCells.length; counter++) 
        {
            var headerCell = headerCells[counter];
            if (headerCell != null) 
            {
                var headerCellName = headerCell.getAttribute("ColName");
                if (headerCellName == colName) { index = counter; break; }
            }
        }
        return index;
    }
    catch (ex) { ShowJSException(ex); }
}

function WebGrid_SetFooterColumnValue(gridID, colName, value) 
{
    try 
    {
        // Get grid's column index for update
        var colIndex = WebGrid_GetColumnIndexByName(gridID, colName);
        if (colIndex < 0) { return false; }

        // Get the grid's footer cells
        var footerCells = WebGrid_GetFooterCells(gridID);
        if (footerCells == null) { return false; }

        // Set footer column's text with specified value
        var footerCell = footerCells[colIndex];
        if (footerCell != null) { footerCell.innerHTML = value; }

        return true;
    }
    catch (ex) { ShowJSException(ex); }
}

I can't provide a sample as I can't seem to find anything in the client-side object model that will help me. I can use the onExitEditMode event to re-calculate the footer columns. But, I have a few questions:

1) Is there a way to indicate either the index or name of the field being changed within the onExitEditMode? If so, I can use that name/index to determine the column being updated and then iterate through the grid's columns and sum the fields accordingly.

2) Using the sum value in #1, how do I retrieve the footer columns? I would need to retrieve this column similiar to the approach in question #1 so I can update the appropriate column.

Thanks.

Thinking about this more.

 

Does it make more sense to handle the OnInitializePostBack event that occurs after the cell value is updated and the row is changed? It's possible to update the underlying DataSource and let the grid re-calculate the footer totals. Actually, at that point, it seems like the changed cell's data is gone...

 

Also, is there a way to turn that off? Strictly just keep it 100% client-side?

 

Hi Shawn,

When you changed cells on the client side, are they also getting updated? If you only set the text on the cells without update, of course footer would not get updated. But you can try to update it manually by aggregate them manually and set the footer by getting the element first. FYI, the element of footer depends on the structure you have.

Regards,
Handy

 

Yes, there is no server-side postback. Everything is done for client-side.

 

Is there a way to iterate through the grid's row for the particular column that has been updated? The OnExitEditMode event can be used but not sure if the editObject knows which column has been edited. Does it know via name or index? I am also not sure how to iterate through the footer's columns. I noticed an example using index. I can use that assuming the editObject knows its index.

Hi Swan,

     After I discuss this with our Developer, it seems that since we are using unBound WebGrid, we cannot using WebValue List. WebValue List should be used in WebGrid with bound data source, if not, it's simply conflicting with the nature of the databinding concept. I hope it helps. Thank you.

Best Regards,

Andi Santoso

 

Is there any work-around? If not, then WebValueList is not possible, at all, using strongly typed classes for a hierarical grid.

 

I did verify my code works after I removed the creating of the hierarchy structure within the code-behind (which is necessary for me).

Hi Shawn,

     I have created a simple running sample using dsNorthwind database. In that sample, I have created a WebValueList under a Hierarchical WebGrid and I used a RootTable to attach my WebValue. However, if you are willing to attach the WebValue in the Child table, instead of grid.RootTable, you can simply use grid.GetTableByName("TableName").

     Please kindly try and run my sample in your end and see if this meets your scenario. However, I do not find any issue in this. If it does not meet your scenario, could you kindly modify my sample so that, it will replicate the issue of yours and send me back for further investigation.

     Thank you.

Best Regards,

Andi Santoso

 

I modified your example to reproduce the issue. The code in your example to define the WebValueList is very similiar to the one I posted above. This has worked without problems in the past but does not with the new DLLs, using strongly typed objects as a datasource, and using a hierarchical grid as discussed within this thread.

 

Hi Shawn,

     Yes, for the particular sample that I have created for you, this cannot be done since we have created the WebGrid programmaticly and bind them thru PreInitialize. So, I will suggest you to use specify the structure via code-behind. And define the structure in PrepareDataBinding server side event.

     Thank you and have a nice day.

Best Regards,

Andi Santoso

 

OK.

 

I ran into another problem using a Hierarchical Grid's WebValueList. The following exception occurs when the WebValueList's DataSource property is set:  IHierarchicalList.ItemType should not be null!

 

I have added the method below that is widely used in my application but does not work with the Hierarcical Grid.

 

        /// <summary>
        /// Creates a WebValueLooup for the specified column.
        /// </summary>
        /// <param name="nvList"></param>
        /// <param name="columnName"></param>
        public static void CreateWebValueLookup(WebGrid grid, object datasource, string columnName)
        {
            WebValueList wvList = grid.RootTable.Columns.GetNamedItem(columnName).ValueList;
            wvList.DataSource = datasource;
            wvList.DataMember = "";
            wvList.DataTextField = CommonConstants.COL_NAME_VALUE_VALUE;
            wvList.DataValueField = CommonConstants.COL_NAME_VALUE_ID;
        }

 

Hi Shawn,

     If we are willing for not using RetrieveHierarchicalStructure, then we will need to specify all the parent and child row in the HTML code. From what I see on your provided code, I did not see that you have specified that in particular. If we do so, we do not need to use RetrieveHierarchicalStructureMethod.

    Attached is a simple sample that I created under Hierarchical WebGrid. Notice that I do not call RetireveHierarchicalMethod in the server. However, the structure is still persisted.

    I hope it helps. Thank you and have a nice day.

Best Regards,

Andi Santoso

 

That doesn't work with strongly typed custom objects with the new DLL .403 that is discussed within this thread.

Hi Shawn,

     If we are willing for not using RetrieveHierarchicalStructure, then we will need to specify all the parent and child row in the HTML code. From what I see on your provided code, I did not see that you have specified that in particular. If we do so, we do not need to use RetrieveHierarchicalStructureMethod.

    Attached is a simple sample that I created under Hierarchical WebGrid. Notice that I do not call RetireveHierarchicalMethod in the server. However, the structure is still persisted.

    I hope it helps. Thank you and have a nice day.

Best Regards,

Andi Santoso

 

That doesn't work with strongly typed custom objects with the new DLL .403 that is discussed within this thread.

Hi Shawn,

     If we are willing for not using RetrieveHierarchicalStructure, then we will need to specify all the parent and child row in the HTML code. From what I see on your provided code, I did not see that you have specified that in particular. If we do so, we do not need to use RetrieveHierarchicalStructureMethod.

    Attached is a simple sample that I created under Hierarchical WebGrid. Notice that I do not call RetireveHierarchicalMethod in the server. However, the structure is still persisted.

    I hope it helps. Thank you and have a nice day.

Best Regards,

Andi Santoso

 

That doesn't work with strongly typed custom objects with the new DLL .403 that is discussed within this thread. But, if I specify the structure via code-behind, it does work.

Hi Shawn,

     I cannot modify your sample since I do not know which one is the child table. To make it easier for me to investigate, could you provide me with the sample and possibly your database?

     However, please ensure that you have specified the child table in prepare data binding server side.

     Thank you and have a nice day.

Best Regards,

Andi Santoso

 

The sample was provided by Andi Santose on the April 12, 2010 @ 4:05AM post.

 

However, I added the code above via server-side's PrepareBinding and it finally worked. Does that mean I am forced to define the structure via server-side? I assume anything I can do via ASPX I can do via server-side. It would be nice to have the flexibility if possible.

I specified the DataMember and the DataKeyField for both the root and child table and it still doesn't render.

 

Can you modify the above example accordingly so I can see waht I am missing?!

All times are GMT -5. The time now is 11:33 PM.
Previous Next