I'm trying to display a Kendo dataviz piechart with the following information.
I'm passing 'results' back from my controller to my view.
My view contains the piechart:
#(Html.Kendo().Chart<PropertyViewModel>()
.Name("chart")
.Title("Properties")
.Legend(legend => legend
.Position(ChartLegendPosition.Top)
)
.DataSource(ds => ds.Read(read => read.Action("GetPropertiesChart", "Home")))
.Series(series => {
series.Pie(model => model.Address.State, model => model.Address.State.Count().ToString());
})
.Tooltip(tooltip => tooltip
.Visible(true)
.Format("{0:N0}")
)
)
I get nothing but a blank area on my page where the piechart should be.
Controller code:
public ActionResult GetPropChart()
{
var allProps = PService.GetAll();
var props = allProps.Cast<PropViewModel>().ToList();
var results = props
.GroupBy(item => item.Address.State)
.Select(g => new
{
State = g.Key,
Count = g.Select(l => l.Address.State).Count()
});
return Json(results);
}
The model you return is as follows:
.Select(g => new
{
State = g.Key,
Count = g.Select(l => l.Address.State).Count()
}
However your series definition are different (there is no Adress property)
series.Pie(model => model.Address.State)
Also binding to methods (such as model.Address.State.Count().ToString()) is Not supported - created regular property which holds the value instead.
Related
Inside the editor template of one of my Grids, A, I have another grid, B. I want to set read and update actions of this Grid based on the current Id in the A.
I've tried using Razor code inside the editor template like this:
// details grid: B
.Read("action", "controller", new { #Model.Id })
But Id was always null, probably because Razor is server-side.
So I've tried to set the Grid inside the main page, in the Edit event of the main Grid.
function EditHandler(e) {
if (e.model.isNew())
return;
var detailGrid = e.container.find("#details").data('kendoGrid');
detailGrid.dataSource.options.transport.read.url = "#Url.Action("", "")".concat('/', e.model.Id);
detailGrid.dataSource.options.transport.update.url = "#Url.Action("", "")".concat("/", e.model.Name);
}
This doesn't work neither. The definition of the Grid in the editor template will overwrite these properties.
This is the main Grid:
#(Html.Kendo().Grid<A>()
.Name("A")
.Columns(columns =>
{
columns.Bound(x => x.Id).Hidden();
columns.Bound(x => x.Name).HtmlAttributes(new { #style = "text-align: left" });
....
columns.Command(command =>
{
command.Edit(); command.Destroy();
});
})
.....
.Selectable()
.Navigatable()
.DataSource(ds => ds
.Ajax()
.Model(model =>
{
model.Id(x => x.Name);
})
.Read("", "")
.Update("", "")
.Destroy("", "")
.Create("", "")
)
.Events(e => e.Edit("EditHandler").Save("SaveHandler"))
)
Inside the editor template of this class, a.cshtml, I have another Grid that I want its Edit and Read Actions include the Id of the Grid A.
#(Html.Kendo().Grid<B>()
.Name("B")
.Columns(columns =>
{
columns.Bound(.....
})
.....
.Editable(edit => edit.Mode(GridEditMode.InCell))
.Selectable()
.Navigatable()
.DataSource(ds => ds
.Ajax()
.PageSize(5)
.Model(model =>
{
model.Id(x => x.Id);
})
.Read("", "")
.Update("", "")
).ToClientTemplate()
)
UPDATE
function EditHandler(e) {
if (e.model.isNew())
return;
var detailGrid = e.container.find("#details").data('kendoGrid');
detailGrid.dataSource.read({ Id: e.model.Id });
detailGrid.dataSource.update({ Name: e.model.Name });
}
As Dion noted, it needs 2 changes:
In the child Grid, B, set the auto bind to false: .AutoBind(false)
Set the ID with read method, not manually as I've been trying.
To overcome this case, I will trigger Grid-B's read manually inside Grid-A's edit event. Follow this setup:
Grid-B Config:
.AutoBind(false)
.DataSource(ds => ds.Ajax()
.Read("action", "controller")
.Update(url => url.Action("update", "controller").Data(paramData)))
Modify Grid-A edit function:
function EditHandler(e) {
var gridB = $("#gridB").getKendoGrid(),
model = e.model;
gridB.dataSource.read({Id: model.Id});
}
// get Id for update
function paramData() {
return { Id : $("#Id").val(); };
}
Hope this help.
Note: Unlike read, update will be triggered after popup shown then Id field will be already have its value. Therefor you can use Url.Action(...).Data() for this case.
In the Kendo Grid there is a foreign key column, and I retrieve the select list from ViewData. Grid's edit mode is InLine.
When I want to add a new record, the first item is selected. If I don't change it and don't select anything else, column's value will be null on the server side.
How can I specify a default value for this column? Please note that ID's are user-generated and I'm not able to guess which Id will the first Item.
This is the Grid:
#(Html.Kendo().Grid<InvtMat>()
.Name("BOM")
.Columns(columns =>
{
columns.ForeignKey(x => x.CGoodCode, (IEnumerable)ViewData["Goods"], "Id", "Text");
// removed for brevity
columns.Command(command => { command.Edit(); command.Destroy(); });
})
.ToolBar(toolbar =>
{
toolbar.Create();
})
.Editable(edit => edit.Mode(GridEditMode.InLine))
.DataSource(ds =>
ds.Ajax()
.Model(model =>
{
model.Id(x => x.CGoodCode);
model.Id(x => x.CGoodCode1);
})
)
)
You can set default value for Grid's model inside DataSource.Model section.
Here is an example:
.DataSource(ds =>
ds.Ajax()
.Model(model =>
{
model.Id(x => x.CGoodCode);
model.Field(x => x.CGoodCode).DefaultValue(0);
})
)
Because you don't know what default value you must write there, then you should find it first before you define the Grid. I suppose you have something like this in your controller:
var goods = // get goods from DB.
var goodsDV= goods.First().Id;
ViewData["Goods"] = goods;
ViewData["GoodsDefaultValue"] = goodsDV;
Or you could also perform this in razor view
#{
var firstGood = ((IEnumerable<Good>)ViewData["Goods"]).First();
ViewData["GoodsDefaultValue"] = firstGood.Id;
}
Then use it like this
model.Field(x => x.CGoodCode).DefaultValue(ViewData["GoodsDefaultValue"]);
Easy right?!
By default it looks like Telerik Grid for MVC3 submits only the rows marked as "dirty" to my controller. I need to be able to submit all rows on a Telerik Grid to my controller. In other words I think I need to mark all rows as changed so the grid will send all rows to my controller.
I am using Ajax data binding as in:
.DataBinding(dataBinding => dataBinding
.Ajax()
.Select("GetData", "ModuleAccess", new { roleId = #ViewBag.RoleId, appId = #ViewBag.AppId })
.Update("SaveBatchEditing", "ModuleAccess")
#(Html.Telerik().Grid<BarcodeListModel>()
.Name("orders-grid")
.ClientEvents(events => events.OnDataBinding("onDataBinding"))
.DataKeys(keys =>
{
keys.Add(x => x.Id);
})
.ToolBar(commands =>
{
commands.SubmitChanges();
})
.DataBinding(dataBinding =>
dataBinding.Ajax()
.Select("BulkEditSelect", "ProductVariant")
.Update("BulkEditSaveBarcode", "ProductVariant")
.Delete("DeleteBarcode", "ProductVariant")
)
.Columns(columns =>
{
columns.Bound(x => x.Id).ReadOnly();
columns.Bound(x => x.SKU);
columns.Bound(x => x.barcode);
//columns.Bound(x => x.Id)
// .Template(x => Html.ActionLink(T("Admin.Common.View").Text, "DeleteBarcode", new { id = x.Id }))
// .ClientTemplate("" + "Delete" + "")
// .Width(50)
// .Centered()
// .HeaderTemplate("DeleteBarcode")
// .Filterable(false)
// .Title("Delete");
columns.Command(commands => commands.Delete()).Width(180);
})
.Pageable(settings => settings.PageSize(gridPageSize).Position(GridPagerPosition.Both))
.DataBinding(dataBinding => dataBinding.Ajax().Select("BarcodeList", "ProductVariant", Model))
.Editable(editing => editing.Mode(GridEditMode.InCell))
.EnableCustomBinding(true)
)
use like this code
I found the answer:
function ModuleAccessGridHasChanges() {
var grid = $("#ModuleAccessGrid").data("tGrid");
if (grid != null) {
var additionalValues = grid.data;
if (!$.telerik.trigger(grid.element, 'submitChanges', { values: additionalValues })) {
grid.sendValues($.extend({}, additionalValues), 'updateUrl', 'submitChanges');
}
}
}
Fiddler shows all the data for the grid coming accross:
I have an mvc editor template (named ExpenseTypeEdit) defined like this:
#model ExpenseType
#(Html.Kendo().DropDownListFor(et => et.ExpenseTypeId)
.OptionLabel("--Please Select--")
.DataTextField("Description")
.DataValueField("ExpenseTypeId")
.DataSource(datasource => datasource
.Read("GetExpenseTypeList", "Lookup", new { area = "" })
)
.HtmlAttributes(new { width = "98%" })
)
I have a kendo grid that looks something like this:
#(Html.Kendo().Grid<ExpenseViewModel>()
.Name("ExpenseGrid")
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Columns(columns =>
{
columns.Bound(e => e.ExpenseType)
.EditorTemplateName("ExpenseTypeEdit");
columns.Command(command =>
{
command.Custom("SaveExpense").Click("SaveExpense_click").Text("Save");
}
);
})
.DataSource(datasource => datasource.Ajax()
.ServerOperation(false)
.Model(model =>
{
model.Id(i => i.ExpenseId);
model.Field(f => f.ExpenseType)
.DefaultValue(new Solutions.Business.Entities.PrimitiveObjects.ExpenseType { ExpenseTypeId = 0, Description = "" });
})
)
)
The function SaveExpense_click looks like this:
function SaveExpense_click(e) {
var item = this.dataItem($(e.currentTarget).closest("tr"));
/*
Variable 'item' looks like like:
{
ExpenseType: {
ExpenseTypeId: 4,
Description: ""
}
}
*/
//debugger;
};
The ExpenseTypeId is present but not the description. Why is item not picking up the Description from the drop down and what do I need to do to get it passed in?
You can't get the Description of a DDL server side, you can only get the value. You can either get the value then retrieve the text from the DB or you can use the combo box control and then you will be able to get both value and text.
Just noticed your tryign to get it client side, if thats the case.
$("#ExpenseTypeId").text() should work, as per your example item.text() might work
I am using Ajax binding and so I am assuming that if I want the total to update after the user edits a change, I need the ClientFooterTemplate as opposed to just the FooterTemplate which works.
Here is my grid which works with FooterTemplate:
#{
GridEditMode mode = (GridEditMode)ViewData["mode"];
GridButtonType type = (GridButtonType)ViewData["type"];
GridInsertRowPosition insertRowPosition = (GridInsertRowPosition)ViewData["insertRowPosition"];
Html.Telerik().Grid<RedFile.Models.QuickQuoteItemView>("items")
.Name("QuoteItems")
.DataKeys(k => k.Add(o => o.Id))
.ToolBar(commands => commands.Insert().ButtonType(type).ImageHtmlAttributes(new { style = "margin-left:0" }))
.Columns(c =>
{
c.Bound(o => o.Id).ReadOnly().Hidden();
c.Bound(o => o.ItemID);
c.Bound(o => o.Description);
c.Bound(o => o.ItemQty);
c.Bound(o => o.ItemPrice).Format("{0:c}");
c.Bound(o => o.LineTotal)
.Width(100)
.Aggregate(ag => ag.Sum())
.FooterTemplate(result => (result.Sum == null ? "0.00" : result.Sum.Format("{0:c}")))
.Format("{0:c}");
c.Command(s =>
{
s.Edit();
s.Delete();
});
})
.Editable(editing => editing.Mode(mode).InsertRowPosition(insertRowPosition))
.DataBinding(b => b.Ajax()
.Select("GridSelect", "QuickQuote")
.Insert("GridInsert", "QuickQuote", new { qqid = Model.Id })
.Update("GridUpdate", "QuickQuote", new { qqid = Model.Id })
.Delete("GridDelete", "QuickQuote", new { qqid = Model.Id })
)
.Footer(true)
.Render();
}
If I change the footer template to something like this: (I have tried multiple variations with the same result)
.ClientFooterTemplate("<#= $.telerik.formatString('{0:c}', Sum) #>")
The total simply disappears.
All I want is a total that updates after the user changes something. Any idea what I'm doing wrong?
Thanks
columns.Bound(p => p.ItemPrice)
.FooterTemplate(
#<text>
Total:#string.Format("{0:c}", Model.ItemPrice)
</text>
)
.Width(100)
.Format("{0:c}");
Refer to Teleriks MVC grid Documentation