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"))
I have a grid where I'm using the popup editor, and it's a custom template (.Editable(e => e.Mode(GridEditMode.PopUp).TemplateName("EIWOStatus")))
The popup is center screen, but I have some javascript that shows or hides certain controls based on what the user is entering. When all the controls are shown dynamically, the window is too low. I'd like to move it up, but the window itself doesn't seem to have an ID I can grab with jQuery in order to manipulate it.
How can I move the default starting position up so that as the controls get shown, it's never too low?
We are using the media player to play audio
The control looks like this
http://i.imgur.com/DfXugTI.png
However when the control looses focus it disappears and looks like this
http://i.imgur.com/vlQadUI.png
How do we prevent this behaviour and keep the player controls shown at all times.
I have a batch edit grid in which my client would like to have keyboard navigation to tab between cells. The .Navigatable() method works great. Although, for certain cells given a certain condition, I need to have them be read-only. I am able to block the cell from being selected with the mouse onClick, but with Navigatable set to true, they are still able to tab into that cell. Based on my code below, is there a way to set the cell as Read-Only? Either with a Grid method or JavaScript?
Grid Code
@
(Html
.Kendo
()
.Grid
<Project
.Models
.MetricData
>()
.Name
(
"grid"
)
// template expression, to be evaluated in the master context
.Columns
(columns =>
{
columns
.Bound
(m => m
.MetricLabel
);
columns
.Bound
(m => m
.Numerator
);
columns
.Bound
(m => m
.Denominator
);
columns
.Bound
(m => m
.Rate
);
})
.ToolBar
(toolbar =>
{
toolbar
.Save
();
})
.Editable
(editable => editable
.Mode
(GridEditMode
.InCell
))
.Navigatable
()
.DataSource
(dataSource => dataSource
.Ajax
()
.Batch
(
true
)
.ServerOperation
(
false
)
.Model
(model =>
{
model
.Id
(m => m
.MetricKey
);
model
.Field
(m => m
.MetricLabel
)
.Editable
(
false
);
})
.Read
(read => read
.Action
(
"Binding_Metrics"
,
"Controller"
))
.Update
(
"UpdateMetric"
,
"Controller"
)
)
.Events
(events => { events
.DataBound
(
"DataBound"
); })
)
JavaScript
<script>
function
DataBound() {
var
grid = $(
"#grid"
).data(
"kendoGrid"
);
var
gridData = grid.dataSource.view();
for
(
var
i = 0; i < gridData.length; i++) {
//get the item uid
var
currentUid = gridData[i].uid;
//if the record fits the custom condition find the row based on the uid and add the custom class
var
currentRow = grid.table.find(
"tr[data-uid='"
+ currentUid +
"']"
);
var
disableCell = $(currentRow).find(
':nth-child(4)'
);
$(disableCell).addClass(
"disabled"
);
//Greys out cell background
$(disableCell).click(
function
(e) {
e.preventDefault();
e.stopImmediatePropagation();
return
false
;
});
}
}
</script>
I have tried to do something like this
model
.Field
(m => m
.Rate
)
.Editable
(
@
<text>
function
(){
if
(#=numFormat# ==
1
){
return
false
;}
else
{
return
true
;}
}</text>);
But the method is unable to accept a lambda expression.
Also I have tried using JavaScript to prevent this as well
$(disableCell).focus(
function
(e) {
e.preventDefault();
e.stopImmediatePropagation();
return
false
;
});
I am not sure how to word this, so I'll describe what I would like to do and hopefully someone can lead me in the right direction.
I have a list of Top Sellers for a shop. These top sellers are categorized by department types (i.e. Fuel, Shop, etc.). When displayed in a bar chart without the grouping, the Fuel group rather skews the results on the chart as seen in the screenshot (topsellers.png). All bars are the same color and there is no legend.
What I would like to do is to is have the chart appear like the screenshot, but with the fuel group having its own color and the shop having its own color. The legend should appear at the top and clicking on the legend will hide/show the associated items in the chart. When I added the Group to the kendo bar chart, I got the colors and the legend, but the groups overlap in the chart creating two columns as shown in the second screenshot (topsellergroup.png) and the shop entries lost their descriptions. So I'd like the grouped items to show up in the chart along with their descriptive text (as in the first screenshot), but with the colors and legend of the second screenshot.
Here is my current chart code. I am setting the group to the DeptType value (i.e. Fuel, Shop) and the series based on the Quantity.
<
div
class
=
"panel panel-default"
>
<
div
class
=
"demo-section k-content wide"
>
@(Html.Kendo().Chart<
CBECloudBO2.ViewModels.ChartTopSellers
>()
.Name("chartTopSellers")
.Title("Top Sellers by Quantity")
.DataSource(datasource => datasource
.Read(read => read.Action("Chart_TopSellers", "Home"))
.Group(group => group.Add(model => model.DeptType))
.Sort(sort => sort.Add(model => model.Quantity).Descending())
)
.Legend(legend => legend.Visible(true).Position(ChartLegendPosition.Top))
.ChartArea(chartArea => chartArea
.Background("transparent"))
.Series(series =>
{
series.Bar(d => d.Quantity).Name("");
})
.CategoryAxis(axis => axis
.Categories(d => d.PLUDesc).Visible(true)
.Title("Product")
.MajorGridLines(lines => lines.Visible(false)))
.ValueAxis(axis => axis
.Numeric()
.Title("Quantity Total")
.Line(line => line.Visible(false))
.MajorGridLines(lines => lines.Visible(true)))
.Tooltip(tooltip => tooltip
.Visible(true)
.Template("#= category #: #= value #"))
)
</
div
>
</
div
>
Is it possible to group items, but not have the chart create the group columns next to each other? I tried adding the .CategoryField to the series and supplying the item description, but this only listed the fuel items and not the shop items.
Thank you for any help.
Regards,
Shawn
I'm using v 2017.1.118.440
There's a requirement to make the grid only allow a single row to be inserted. Upon loading, there should be a single blank row ready for the user to populate, and no "Add record" button.
I've disabled the Add record button from the toolbar, but I can't find the settings to have a single row already displaying in the grid and ready for populating. There doesn't seem to be an onLoad event for the grid to do this.
Any thoughts or suggestions?
Thanks in advance.
Hello,
I am having a kendo grid which is editable and the rows I am using the "DateTimeInGridEditor" template which has some settings as min and max values. This works as expected, however I want to change min max values as the values from the dates are changing, meaning that I want to have a timespan between them of x years or months. I looked through the documentation and I do not find a way of doing this. From what I have experienced will mean that I will have to change the editor and make it all the way using javascript but I do not know how I can do this. Is there a sample available?
Thanks in advance.
Hi All,
I have used below mvc helpers + odata based grid sample to create grid with crud operation with odata 4, and able to get it working.
grid - based on mvc 5 with odata 4
I have to now take it to next level, where in i will have a form with few inputs fields(they all will belong to a parent record/row in parent table),
and same form will have multiple grids with crud(each grid saves to its own table on full form save, and each of these tables are children to parent table).
For this I was looking for such sample/directions using telerik mvc helper + odata, where in we can save complete form having grid as child record and few input fields as master/parent record and save them in one go when form is saved.
Until full form is saved, we shall still be able to save/edit/delete grid rows somewhere temporarily and then shall be able to related this temp data of grid to master details(inputs fields in form) during save.
Form is like this:
Form - here table 1 is parent table, and table 2 is child to it, related by parent id of parent
Tech used:
Asp.net mvc 5 - for UI
Web api 2.2 with Odata - for grids crud (we don't want grid to be directly bound to server model rather they will use transport and will make use of api url for crud)
Data layer - EF code first (can say any ef based layer to save entities to db when full form is saved)
Could anyone of you please help and share any link to such sample to save parent fields from form with at least 1 child gird in one go.
Using mvc helpers + web api (better if we can have with odata, otherwise without odata is also ok but web api is must to bind grids to)
References already gone through:
http://www.telerik.com/support/code-library/submit-form-containing-grid-along-with-other-input-elements - doesn't fit as grid is bound to server sid emodel but we want to use web api url for grid's crud
Thank you.
I'd like to create chart that shows stacked columns and single line on the same chart area. I can adjust model data as needed, but i couldn't get chart to show this. The other acceptable option is to show two stacked columns per category side by side.
Are this scenarios achievable using Telerik UI for ASP.NET MVC?
Hi to all,
I created a new project web Telerik application MVC with Razor, I added a submenu in _Layout.cshtml
<
div
id
=
"responsive-panel"
class
=
"navbar-left"
>
@(Html.Kendo().Menu()
.Name("Menu")
.Items(items =>
{
items.Add().Text("Home").Action("Index", "Home", new { area = "" });
items.Add().Text("About").Action("About", "Home", new { area = "" });
items.Add().Text("Contact").Action("Contact", "Home", new { area = "" });
items.Add().Text("Configurazioni").Items(subitems =>
{
subitems.Add().Text("Ruoli").Action("Index", "Roles", new { area = "" });
});
})
)
</
div
>
But when a try to run, I see strange style for submenu, is it correct?