I need to send a model to my controller action. I have created a Kendo grid:
Html.Kendo().Grid<XXXX.WebUI.Models.Employees.LocationsListViewModel>()
.Name("EmployeeLocationsGrid")
.Columns(columns => {
columns.Select().Width(45);
columns.Bound(c => c.UIDEmployee).Visible(false);
columns.Bound(c => c.UIDEmployee_Location).Title("Id").Width(50);
if (Model.LocationsEntities != null)
{
columns.ForeignKey(f => f.UIDLocation, Model.LocationsEntities?.Items, "UIDEntity", "Name")
.Title("Location")
.EditorTemplateName("FieldListLocations")
.EditorViewData(new { locations = Model.LocationsEntities.Items })
.Width(200);
}
if (Model.LocationsEntities != null)
{
columns.ForeignKey(f => f.UIDSublocation, Model.SublocationsEntities?.Items, "UIDEntity", "Name")
.Title("Sublocation")
.EditorTemplateName("FieldListSublocations")
.EditorViewData(new { sublocations = Model.SublocationsEntities.Items })
.Width(200);
}
columns.Bound(c => c.Main)
.Title("Main")
.EditorTemplateName("FieldCheckBox")
.ClientTemplate("#= Main ? 'Yes' : 'No' #")
.Width(100);
columns.Bound(c => c.PercentageOfDedication)
.Title("% Dedication")
.EditorTemplateName("FieldNumericTextBox")
.Format("{0} %")
.Width(200);
columns.Bound(c => c.StartDate)
.Title("Start Date")
.ClientTemplate("#= kendo.toString(kendo.parseDate(StartDate), 'dd/MM/yyyy') #")
.EditorTemplateName("FieldDateOnlyPicker")
.Width(200);
columns.Bound(c => c.EndDate)
.Title("End Date")
.ClientTemplate("#= EndDate != null ? kendo.toString(kendo.parseDate(EndDate), 'dd/MM/yyyy') : '<strong>Currently</strong>' #")
.EditorTemplateName("FieldDateOnlyPicker")
.Width(200);
columns.Bound(c => c.Comments)
.Title("Comments")
.EditorTemplateName("FieldTextArea")
.Width(250);
columns.Command(command => {
command.Edit().Text(" ").UpdateText(" ").CancelText(" ").IconClass("bi bi-pencil-square").HtmlAttributes(new { @class = "btn btn-outline-primary", title = "Edit" });
command.Custom("deleteLocation")
.Click("function(e) { var dataItemLoc = this.dataItem($(e.target).closest('tr')); window.i3.OnDeleteEmployeeLocation(dataItemLoc); }")
.Text(" ").IconClass("bi bi-trash3")
.HtmlAttributes(new { @class = "btn btn-outline-primary", title = "Delete" });
}).Title("Actions");
})
.NoRecords(s => s.Template("<span class='ms-3 mt-3'><i class='bi bi-people-fill me-2'></i><strong>This employee was not assigned to any location.</strong></span>"))
.AutoBind(true)
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Sortable(sorting => sorting.Enabled(true))
.Selectable(selectable => selectable.Mode(GridSelectionMode.Multiple).DragToSelect(false))
.Events(events => events
.Sort("window.i3.OnColumnSorted").Save("window.i3.OnSaveLocation")
)
.DataSource(ds => ds
.Ajax()
.Model(gridModel =>
{
gridModel.Id(entity => entity.UIDEmployee_Location);
gridModel.Field(p => p.UIDEmployee_Location).Editable(false);
gridModel.Field(p => p.UIDEmployee).Editable(false).DefaultValue(Model.UIDEmployee);
gridModel.Field(p => p.UIDLocation).Editable(true);
gridModel.Field(p => p.UIDSublocation).Editable(true);
gridModel.Field(p => p.UIDStatus).Editable(false);
gridModel.Field(p => p.UIDPosition).Editable(false);
})
.Read(r => r.Action("GetAllEmployeeLocations", "Employees", new { EmployeeID = Model.UIDEmployee }))
.Events(events => events
.RequestEnd("window.i3.OnRequestEndLocation")
)
.PageSize(10)
)
)
This data reaches me at this event where I process it:
public OnSaveLocation(e: kendo.ui.GridSaveEvent): void {
e.preventDefault();
const gridLocation = $("#EmployeeLocationsGrid").data("kendoGrid");
const locationsItems: LocationsListViewModel[] = (gridLocation?.dataSource.data() as unknown) as LocationsListViewModel[];
let newLocItem: LocationsListViewModel = (e.model as any) as LocationsListViewModel;
// Fix Date
let startLocationDateNew = new Date(newLocItem.StartDate);
let endLocationDateNew = new Date(newLocItem.EndDate);
let offsetLocationNew = startLocationDateNew.getTimezoneOffset();
startLocationDateNew = new Date(startLocationDateNew.getTime() - (offsetLocationNew * 60 * 1000));
endLocationDateNew = new Date(endLocationDateNew.getTime() - (offsetLocationNew * 60 * 1000));
let newLocationItem: LocationsListViewModel = {
UIDEmployee_Location: newLocItem.UIDEmployee_Location,
UIDEmployee: newLocItem.UIDEmployee,
UIDLocation: newLocItem.UIDLocation,
UIDSublocation: newLocItem.UIDSublocation,
UIDPosition: newLocItem.UIDPosition,
Main: newLocItem.Main,
PercentageOfDedication: newLocItem.PercentageOfDedication,
StartDate: startLocationDateNew.toISOString().split('T')[0],
EndDate: endLocationDateNew.toISOString().split('T')[0],
UIDStatus: newLocItem.UIDStatus,
Comments: newLocItem.Comments
};
}
All the data is well collected except Sublocations is set to null. Where it should be an int ID. I share with you the Template and the model:
@using XXXX.Application.Application.Maintenances.DTOs;
@model int?
@(Html.Kendo().DropDownListFor(m => m)
.DataTextField("Name")
.DataValueField("UIDEntity")
.OptionLabel("Select...")
.BindTo((IEnumerable<GenericMaintenanceEntityDTO>)ViewData["sublocations"]!)
)
@using XXXX.Application.Application.Maintenances.DTOs;
@model int
@(Html.Kendo().DropDownListFor(m => m)
.DataTextField("Name")
.DataValueField("UIDEntity")
.OptionLabel("Select...")
.BindTo((IEnumerable<GenericMaintenanceEntityDTO>)ViewData["locations"]!)
)
interface LocationsListViewModel {
UIDEmployee_Location: number;
UIDEmployee: number;
UIDLocation: number;
UIDSublocation: number;
UIDPosition: number;
Main: boolean;
PercentageOfDedication: string;
StartDate: string;
EndDate: string;
UIDStatus: number;
Comments: string;
}
I have been looking for the problem for quite some time but I can't find it. Can someone help me?
Thanks