Custom editor And foreign key Grid

9 posts, 1 answers
  1. Gaetano
    Gaetano avatar
    71 posts
    Member since:
    May 2012

    Posted 18 Mar 2014 Link to this post

    Hi Guys,
    I'm working with mvc and EF + razor.

    I'd like to edit a model that is composed like this:
    (EF generated from DB first)
    public partial class DATACLASS_T003
        {
            public DATACLASS_T003()
            {
                this.DATACLASS_ATTRIBUTES_T012 = new HashSet<DATACLASS_ATTRIBUTES_T012>();
            }
         
            public long PARENTID { get; set; }
            public long CLASSID { get; set; }
            public Nullable<long> DATACLASS_PARENTID { get; set; }
            public int GEOMETRY_TYPE { get; set; }
            public string NAME { get; set; }
            public int ID { get; set; }
         
            public virtual ICollection<DATACLASS_ATTRIBUTES_T012> DATACLASS_ATTRIBUTES_T012 { get; set; }
            public virtual TIP_GEOMETRY_T014 TIP_GEOMETRY_T014 { get; set; }
        }
    Now, I handled all the field with a normal razor view...All but the ICollection<DATACLASS_ATTRIBUTES_T012> DATACLASS_ATTRIBUTES_T012

    public partial class DATACLASS_ATTRIBUTES_T012
        {
            public DATACLASS_ATTRIBUTES_T012()
            {
                this.ATT_VALUES_T004 = new HashSet<ATT_VALUES_T004>();
            }
         
            public int ATTRIBUTEID { get; set; }
            public int DATACLASS_ID { get; set; }
            public Nullable<int> UOM_ID { get; set; }
         
            public virtual ICollection<ATT_VALUES_T004> ATT_VALUES_T004 { get; set; }
            public virtual DATACLASS_T003 DATACLASS_T003 { get; set; }
            public virtual DC_ATTRIBUTES_T006 DC_ATTRIBUTES_T006 { get; set; }
            public virtual UNITS_OF_MEASURE_T013 UNITS_OF_MEASURE_T013 { get; set; }
        }

    Here ATTRIBUTEID is the foreign key for DC_ATTRIBUTES_T006  table while UOM_ID is the foreign key for UNITS_OF_MEASURE_T013 table.

    in my grid, I'd like to edit theese fields as combobox. I checked the "custom editor" and "foreign key" example but I'm not able to make them work.

    following the custom editor ex, when I enter edit mode (inline or incell) the grid shows me ever entity field (like 4-5).
    On the other hand, trying with the foreign key example I got an error
    Here is my grid
    @(Html.Kendo().Grid(Model.DATACLASS_ATTRIBUTES_T012)
                .Name("Grid")
                .ToolBar(commands => { commands.Create().Text("New Attribute"); commands.Save(); })
                .Columns(columns =>
                {
                    columns.Bound(p => p.ATTRIBUTEID).Title("Attribute");
                    columns.ForeignKey(p => p.UOM_ID, (System.Collections.IEnumerable)ViewData["Measure"], "ID", "CODE")
                        .Title("Measure Unit");
                })
                .Pageable()
                .Sortable()
                .Scrollable()
                .Filterable()
                .Editable(mode => mode.Mode(GridEditMode.InCell))
                .DataSource(dataSource => dataSource
                    .Ajax()
                    .PageSize(5)
                    .ServerOperation(false)
                    .Batch(true)
                    .Model(model =>
                    {
                        model.Id(v => v.ATTRIBUTEID);
                        model.Field(v => v.ATTRIBUTEID).Editable(false);
                        model.Field(v => v.UOM_ID).DefaultValue(1);
                    })
                    .Read(r => r.Action("GetAttributeByDataClass/" + Model.ID, "Attribute"))
                    .Update(r => r.Action("UpdateAttribute", "Attribute"))
                 )
            )
    and my read action:

    public ActionResult GetAttributeByDataClass([DataSourceRequest]DataSourceRequest request, long Id)
            {
                IList<DATACLASS_ATTRIBUTES_T012> res = db.DATACLASS_ATTRIBUTES_T012
                    .Include(x => x.DC_ATTRIBUTES_T006)
                    .Include(x => x.UNITS_OF_MEASURE_T013)
                    .Where(x => x.DATACLASS_ID == Id).ToList();
     
                foreach (DATACLASS_ATTRIBUTES_T012 item in res)
                {
                    item.DC_ATTRIBUTES_T006.DATACLASS_ATTRIBUTES_T012 = null;
                    item.UNITS_OF_MEASURE_T013.DATACLASS_ATTRIBUTES_T012 = null;
    //to avoid circular ref
                }
     
     
                ViewData["Attribute"] = db.DC_ATTRIBUTES_T006;
                ViewData["AttributeDefault"] = db.DC_ATTRIBUTES_T006.First(); 
                ViewData["Measure"] = db.UNITS_OF_MEASURE_T013;
                DataSourceResult result = res.ToDataSourceResult(request);
                return Json(result);
            }

    The Error I got is: Value cannot be null.Parameter name: items (the controller's action breakpoint is not hit)

    The point is that to me, in this view, attributes and measure units are like enum, I'd like to use them just as a combo with Id-Name tuple...all I need is to have the foreign key field not null on update/create.

    Thanks
    Fabio
  2. Daniel
    Admin
    Daniel avatar
    2231 posts

    Posted 20 Mar 2014 Link to this post

    Hello Fabio,

    The  exception will be thrown because the foreignkey data is populated in the read action. You should add the data to the VIewData dictionary in the action that returns the View with the Grid in order for it to be available when the Grid is being rendered.
    In order to use a custom editor you should follow the steps described in this documentation topic:
    [UIHint("AttributeIDEditor")]
    public int ATTRIBUTEID { get; set; }
    //add a view named AttributeIDEditor in the EditorTemplates folder
    @model int
     
    @(
        Html.DropDownListFor(model => model)
            ...
     
    )


    Regards,
    Daniel
    Telerik
     

    Build cross-platform mobile apps using Visual Studio and .NET. Register for the online webinar on 03/27/2014, 11:00AM US ET.. Seats are limited.

     
  3. Gaetano
    Gaetano avatar
    71 posts
    Member since:
    May 2012

    Posted 24 Mar 2014 in reply to Daniel Link to this post

    Hi Daniel,
    I managed to solve a part of my issue..
    The real problem was the I was not passing some properties bound to the grid.
    now my grid bound look like this

    columns.Bound(m => m.ATTRIBUTEID).EditorTemplateName("AttributeEditor").EditorViewData(ViewBag.Attributes).ClientTemplate("#:DC_ATTRIBUTES_T006.NAME#").Title("Attribute");
    columns.Bound(m => m.UOM_ID).EditorTemplateName("MeasureUnitEditor").EditorViewData(ViewBag.Measure).ClientTemplate("#:UNITS_OF_MEASURE_T013.CODE#").Title("Measure Unit");

    now I have 2 questions..

    1) what's the difference in using a normal columns.bound and a columns.foreignKey?

    2) When I try to create a new record in my grid, I get this error:

    Uncaught ReferenceError: DC_ATTRIBUTES_T006 is not defined 

    should I provide a null default value? or what?

    Thanks
    Fabio
  4. Gaetano
    Gaetano avatar
    71 posts
    Member since:
    May 2012

    Posted 24 Mar 2014 in reply to Gaetano Link to this post

    Ok I undertood what is the issue (point 2)

    The Client template is bound to a different property.
    (just to recall, UOM_ID is the foreign key to UNITS_OF_MEASURE_T013 and DOMAINID is the fk to DC_ATTRIBUTES_T006)
    of course I want to show the name of the class and not its id...
    When I create a new line the classes are null and the template fails to find the selected property.

    How can I achieve my expected result?

    Should I bind directly to the class and provide a default value for it? anything else? 

    Thanks
    Fabio
  5. Answer
    Daniel
    Admin
    Daniel avatar
    2231 posts

    Posted 26 Mar 2014 Link to this post

    Hello again Fabio,

    The difference is that the ForeignKey column also allows to specify a collection that will be used to show the corresponding text instead of the column value. The ForeignKey column editor and filter inputs are also dropdownlists using the provided data by default.

    Regarding the error - it will thrown because the objects will be null by default for new items. You can either use the approach demonstrated in the custom editor demo and  specify a default value for the objects via the DataSource Model or use a condition in the template that checks if the object is not null before accessing its text field:
    .ClientTemplate("#: data.DC_ATTRIBUTES_T006 ? DC_ATTRIBUTES_T006.NAME : ''#")


    Regards,
    Daniel
    Telerik
     

    Build cross-platform mobile apps using Visual Studio and .NET. Register for the online webinar on 03/27/2014, 11:00AM US ET.. Seats are limited.

     
  6. Gaetano
    Gaetano avatar
    71 posts
    Member since:
    May 2012

    Posted 26 Mar 2014 in reply to Daniel Link to this post

    Hi Daniel,

    So, about my case would  be better to use the foreing key i guess...I'll try it out..
    regarding te error,
    your template solve my issue!!!
    I tried the same but I missed out the "data." part...not sure to fully undestand how the template works...

    anyway thanks again!
    Fabio
  7. Daniel
    Admin
    Daniel avatar
    2231 posts

    Posted 28 Mar 2014 Link to this post

    Hello Fabio,

    Since you have both the related object and the ID in the model you can use both approaches but the foreignkey column has the advantage that it can be filtered and grouped which is not available by default for an object.

    Regards,
    Daniel
    Telerik
     

    Build cross-platform mobile apps using Visual Studio and .NET. Register for the online webinar on 03/27/2014, 11:00AM US ET.. Seats are limited.

     
  8. Senthilkumar
    Senthilkumar avatar
    12 posts
    Member since:
    May 2015

    Posted 22 Jun 2015 Link to this post

    Hi Team,

     Please let me know how to get the foreign key drop down (InstanceTypeIds) selected value using Jquery to send input value to cascading drop down (InstanceId) of grid row. 

     

        @(Html.Kendo().Grid<Flextronics.DevFactory.Ingrex.Entity.IngrexDataEntity.IngrexGlobalNewRequest>()
        
        .Name("GridGlobalNewRequest")
        .Columns(columns =>
        {
            columns.ForeignKey(p => p.InstanceTypeIds, (System.Collections.IEnumerable)ViewData["listofinstanceTypes"], "InstanceTypeId", "InstanceTypeName").Title("InstanceType").Width(120).EditorTemplateName("InstanceTypeIds");
            columns.ForeignKey(p => p.InstanceId, (System.Collections.IEnumerable)ViewData["listofInstance"], "InstanceId", "InstanceNm").Title("Instance").Width(120).EditorTemplateName("InstanceId").Width(120);
            columns.Bound(p => p.StartCompany).Title("Start").Width(90);
           // columns.Command(command => command.Edit()).Width(80).HtmlAttributes(new { style = "text-align:center" });
            columns.Command(command => command.Destroy()).Width(80).HtmlAttributes(new { style = "text-align:center" });
        })
                .ToolBar(toolbar => {
                    toolbar.Create();
                    toolbar.Save();
                })
                
        .Editable(editable => editable.Mode(GridEditMode.InCell))
        .Pageable(page => page.Enabled(true).PageSizes(new int[] { 10, 50, 100, 500}))
        .Sortable()
        .Scrollable()
     
        .DataSource(dataSource => dataSource
                    .Ajax()
                   
                    .PageSize(20)                
                   
                    .Model(model =>
                    {
                        model.Id(p => p.InstanceTypeIds);
                        model.Field(p => p.InstanceId);
                        model.Field(p => p.InstanceTypeIds);
                    })
                    
                    
                //.Create(update => update.Action("EditingInline_Create", "NewRequest"))
                //.Read(read => read.Action("EditingInline_Read", "NewRequest"))
                //.Update(update => update.Action("EditingInline_Update", "NewRequest"))
                //.Destroy(update => update.Action("EditingInline_Destroy", "NewRequest"))
        
                    .Create("EditingInline_Create", "NewRequest")
                    .Read("EditingInline_Read", "NewRequest")
                    .Update("EditingInline_Update", "NewRequest")
                    .Destroy("EditingInline_Destroy", "NewRequest")
        
        )
        
        )

  9. Rosen
    Admin
    Rosen avatar
    3253 posts

    Posted 26 Jun 2015 Link to this post

    Hello Senthilkumar,

    You can get the other values of the edited record by getting reference to the edited cell's parent row and retrieving the associated model instance. Similar to the following:

    function getInstanceTypeIds() {
        var grid = $("#GridGlobalNewRequest").data("kendoGrid");
        var row = grid.tbody.find(".k-edit-cell").closest("tr");
     
        return grid.dataItem(row).InstanceTypeIds;
    }

    On a side note. As your question is not directly related to the thread's initial topic, I would ask you to open a separate support request if additional questions arise.

    Regards,
    Rosen
    Telerik
    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 Feedback Portal and vote to affect the priority of the items
Back to Top