Create new ListView item associated with a parent

1 Answer 142 Views
ListView
Jon
Top achievements
Rank 1
Iron
Jon asked on 26 Jan 2022, 08:54 PM

I am struggling to understand how to handle create operations when ListView contents must be associated with a parent object.  To demonstrate by using examples from your docs, let's say the orders are part of a store object:

public class StoreViewModel
{
    public int StoreID {get; set;}
    IEnumerable<OrderViewModel> StoreOrders {get; set;}
    // various other fields
}

My goal is to have a View, Model type is the StoreViewModel, and a ListView showing the Orders from a specific store.  The Create function of the ListView would need to know the store ID and have it passed somehow.  I think I need something like this:

@model StoreViewModel

@(Html.Kendo().ListView<OrderViewModel>()
    .DataSource(ds => ds
        .Ajax()
        .Model(m => m.("OrderID")
        .Read(read => read
            .Action("Orders_Read", "ListView")
            .Data(@<text>@Html.Raw(Json.Serialize(Model))</text>)    
        )
        .Create(create => create
            .Action("Orders_Create", "ListView")
            .Data(@<text>@Html.Raw(Json.Serialize(Model))</text>)    
        )
    )
)

 

The controller has this method for read, which works perfectly:

public ActionResult Orders_Read([DataSourceRequest]DataSourceRequest request, StoreViewModel store)
{
    // code that returns orders from one store
}

However, when I try to create, the same .Data parameter doesn't seem to be passed:

public ActionResult Orders_Create([DataSourceRequest]DataSourceRequest request, StoreViewModel store)
{
    // misc code to make a new order and add to DB goes here
    newOrder.StoreID = store.StoreID;  // this fails
}

When looking through this with the debugger, "store" is populated in the Orders_Read method, but is null in the Orders_Create method, even though I'm trying to use them the same way.  While that's concerning, I suspect there's an overall better way to do this period.  Are there any examples that show similar scenarios with related models/objects?

 

Jon
Top achievements
Rank 1
Iron
commented on 27 Jan 2022, 03:50 PM

Another thing I tried today - using the .Filter() method.  I was hoping I could filter by store ID then see this via the DataSourceRequest object within the controller:

.Filter(filters =>

{

   filters.Add(s => s.StoreID).Equals(Model.StoreID);

})

This *appears* to work initially, but when following along in the debugger, Orders_Read, I look at the request.Filters[0] and find that the Member and Operator are populated correctly, but Value is null.  This causes an exception in ToDataSourceResult().  I'm not sure why the filter value wouldn't be populated.  Even removing Model.StoreID and hard coding an int like 2 doesn't work.  No idea why the filter is broken.

 

1 Answer, 1 is accepted

Sort by
0
Stoyan
Telerik team
answered on 31 Jan 2022, 06:49 PM | edited on 31 Jan 2022, 06:50 PM

Hi Jon,

You are on the right track. To get the StoreViewModel object in the Orders_Create Controller method add a parameter for the newly created Order and then add the parameter for the store:

public ActionResult Orders_Create([DataSourceRequest]DataSourceRequest request, OrderViewModel order, StoreViewModel store)
{
      ...
}
This way the Action method will be able to use both Models to persist the new order.

 

Regarding your second question, the most probable reason for the encountered exception is that the OrderViewModel doesn't contain a StoreID property to be filtered by. If this is the case you would need define that field in the OrderViewModel.

I hope the information above is useful. Please don't hesitate to let me know should further questions occur.

Regards,
Stoyan
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Jon
Top achievements
Rank 1
Iron
commented on 02 Feb 2022, 01:44 PM

Thanks Stoyan.  Is the second parameter fed the object from .Data() ?  How do you recommend serializing that object?  Does it have to be an object, or can it be fed simple types (int, string, etc) as well?

I wish the documentation described that functionality more thoroughly.

Stoyan
Telerik team
commented on 04 Feb 2022, 11:41 AM

Hi Jon,

There are a couple of ways to send data to the Controller Action method.

  1. Add a static parameter to the DataSource tranport method:
    .DataSource(dataSource => dataSource
                    .Ajax()
                    .PageSize(5)
                    .Read(read => read.Action("Read_Orders", "Grid", new{ employeeID = "1" }))
    )
  2. Use the Data configuration method of the transport. This will allow you to define a JavaScript function that returns the data sent to the server.

The Action method is able to parse Json serialized key-value pairs as parameters. It will be able to convert the string values to the simple types listed in the related Microsoft Model binding article. If you need you can also pass a complex object which will be parsed to a class defined by you. The order parameter of type OrderViewModel is an example of this.

 
Tags
ListView
Asked by
Jon
Top achievements
Rank 1
Iron
Answers by
Stoyan
Telerik team
Share this question
or