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

Multi editor popup

7 Answers 50 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Rémi
Top achievements
Rank 1
Rémi asked on 13 May 2019, 09:08 AM

Hello,

I have a grid with derived objects and I would like to open different edit popup for each type of child object.

I'll give a simplified example:

Models:

public class Product
{
        public string Label { get; set; }
}
public class TypeA: Product
{
        public string PropA { get; set; }
}
public class TypeB: Product
{
        public int PropB { get; set; }
}
 
public class Order
{
        public int Id {get;set;}
        public virtual ICollection<Product> Products { get; set; }
}

 

Controller:

public async Task<Order> GetById(int id)
{
    Order order = await webApi.GetById(id); // webApi is a private service who calls a json converter to return a strongly typed list with derived class
    return order ;
}

 

At this point, the object order have a Products property which is a collection of TypeA, TypeB and Product

Views:

@model Order
<div>
    @(Html.Kendo().Grid<Product>(Model.Products).Name("grid")
        .Editable(editable => editable.Mode(GridEditMode.PopUp))
        .Columns(columns =>
        {
            columns.Bound(p => p.Label);
            columns.Command(command => { command.Edit(); });
        })
    )
</div>

 

I also create templates in Views\Shared\EditorTemplates

@model Product
 
<div>
    <h1>Product</h1>
</div>
 
-------------------------
 
@model TypeA
 
<div>
    <h1>TypeA</h1>
</div>
 
-------------------------
 
@model TypeB
 
<div>
    <h1>TypeB</h1>
</div>

 

Only the Product template pops up. I guess it's because of Grid<Product> declaration.

How can I strongly typed each row and/or have different editor template? I don't want to show PropA and PropB in my grid but I want to allow to edit them in the popup.

Thanks

 

7 Answers, 1 is accepted

Sort by
0
Georgi
Telerik team
answered on 16 May 2019, 08:09 AM
Hello RĂ©mi,

Generally speaking. the grid creates the editor form based on the specified model - in your case Product. Therefore it is expected that the popup contains only the fields of the Product class.

As a workaround I can suggest you to create a conditional popup and depending on the current item, display the relevant fields.

e.g.


// override default editor  
 $(function () {
        var grid = $('#grid').data('kendoGrid');
        var options = grid.options;
 
        options.editable.template = $("#template-edit").html(); // replace server generated editor with client-side editor
        grid.setOptions(options);
    })
 
 
// editor
 
<script type="text/x-kendo-template" id="template-edit">
    #if(data.PropA) {# // if the item has prop A it is of type TypeA
    #var tempA = kendo.template($("\#typeAEditor").html());#
    #=tempA(data)#
    #} else {#
    #var tempB = kendo.template($("\#typeBEditor").html());#
    #=tempB(data)#
    #}#
</script>
 
// type a and type b editors
 
<script type="text/x-kendo-template" id="typeAEditor">
    @Html.Partial("TypeAEditor") // the partial view which contains the editor for Type A
</script>
 
<script type="text/x-kendo-template" id="typeBEditor">
 @Html.Partial("TypeBEditor") // the partial view which contains the editor for Type B
</script>

However, I am not quite sure how creating items will be handled. Are the users allowed to create new items?


Regards,
Georgi
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Rémi
Top achievements
Rank 1
answered on 20 May 2019, 07:22 AM

Hello,

That's what I thought.

When I was wating for your answer I found an other solution which works fine.

I bound an ajax function to a custom columns.command. The controller select the good view to return and then I bound the dataItem from the grid to it.

        $.ajax({
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            url: this.url,
            type: "post",
            data: JSON.stringify(this.data),
            dataType: "html",
            success: (response) => {
                this.window = $(div).kendoWindow({
                    modal: true,
                    title: this.data["Discriminator"],
                    open: (e: kendo.ui.WindowEvent) => {
                        this.window.center();
                    },
                }).data("kendoWindow");
                this.window.content(response);

                kendo.bind(this.window.element, this.data);

            }
})

this.data contains the discriminator (from entity framework). I send the full object, but I guess I can only pass the discriminator in a get request.

the controller:

[HttpPost]
public IActionResult Edit([FromBody] Product product)
{
    string name = product.GetType().Name;
    string viewName = new StringBuilder(name).Append("Edit").ToString();
    return PartialView(viewName);
}

 

I created view for each type with data-bind attribute like this:

<textarea data-role="editor" data-bind="value:Label"></textarea>

 

Now I just need to create the valid and cancel command =)

 

 

0
Georgi
Telerik team
answered on 23 May 2019, 06:32 AM
Hi RĂ©mi,

Thank you for sharing your solution with the community.

Indeed another approach would be to create your own popup editor. Have in mind that you will have to manually refresh the grid to display the changes made through the custom window. 


Regards,
Georgi
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Rémi
Top achievements
Rank 1
answered on 23 May 2019, 11:01 AM

Hi,

I do not even need to manage the refresh because of the kendo.bind().

But I guess I will have to if I need to improve the dirty tracking

0
Georgi
Telerik team
answered on 28 May 2019, 06:51 AM
Hello RĂ©mi,

Sometimes the items are modified on the server, for example when creating a new record, most commonly the id is assigned on the server. In such cases, to display the latest state of the data in the grid, you will have to refresh it as the client is not aware of the modifications done on the server.


Regards,
Georgi
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Rémi
Top achievements
Rank 1
answered on 28 May 2019, 09:57 AM

You're right, I add a function to set each server response property to keep dirty tracking

so instead of something like this

$.extend(data,serverResponse);

 

I have a function

private dataSetter(data: kendo.data.Model): void {
    let keys = Object.keys(data);
    for (let i = 0; i < keys.length; i++) {
        let value = data[keys[i]];
        let currentValue = this.viewModel.get(`data.${keys[i]}`);
        if (currentValue != value) {
            this.viewModel.set(`data.${keys[i]}`, value);
        }
    }
}

 

0
Georgi
Telerik team
answered on 31 May 2019, 07:49 AM
Hello RĂ©mi,

Thank you for sharing your solution with the community.

I have examined the provided function for syncing the data and I did not notice anything that might cause an issue.


Regards,
Georgi
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Tags
Grid
Asked by
Rémi
Top achievements
Rank 1
Answers by
Georgi
Telerik team
Rémi
Top achievements
Rank 1
Share this question
or