For the past few days I've been trying to get a grid working for a relatively complex model. I want to use a remote datasource for populating the initial grid, but for adding and editing I need to query other datasources for several columns, to get filtering and sorting in a dropdownlist.
I've encountered several problems, with things like binding the dropdowns and validating the editor. I'll post some of my code here, maybe someone here can provide a suggestion on what I'm doing wrong/forgetting.
Controller:
// GET: Settings
public ActionResult Index()
{
return View();
}
public async Task<
ActionResult
> GetSettings([DataSourceRequest] DataSourceRequest request)
{
DiscountSettingsViewModel viewModel = await _discountService.GetViewModel();
var result = viewModel.Discounts.ToDataSourceResult(request);
result.Total = viewModel.Discounts.Count;
return Json(result, JsonRequestBehavior.AllowGet);
}
public async Task<
ActionResult
> GetItemGroups([DataSourceRequest] DataSourceRequest request)
{
var queryParser = new DataSourceODataParser();
List<
ItemGroupViewModel
> result = await _discountService.GetItemGroups(queryParser.Parse(request));
return Json(new DataSourceResult {Data = result, Total = result.Count}, JsonRequestBehavior.AllowGet);
}
public async Task<
ActionResult
> GetItems([DataSourceRequest] DataSourceRequest request)
{
var queryParser = new DataSourceODataParser();
List<
ItemViewModel
> result = await _discountService.GetItems(queryParser.Parse(request));
return Json(new DataSourceResult {Data = result, Total = result.Count}, JsonRequestBehavior.AllowGet);
}
public async Task<
ActionResult
> GetResellers([DataSourceRequest] DataSourceRequest request)
{
var queryParser = new DataSourceODataParser();
List<
ResellerViewModel
> result = await _discountService.GetResellers(queryParser.Parse(request));
return Json(new DataSourceResult { Data = result, Total = result.Count }, JsonRequestBehavior.AllowGet);
}
public async Task<
ActionResult
> GetCustomers([DataSourceRequest] DataSourceRequest request)
{
var queryParser = new DataSourceODataParser();
List<
CustomerViewModel
> result = await _discountService.GetCustomers(queryParser.Parse(request));
return Json(new DataSourceResult { Data = result, Total = result.Count }, JsonRequestBehavior.AllowGet);
}
ViewModels:
public class DiscountSettingsViewModel
{
public int SubscriptionId { get; set; }
public List<
DiscountViewModel
> Discounts { get; set; }
}
public class DiscountViewModel
{
public int Id { get; set; }
public ItemGroupViewModel ItemGroup { get; set; }
public ItemViewModel Item { get; set; }
public ResellerViewModel Reseller { get; set; }
public CustomerViewModel Customer { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public bool IsExtra { get; set; }
public double Discount { get; set; }
public DiscountViewModel()
{
Id = 0;
ItemGroup = new ItemGroupViewModel();
Item = new ItemViewModel();
Reseller = new ResellerViewModel();
Customer = new CustomerViewModel();
IsExtra = false;
Discount = 0;
}
}
public class ItemGroupViewModel
{
public string Code { get; set; }
public string Description { get; set; }
public ItemGroupViewModel()
{
Code = "";
Description = "";
}
}
public class ItemViewModel
{
public string Code { get; set; }
public string Description { get; set; }
public ItemViewModel()
{
Code = "";
Description = "";
}
}
public class ResellerViewModel
{
public Guid? ID { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public Guid? Classification1 { get; set; }
public ResellerViewModel()
{
ID = Guid.Empty;
Code = "";
Name = "";
Classification1 = Guid.Empty;
}
}
public class CustomerViewModel
{
public Guid? ID { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public ResellerViewModel Reseller { get; set; }
public CustomerViewModel()
{
ID = Guid.Empty;
Code = "";
Name = "";
Reseller = new ResellerViewModel();
}
}
Main view:
<
h2
>Discount Settings</
h2
>
<
script
type
=
"text/javascript"
>
kendo.data.binders.widget.defferedValue = kendo.data.Binder.extend({
init: function (widget, bindings, options) {
kendo.data.Binder.fn.init.call(this, widget.element[0], bindings, options);
this.widget = widget;
this._change = $.proxy(this.change, this);
this.widget.bind("change", this._change);
},
refresh: function () {
if (!this._initChange)
{
var widget = this.widget;
var value = this.bindings.defferedValue.get();
if (value)
{
if (widget.options.autoBind === false)
{
//Bind the widget with single item if deffered binding is used
widget.dataSource.data([value]);
widget.value(value[widget.options.dataValueField]);
} else
{
//set widget value directly
this.widget.value(value[widget.options.dataValueField]);
}
}
}
},
change: function () {
this._initChange = true;
this.bindings.defferedValue.set(this.widget.dataItem() || null);
this._initChange = false;
},
destroy: function () {
this.widget.unbind("change", this._change);
}
});
</
script
>
@(Html.Kendo().Grid<
DiscountViewModel
>()
.Name("Discounts")
.Columns(col =>
{
col.Bound(i => i.ItemGroup)
.Title(Resource.ItemGroup)
.ClientTemplate("#: data.ItemGroup ? data.ItemGroup.Code : '[none]' #")
.EditorTemplateName("ItemGroupLookup")
.Filterable(false)
.Sortable(true);
col.Bound(i => i.Item)
.Title(Resource.Item)
.ClientTemplate("#: data.Item ? data.Item.Code : '[none]' #")
.EditorTemplateName("ItemLookup")
.Filterable(false)
.Sortable(true);
col.Bound(i => i.Reseller)
.Title(Resource.Reseller)
.ClientTemplate("#: data.Reseller ? data.Reseller.Name : '[none]' #")
.EditorTemplateName("ResellerLookup")
.Filterable(false)
.Sortable(true);
col.Bound(i => i.Customer)
.Title(Resource.Customer)
.ClientTemplate("#: data.Customer ? data.Customer.Name : '[none]' #")
.EditorTemplateName("CustomerLookup")
.Filterable(false)
.Sortable(true);
col.Bound(i => i.StartDate).Title(Resource.StartDate).Format("{0:dd-MM-yyyy}");
col.Bound(i => i.EndDate).Title(Resource.EndDate).Format("{0:dd-MM-yyyy}");
col.Bound(i => i.IsExtra).Title(Resource.IsExtra);
col.Bound(i => i.Discount).Title(Resource.Discount);
col.Command(command =>
{
command.Edit().Text(Resource.Edit);
command.Destroy().Text(Resource.Delete);
}).Width(250);
})
.Sortable(s => s.SortMode(GridSortMode.MultipleColumn))
.ToolBar(toolbar => toolbar.Create().Text(Resource.Add))
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Pageable()
.DataSource(source => source
.Ajax()
.PageSize(20)
.Events(events => events.Error("error_handler"))
.Model(m =>
{
m.Id(i => i.Id);
m.Field(p => p.ItemGroup);
m.Field(p => p.Item);
m.Field(p => p.Reseller);
m.Field(p => p.Customer);
m.Field(p => p.StartDate);
m.Field(p => p.EndDate);
m.Field(p => p.IsExtra);
m.Field(p => p.Discount);
})
.Create(update => update.Action("CreateSetting", "Settings"))
.Read(read => read.Action("GetSettings", "Settings"))
.Update(update => update.Action("UpdateSetting", "Settings"))
.Destroy(update => update.Action("DestroySetting", "Settings"))
)
.NoRecords(Resource.NoSettings)
)
Example EditorTemplate:
@model NuCall.ViewModels.ItemGroupViewModel
@(Html.Kendo().DropDownListFor(m => m)
.HtmlAttributes(new { data_skip = "true", data_bind = "deferredValue: ItemGroup" })
.OptionLabel("--none--")
.DataSource(source =>
{
source.Custom()
.ServerFiltering(true)
.ServerPaging(true)
.PageSize(20)
.Type("aspnetmvc-ajax")
.Transport(transport => transport.Read("GetItemGroups", "Settings"))
.Schema(schema => schema
.Data("Data")
.Total("Total")
.Errors("Errors"));
})
.MinLength(1)
.AutoBind(false)
.Filter(FilterType.StartsWith)
.DataValueField("Code")
.DataTextField("Code"))