This is a migrated thread and some comments may be shown as answers.

[Solved] In-line grid edit does not use values present in grid before clicking edit

9 Answers 220 Views
Grid
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Stewart
Top achievements
Rank 1
Stewart asked on 28 May 2011, 12:22 AM

I'm trying to use the MVC Telerik Grid with a dynamic number of server-bound columns, and in-line Ajax editing. I've gotten the values to appear correctly in the dynamic columns, but when I click "edit" for the in-line editing, the edit value I get is an "empty" value for the field. For example if the grid shows 123.00 for a decimal, I get 0.00 when I edit it. If I then cancel the edit, the fields are blanked - not 123.00, or 0.00, but blank. I've attached sequential screenshots below

I'm using  Telerik v. 2011.1.315.340 on Visual Studio 2010, MVC 3.

Here's my grid instantiation. It's a series of grids inside a PanelBar - sorry for the extra noise.

<%
    Html.Telerik().PanelBar()
        .Name("PhaseEstimatesPanelBar")
        .Items(items =>
               {
                   int phaseIndex = 0;                   
                   foreach (var initiativePhase in Model.InitiativePhases)
                   {
                       // HACK - next unused funding source
                       InitiativePhaseEstimate initiativePhaseEstimate = initiativePhase.GetInitiativePhaseEstimate();
                       FundingSource nextUnusedFundingSource = AllPossibleFundingSources.First();
                       if (initiativePhaseEstimate != null)
                       {
                           var usedFundingSources = initiativePhaseEstimate.GetFundingSources();
                           nextUnusedFundingSource = AllPossibleFundingSources.First(fs => !usedFundingSources.Contains(fs));                           
                       }
                         
                       // HTML of Button for adding a new Estimate                       
                       var newEstimateButtonLink = SitkaRoute<InitiativeController>.BuildLinkFromExpression(c => c.CreateFundingSourceEstimateRow(initiativePhase.InitiativePhaseID, nextUnusedFundingSource.FundingSourceID), "Add Funding Source");
  
                       // This is grotesque, and deserves an explanation.
                       //
                       // Telerik Grid wants to call a default, parameterless constructor on the Model type of the grid, in this case FundingSourceEstimateRow. But my first crack at a parameterless constructor just
                       // had a blank List of BudgetEstimates, which meant that the generated AJAX template did not have enough columns. So instead we set this static just-in-time before the parameterless constructor
                       // is called in the grid so that it has the correct BudgetEstimate columns. 
                       // 
                       // The Default constructor is the *ONLY* member that needs these, and they should be otherwise ignored.
                       // -- SLG
                       FundingSourceEstimateRow.BudgetEstimateTemplatesForDefaultConstructor = FundingSourceEstimateRow.GetBlankBudgetEstimatesForInitiativePhaseEstimate(initiativePhaseEstimate, nextUnusedFundingSource);
                         
                       // Build grid control for the initiative phases
                       var rowsForInitiativePhase = GetFundingSourceEstimateRows(initiativePhase);
                       var gridContent = Html.Telerik().Grid<FundingSourceEstimateRow>(rowsForInitiativePhase)
                           .Name(string.Format("InitiativePhaseEstimatimesGrid_PhaseID{0}", initiativePhase.ID))
                           .ToolBar(commands => commands.Insert())
                           .DataKeys(keys => keys.Add(x => x.ID))
                           .DataBinding(f => f.Ajax()
                                            .Select("EstimatesGridEditSelect", "Initiative")
                                            .Insert("EstimatesGridInsert", "Initiative")
                                            .Update("EstimatesGridSave", "Initiative")
                                            .Delete("EstimatesGridDelete", "Intiative"))
                           .Columns(columns =>
                                    {
                                        //columns.Bound(c => c.InitiativePhaseEstimateID).Hidden();
                                          
                                        columns.Command(commands =>
                                        {
                                            commands.Edit().ButtonType(GridButtonType.BareImage);
                                            commands.Delete().ButtonType(GridButtonType.BareImage);
                                        }).Width(200).Title("Actions");                                        
                                                                                  
                                        //columns.Bound(c => c.ID).Title("Fund Estimate ID");
                                        //columns.Bound(c => c.FundingSource.FundingSourceID).Title("Funding Source ID");
                                        columns.Bound(c => c.FundingSource.HierarchicalDisplayName).Title("Funding Source").Width(200);
  
                                        var phaseEstimate = initiativePhase.GetInitiativePhaseEstimate();
                                        if (phaseEstimate != null)
                                        {
                                            var fiscalYearQuarters = phaseEstimate.InitiativePhase.GetFiscalQuarters();
  
                                            Action<int> addValueColumn = (i) =>
                                                                         {
                                                                             columns.Bound(u => u.BudgetEstimates[i].EstimatedBudget).Title(fiscalYearQuarters[i].DisplayName).Width(90);
                                                                         };
  
                                            int quarterColumnCount = fiscalYearQuarters.Count;
                                            for (int quarterIndex = 0; quarterIndex < quarterColumnCount; quarterIndex++)
                                            {
                                               addValueColumn(quarterIndex);
                                            }
                                        }
  
  
                                    })
                                    .Editable(editing => editing.Mode(GridEditMode.InLine))
                                    .Scrollable(scroll => scroll.Height(140));
                         
                       // Only show the grid if there are existing BudgetEstimates for the Phase
                       string gridContentHtml = string.Empty;
                       if (initiativePhaseEstimate != null && initiativePhaseEstimate.BudgetEstimates.Any())
                       {
                           gridContentHtml = gridContent.ToHtmlString();
                       }
                                                                           
                       // Output Phase accordian item
                       items.Add()
                           .Text(initiativePhase.Name)
                           .HtmlAttributes(new { @id = string.Format("estimate_phase_{0}", phaseIndex) })
                           .Content(() => { %> 
                                <%= newEstimateButtonLink %> 
                                <%= gridContentHtml %> 
    
                                <% if (initiativePhaseEstimate != null) %>
                                <% { %>                                
                                    <div style="text-align:top;">Estimate Assumptions:</div>
                                    <textarea rows='10' cols='118'><%: initiativePhaseEstimate.Assumptions%></textarea>
                                <% } %>
                                    
                                <div><button name='Save'>Save</button></div>
  
                             
                           <% });
  
                       phaseIndex++;
                   }
                     
               })
               .Render();

I've had the feeling now for a while (see the "grotesque hack" comment above) that I'm swimming upstream with this stuff - if a custom Ajax binding would be better, for example, please tell me.

Still, I feel like what I've done so far should work - the proper values *are* being displayed on the grid, and clicking edit and cancel are entirely client-side issues - none of my code is being called when this fails.

Thanks in advance for any help.

9 Answers, 1 is accepted

Sort by
0
Stewart
Top achievements
Rank 1
answered on 01 Jun 2011, 06:42 PM
It appears that my issue is that the grid is pulling the values being edited not from the grid, but from the template object I instantiated just for the purposes of giving the grid the correct number of columns.

In other words, if I change the EstimatedBudget being set in the default constructor to "888.88", but the value in the actual object is "111.00'", I will see 111.00 when the grid outputs, but 888.88 when I click edit, and 111.00 if I click cancel.  Here's the snippet of the relevant script where I believe the value presented on edit is being lifted from:

"member":"EstimatedBudget",
"type":"Number",
"editor":"\u003cinput class=\"text-box single-line\" id=\"BudgetEstimates_2__EstimatedBudget\"
 name=\"BudgetEstimates[2].EstimatedBudget\" type=\"text\" value=\"888.88\"
 /\u003e\u003cspan class=\"field-validation-valid\"
id=\"BudgetEstimates_2__EstimatedBudget_validationMessage\
"\u003e\u003c/span\u003e"},
the value="888.88" above is only output *ONCE*, for the entire grid, and will be used for any edit of that column, no matter which row! This means even if I were to somehow get my default constructor to have appropriate BudgetEstimate values for a single row, it would not have the appropriate values for other rows.

I originally read (http://www.telerik.com/community/forums/aspnet-mvc/grid/problems-with-mvc-grid-and-csla-object.aspx) that the grid wanted the default constructor "to instantiate a new object of the model type in order to render the editors using Html.EditorFor. " It seems like it is using it for more than type information, however.

I started down this road because of this post: http://www.telerik.com/community/forums/aspnet-mvc/grid/dynamically-added-columns-not-showing-data.aspx, but I don't understand what that poster is doing differently, or what impact a ClientTemplate might have on my issues.

Help appreciated.
0
Stewart
Top achievements
Rank 1
answered on 01 Jun 2011, 09:20 PM
Adding a ClientTemplate to the addValueColumn column expression like so:

 

Action<int> addValueColumn = (i) =>
{
columns.Bound(u => u.BudgetEstimates[i].EstimatedBudget).Title(fiscalYearQuarters[i].DisplayName).ClientTemplate("<#= BudgetEstimates[" + i + "].EstimatedBudget #>").Width(90);
};

 

Appears to fix one problem - the clearing when I cancel an edit. With the ClientTemplate, the appropriate old values are restored. But it does not fix the clearing on edit.

 

 

 

 

 

 

0
Stewart
Top achievements
Rank 1
answered on 07 Jun 2011, 07:25 PM
I am attaching a small sample project that demonstrates this issue, along with a screenshot.

I hope that someone can take some time to look at this issue.
0
Accepted
Atanas Korchev
Telerik team
answered on 08 Jun 2011, 10:12 AM
Hi Stewart,

 Thank you for providing a sample project.

 You have hit a limitation of the Grid. It didn't support indexer expressions such as 

columns.Bound(u => u.BudgetEstimates[i].EstimatedBudget)

 when declaring bound columns.

 Fortunately I managed to add support for that. I am sending you updated project which should work as expected.

Regards,
Atanas Korchev
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Stewart
Top achievements
Rank 1
answered on 08 Jun 2011, 05:54 PM
Thank you very much for trying to fix the issue. It does seem improved, but I still have issues with the project you attached.

When I click to edit a number in the field, it maintains the proper value in the editable field - great! But when I click the checkmark to save, I get a JavaScript error: " 'BudgetJsonThings.0' is null or not an object" inside jquery-1.5.1.min.js.

I thought at first this might be because I did not properly implement the ajax databinding functions, but this crash occurs without any calls being made to the controller.

Am I missing something, or is there something different about our environments?

Thanks again. Screenshot attached.

0
Stewart
Top achievements
Rank 1
answered on 08 Jun 2011, 06:00 PM
It turns out that the JS error happens on IE8 for us. Firefox 4 seems to make it through to the actual server call. I haven't tested other browsers.

[ As a sidenote, are you aware that your forum throws repeated JS errors on every post under IE8? Check out the attached screenshot. ]
0
Atanas Korchev
Telerik team
answered on 09 Jun 2011, 08:06 AM
Hi Stewart,

 I think the problem occurs because you have not implemented properly the Update action method - it returns different model. The JavaScript error is always thrown because of the  unexpected response.

Best wishes,
Atanas Korchev
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Stewart
Top achievements
Rank 1
answered on 10 Jun 2011, 07:36 PM
" I think the problem occurs because you have not implemented properly the Update action method - it returns different model. The JavaScript error is always thrown because of the  unexpected"

You were absolutely correct about this. I was confused because I wasn't seeing the call in Fiddler, but normally we run against IIS, and not the ASP.NET Development Server as was in the sample. So when I couldn't see the call in Fiddler I assumed it wasn't happening. Once I set a breakpoint I could see that it was.

That aside, your fix worked great and we're very pleased. Thank you very much for the help.

0
Mike
Top achievements
Rank 1
answered on 20 Apr 2012, 01:39 AM
Atanas,

You stated: "Fortunately I managed to add support for that. I am sending you updated project which should work as expected."

I went through the fixed sample but I'm not sure what you changed. I am having the same "indexer expressions"
problem on version 2012.1.214 without any luck.

Thanks!!

- Mike
Tags
Grid
Asked by
Stewart
Top achievements
Rank 1
Answers by
Stewart
Top achievements
Rank 1
Atanas Korchev
Telerik team
Mike
Top achievements
Rank 1
Share this question
or