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

Searching for ways to create a dynamic editor template

6 Answers 599 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Sheldon
Top achievements
Rank 1
Sheldon asked on 17 Jul 2014, 07:05 PM
In my scenario I need to load a dropdownlist with data that is determined at runtime.

In my case I have a grid filed with a single product's master data.   Each row in the Kendo grid contains an attribute name and its associated value.   

ex. "Product Name" "Ibuprophen"
      "Strength"            "200 mg"
      "Form"                  "Casule"

Each attribute of the product comes from a different master data table, so what I was hoping to do was pass an entire object containing the information I need to dynamically load the dropdownlist to the editor template like so:

@model IEnumerable<NewGlobalProductCatalogue.Models.ProductInfo>

<p>Product Info - @ViewBag.ProductLanguage</p>
@{ string lang = ViewBag.ProductLanguage; }

@(Html.Kendo().Grid(Model)
    .Name("ProductInfo_" + lang)
    .Columns(columns =>
    {
        columns.Bound(c => c.ColumnName);
        columns.Bound(c => c.ProductData.FieldName);
        columns.Bound(c => c.ProductData).ClientTemplate("#: ProductData.MasterDataValue   
#").EditorTemplateName("EditorProductMasterData");       <<--this is the important line... ProductData is a class with all the data I need to look up the product master data

        columns.Command(command => { command.Edit(); });
    })
    .DataSource(d => d
      .Ajax()
      .Read(r => r.Action("Get", "Product"))
      .Model(m =>
      {
         m.Id(p => p.ProductData.FieldID);
         m.Field(p => p.ColumnName).Editable(false);
         m.Field(p => p.ProductData.FieldName).Editable(false);
         m.Field(p => p.ProductData.MasterDataValue).Editable(true);
      })
     .Update(u => u.Action("Update", "Product"))
     )
    .Pageable()
    .Editable(e => e.Mode(GridEditMode.InLine))   

And then in the editor I would pass the necessary parameters on to the .read action so that the controller would dynamically load the listbox from the correct table.   (NOTE: All the master data tables have a predictable field structure so I simply call a dynamic stored procedure which builds the appropriate SQL query)

Here was my editor:

@model NewGlobalProductCatalogue.Models.ProductMasterData
@(Html.Kendo().DropDownList()
.Name("MasterDataValues")
.DataValueField("MasterDataID")
.DataTextField("MasterDataValue")
.DataSource(d => d
   .Read(r => r.Action("Index", "MasterDataSelection", new { countrycode = Model.Country, lang = Model.Language, GlobalFieldName = Model.FieldName, MDTableName = Model.MasterDataTableName }))
)
.SelectedIndex(0)
)


Of course it all came crashing down when I realized that the editor template is only called once when the grid is built.   The weird part is, the controller that loads the data IS called every time I click on a rows EDIT button.
 
public class MasterDataSelectionController : Controller
    {
        //
        // GET: /MasterDataSelection/
        private APOIPCEntities db = new APOIPCEntities();
        public JsonResult Index(string countrycode, string lang, string GlobalFieldName, string MDTableName)
        {

           return  this.Json(db.GetCountryLanguageMasterData(countrycode,lang,GlobalFieldName, MDTableName), JsonRequestBehavior.AllowGet);

        }
}

I am wondering if someone can think of a sneaky way this behavior could be exploited to achieve the dynamic data loading I am looking for.   Maybe if I could put a function call in my controller that could look back into the grid to see what row it is currently focused on, and extract the necessary data from it prior to calling the stored procedure ..... just not sure how to do that.


Thanks for any thoughts you might have.

-Sheldon 








6 Answers, 1 is accepted

Sort by
0
Petur Subev
Telerik team
answered on 21 Jul 2014, 11:53 AM
Hello Sheldon,

That's right the editor template is turned into JavaScript function with template which is later on executed. Since at the moment of execution you cannot get reference to the model (you can use only MVVM bindings) you can use approach similar to this one in the attached project.

I hope this helps.

Kind Regards,
Petur Subev
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Sheldon
Top achievements
Rank 1
answered on 21 Jul 2014, 08:28 PM
Thanks so much!   I'll go through this and see what I can learn... may take a a day or two :) 

Many thanks!
0
Sheldon
Top achievements
Rank 1
answered on 21 Jul 2014, 08:42 PM
BTW ... Vladimir Iliev  also sent me some code for incell editing using cascading dropdownlists ... initially I thought that might do the trick as well, but it is looking less and less likely now that I dig into it.     The Cascading feature still doesn't seem to let me pass multiple columns from within the current row of the grid.

Your project looks a lot more promising :) 
0
Sheldon
Top achievements
Rank 1
answered on 23 Jul 2014, 07:07 PM
This worked great ... I was able to pass multiple parameters by referencing them in the javascript within the template.

The only minor thing I haven't been able to figure out yet is how columns are referenced if you happen to have an object in a column, rather than a single value.

 columns.Bound(c => c.ProductData).ClientTemplate("#: ProductData.MasterDataValue #").EditorTemplateName("EditorProductMasterData");

Not sure how to reference a field from within that object .... for example the "ProductData.Country"

I've tried:

    function sendName() {
        return  {
            name: $("[name=NamE]").val(),
            country: $("[name=ProductData.Country]").val()
        };

Among many other combinations without any luck.

Any thoughts?


0
Petur Subev
Telerik team
answered on 25 Jul 2014, 01:06 PM
Hello Sheldon,

What this code:

 $("[name=NamE]").val(),

does is that it will search for input with name attribute set to NamE. Which means we search the DOM for such value and we retrieve it from the input. This means that it will work only in scenarios where there is bound column to the NamE property and it is editable. You can experiment and see that if you do not have such column the code won't work - as I mentioned this is the only work-around that I can suggest. For nested fileds like there won't be such editor.

So you might need to take slightly different approach, first get the ID that identifies the row in the Grid, then once you have the ID of the record get the corresponding dataItem (check dataSource.get) then you should have access to the object and its nested objects.

<script type="text/javascript">
    function sendName() {
        var rowId = $("[name=PersonID]").val();
        var model = $("#persons").data("kendoGrid").dataSource.get(rowId);
        // now you can use model.NestedProperty
        return  {
            name: $("[name=Name]").val()
        };
    }
</script>
 
 
@(Html.Kendo().DropDownListFor(f => f)
            .DataSource(ds =>
            {
                ds.Read(read =>
                {
                    read.Action("GetRoles", "Home").Data("sendName").Type(HttpVerbs.Post);
                });
            })
            .AutoBind(false)
            .DataTextField("RoleName")
            .DataValueField("RoleID")
        )


Kind Regards,
Petur Subev
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Sheldon
Top achievements
Rank 1
answered on 25 Jul 2014, 07:45 PM
Thanks so much!

This did the trick!   I was a bit confused as to where you got the identifier "kendoGrid" specified within your .data method, but eventually found it within the kendo.all.min.js file.   Starting to understand things a bit better but definitely need to get better an playing with the DOM.

So now I have it dynamically populating my dropdown list depending on the row!  YEAH!

Just have to figure out how to save the changes back to the appropriate table(s) ... probably call a stored procedure from the updated method of the controller and pass in the necessary information to dynamically build the appropriate SQL update statement.

In reality I am probably making my life a lot more difficult than it needs to be, but at least I am learning lots.

Thanks!
Tags
Grid
Asked by
Sheldon
Top achievements
Rank 1
Answers by
Petur Subev
Telerik team
Sheldon
Top achievements
Rank 1
Share this question
or