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

[Solved] Advanced Custom Editing from Grid

9 Answers 370 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.
Mark
Top achievements
Rank 1
Mark asked on 18 Jul 2011, 03:53 PM
I am currently evaluating Telerik MVC for a large project, and the client requirements are very particular on the way editing records from a a grid should function. It does not appear that Telerik grid's built in editing functions are sufficient, and we will have to work around that by simply not using Telerik's Insert, Update, Delete command bindings, and just doing it ourselves. But before I write that off, I want to make sure I did not miss something.

The requirements are to be able to have an advanced grid with sorting, filtering, paging, etc., which Telerik's grid fits perfectly. The grid should also have a row buttons to open an Edit dialog which displays a custom edit template (MVC Model Template), as well as an Add New button at the top or bottom, which also opens a custom edit template for new records. Each row must also have a checkbox to select the records. A button in the header for "multiple edit" and "multiple delete" then allows for the checked records to be deleted in batch, or edited in batch--that is, a single edit popup for editing multiple records at once.

Here are the problems I'm running into. First, while Telerik works great with MVC Model Templates for the most part, there's a funny problem where it does not appear to have the model data available in all cases. Consider the following very simple Model Template (located in /Shared/EditorTemplates):

@model AdventureWorks.Common.EmployeeModel
 
@Html.LabelFor(p => p.EmployeeID): @Model.EmployeeID<br />
@Html.LabelFor(p => p.FirstName):   @Html.EditorFor(p => p.FirstName) <br />
@Html.LabelFor(p => p.LastName):    @Html.EditorFor(p => p.LastName) <br />

If this is invoked from the grid (using the commands.Edit() call as normal, and PopUp mode), the Window appears with First Name and Last Name filled in on the Textboxes as expected, but EmployeeID is 0! If instead of specifying @Model.EmployeeID I put it in an EditorFor (that is, @Html.EditorFor(p => p.EmployeeID) ), then I DO see the correct ID. However, I do not want EmployeeID to be in a textbox (editable or not -- I do have the ReadOnly attribute set, so it is a readonly box, but I do not want it in a box at all). It seems like the model is not really loaded until a certain point, but I cannot quite figure out what is going on to cause this issue. If I can get that working correctly, it will go a long way to solving *a lot* of my issues (for instance, I want to use Model.EmployeeType to default certain things, or hide or show certain fields, which I can only do if I can get the value of Model.EmployeeType before the form is rendered).

The bigger problem is multiple select and edit/delete. Selecting multiple records and deleting them is not too much of an issue. However, with Paging (I am using Ajax binding), I can only select the items currently displayed--if I select 4 items on page 1, and then 3 items on page 2, and click delete, only the 2 items on page 2 are deleted. I understand why this is, but our client does not, and our client wants the "best of both worlds" with Ajax paging as well as the ability to remember selections from prior pages.

Now, editing multiple records at once is the biggest challenge of all. For this, the requirement is to be able to select multiple records (checking them as previously described) and clicking an "Edit Selected Records" button that is in the header. This would then open a window with an edit view that has only a few fields in it that are designed as being "multi-editable". For instance, a "due date" might be multi-editable, allowing the user to select 20 records, click edit, and change the due-date for all selected records to the same due date. This appears to be completely outside of anything that Telerik is designed to do, and I am pretty sure we will just have to have a some custom javascript and a custom control to handle this.

Anyway, I just wanted to make sure I wasn't missing something before going on on my own direction with this. Thank you.

9 Answers, 1 is accepted

Sort by
0
Atanas Korchev
Telerik team
answered on 19 Jul 2011, 09:08 AM
Hi Mark, 

Up to your questions:

  1. I am not really sure why your custom model template does not work. You can check this code library project for a working example. Perhaps it would help.
  2. Keeping track of checked records should be possible even when the user changes the page. You can store the checked records in a JavaScript array. Paging won't clear that.
  3. Implementing multi-row editing would be a challenging task. The main problem is guarantee unique name and id attribute for the editor controls. I am not sure this could be easily implemented on the client-side. What I can suggest is to check the batch editing mode supported out of the box. It allows to edit more than one record and submit the changes in one batch.

Regards,
Atanas Korchev
the Telerik team

Register for the Q2 2011 What's New Webinar Week. Mark your calendar for the week starting July 18th and book your seat for a walk through of all the exciting stuff we will ship with the new release!

0
Mark
Top achievements
Rank 1
answered on 19 Jul 2011, 01:53 PM
I have studied the project in question, but it does not address the issue. The Template code from the example.

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<CustomPopUpForm.Models.Customer>" %>
<fieldset>
    <legend>Customer</legend>
    <%= Html.HiddenFor(c => c.CustomerID) %>
    <div>Contact Name: <%= Html.EditorFor(c => c.ContactName) %></div>
    <div>Company Name: <%= Html.EditorFor(c => c.CompanyName) %></div>
</fieldset>

...uses EditorFor and HiddenFor. Those do indeed work. But the problem I was referring to was the fact that if I try to access properties on the model directly, they are unset. For instance, accessing Mode.EmployeeId returns 0, while at the same time Html.EditorFor(model => model.EmployeeID) gives the correct value. I thought perhaps Html.DisplayFor(model => model.EmployeeID) would work, but it does not -- it also returns 0. So basically, I am asking why does Html.EditorFor(model => model.EmployeeID) give the correct value, while Html.DisplayFor(model => model.EmployeeID) and Model.EmployeeID return 0, or an unset value?

As far as multi-record editing goes, the Batch Editing example is not what I am talking about. I am talking about a mechanism whereby you select several records, then click an "edit selected" button, and get a popup window editor which allows for editing only a few select values, so the user can set all selected records to having the same value for those certain fields (i.e., a due date, or some such). Telerik grid clearly has no such capability out of the box, but to be fair no one else does either.

I have come across another problem, or oddity, however. While trying to add a custom command button to grid rows, I discovered that GridActionCommandFactory does not support Custom. It only supports Edit, Delete, and Select. Why does GridToolbarCommandFactory support Custom while GridActionCommandFactory does not? How I am supposed to put Custom command buttons on rows? Obviously, I could just insert the code for button with a jquery event in its own column, but I really wanted it to be "integrated" with the other command buttons provided by Telerik Grid, just as I can in the Toolbar.

0
Atanas Korchev
Telerik team
answered on 19 Jul 2011, 03:05 PM
Hello Mark,

 The properties of the model are not set when you are using ajax editing. The reason is simple - the editor template is populated client-side. The editor template is used only to get the editor HTML. The grid then uses the "name" attribute of the rendered html elements to populate them from the model.

 I understand that the batch editing is not what you originally requested. It this the closest out-of-the-box solution we can provide for now.

 Indeed custom buttons are only supported for the toolbar. We have this logged as a feature request and you  may consider voting for it. It is one of the most requested features so we will probably implement it in the upcoming release.

The current way to implement custom commands is by using a template column.

Regards,
Atanas Korchev
the Telerik team

Register for the Q2 2011 What's New Webinar Week. Mark your calendar for the week starting July 18th and book your seat for a walk through of all the exciting stuff we will ship with the new release!

0
Mark
Top achievements
Rank 1
answered on 19 Jul 2011, 03:41 PM
Ok, lets get back to the issue with the Templates as this is extremely critical. Please illustrate on how I can accomplish the following:

@model AdventureWorks.Common.EmployeeModel
 
@Html.LabelFor(model => model.EmployeeID): @Model.EmployeeID<br /> <---- show the EmployeeID, no textbox, just the text value
@Html.LabelFor(model => model.FirstName):  @Html.EditorFor(model => model.FirstName) <br />
@Html.LabelFor(model => model.LastName):   @Html.EditorFor(model => model.LastName) <br />
@if (Model.HireDate > DateTime.Parse("5/1/2011")) {  <----logic of some kind based on a Model value
    <p>New Employee</p>
} else {
    <p>Old Employee</p>
}

See the two arrow points above that illustrate the problem. What I have coded does not work, but ordinarily should. I just want to know how you would solve the above problem.
0
Atanas Korchev
Telerik team
answered on 19 Jul 2011, 07:38 PM
Hi Mark,

 You can use the OnEdit event to set additional values in the editor popup.

Greetings,
Atanas Korchev
the Telerik team

Register for the Q2 2011 What's New Webinar Week. Mark your calendar for the week starting July 18th and book your seat for a walk through of all the exciting stuff we will ship with the new release!

0
Mark
Top achievements
Rank 1
answered on 20 Jul 2011, 07:34 PM
Well, I figured out how to do it using a javascript function like so (called when an edit button is clicked):

//get a reference to the Telerik Window object
var window = $("#Edit").data("tWindow");
//change the contentURL to reference the currently selected record ID
window.contentUrl = '/GridExample/EmployeeEdit?employeeID=' + recordID; //record ID is stored when the row is selected
//refresh and open the window.
window.refresh().center().open();

Basically, I just rewrite the contentURL for the Telerik Window that will be displaying the Edit form (a partial view that references the custom Editor Template for Employee). Doing it this way means the Model *is* available at access time, rather than being depend on the "name" attribute on the form elements (which, by the way, only works for elements that have a "name" attribute).

I'm not sure why you (Telerik) didn't do it this way.

0
shawn
Top achievements
Rank 1
answered on 02 Aug 2011, 07:06 PM

When setting up an MVC 3 application, the foreign keys that should allow drop down lists to select an item do not get rendered as drop downs, but as static inputs. This can be resolved by creating a custom display and view for that field.

We will need to start by creating a custom partial view that will live in “~/Views/Shared/DisplayTemplates/UserGuid.cshtml”, and “~/Views/Shared/EditTemplates/UserGuid.cshtml”. The code for one is located below:

@model Guid

@{

incMvcSite.Models.MvcSiteDB db = new incMvcSite.Models.MvcSiteDB();

incMvcSite.Models.SecUser usr = db.SecUsers.Single(u => u.Guid == Model);

}

@usr.Display

This is a display for template that will look up the item in the referenced table and display it. We also need an edit for template as follows:

@model Guid

@{

incMvcSite.Models.MvcSiteDB db = new incMvcSite.Models.MvcSiteDB();

SelectList items = new SelectList(db.SecUsers.OrderBy(i => i.Display).ToList(), "Guid", "Display", Model);

}

@Html.DropDownList("", items)

The edit for template is implemented as a drop down list. Originally, we has used static HTML code, but the problem will appear of implementing a “prefix”. Static HTML code does get handled by HTML helpers, so it’s recommended that you use the HTML.DropDownList().

To force the MVC framework to use the new Display and Edit for templates, we need to annote our model item an add the following line:

[UIHint("UserGuid")]

This will cause MVC to use the Display and Edit templates named “UserGuid”, which are just partial views.


Internetwork Consulting

0
Neil
Top achievements
Rank 1
answered on 04 Nov 2011, 09:24 PM
Hi Mark,

nice solution to your DisplayFor problem - i'll have to try that - i was having the same problem trying to display a label with model information on an editor view.

Regarding your batch editing problem, i was wondering if you found a solution.  I have the same request from my customer.

neil
0
MICHAEL
Top achievements
Rank 1
answered on 31 Oct 2012, 09:57 AM
Mark,

I'm using your technique to load a window via a partial view that has a editor template:
//get a reference to the Telerik Window object
var window = $("#Edit").data("tWindow");
//change the contentURL to reference the currently selected record ID
window.contentUrl = '/GridExample/EmployeeEdit?employeeID=' + recordID; //record ID is stored when the row is selected
//refresh and open the window.
window.refresh().center().open();

The problem I have is my form is not submitting when i click the save button.   Here is my code, can you point out what I'm doing wrong?

This is my code where I open the window like you have:

 

//get a reference to the Telerik Window object

var window = $("#EditWindow").data("tWindow");

//change the contentURL to reference the currently selected record ID

window.contentUrl =

'/Hospital/HospitalEdit?id=' + id; //record ID is stored when the row is selected

//refresh and open the window.

window.refresh().center().title

 

"Hospital Profile").open();


Here is my HospitalEdit partial view that renders my editor template:

<% using (Html.BeginForm("HospitalEdit", "Hospital", FormMethod.Post, new { hospital = Model }))
   {
    Html.RenderPartial("EditorTemplates\\HospitalViewModel", Model); %>
    <button type="submit" class="t-button">Save</button> <%
   }
%>
<br />

Here is my controller method that accepts the http post:

[

HttpPost]

 

public ActionResult HospitalEdit(HospitalViewModel hospital)

{
}

Tags
Grid
Asked by
Mark
Top achievements
Rank 1
Answers by
Atanas Korchev
Telerik team
Mark
Top achievements
Rank 1
shawn
Top achievements
Rank 1
Neil
Top achievements
Rank 1
MICHAEL
Top achievements
Rank 1
Share this question
or