Telerik Grid ServerTemplate problem - grid

I'm trying to set up a Master/Detail grid using the Grid control from Telerik's Extensions for ASP.NET MVC. My problem is setting up the server template.
The demo I'm following is the first one on this page, except I'm using Razor View Engine.
I have the grid displaying fine. The problem is that I cannot write any sort of a server template that doesn't throw a compiler error - aside from leaving it blank!
#(Html.Telerik().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
columns.Bound(o => o.Date).Format("{0:MM/dd/yyyy}").Width(100);
columns.Bound(o => o.Title).Template(#<text> #item.Title</text>).Sortable(false);
columns.Bound(o => o.Publication).Width(120).Sortable(false);
})
.DetailView(detailView => detailView.Template(e =>
{
//Anything other than this comment will throw a compiler error
}))
.RowAction(row =>
{
// Expand initially the detail view of the first row
if (row.Index == 0)
{
row.DetailRow.Expanded = true;
}
})
.Sortable()
.Scrollable(scrolling => scrolling.Height(494)).Footer(false)
.ClientEvents(events => events.OnRowDataBound("onRowDataBound"))
)
See that comment "anything other than this comment..."? When I replace that with something like #<text> hello</text>, I get a compilation error:
CS1002: ; expected
That doesn't seem to make sense, but I humour myself and put a semicolon in like such #<text> hello</text>;. That gives me this error:
CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement
When I replace that with a portion of the template I really want, namely #<text><b>Slug</b>: #item.Slug</text>, I get the same errors; CS1002 with no semicolon, and CS0201 with a semicolon.
What am I missing here?

There are two ways you can approach this. If you just want to display some simple text and not really integrate any other components it would be the easiest to modify the code you have above to just do this:
.DetailView(detailView => detailView.Template(#<text>test</text>))
As you can see I removed the whole e => { ... } part and just put in #<text></text>.
However, if you want to look into getting more components in your detail view I think it would be better to look at the demo found here. Although the description mentions some WebForms code you don't need to worry, the rest is all in Razor :) It also explains things you have to keep in mind. One of the most important ones is that any components within the DetailTemplate will have to use { ... } as opposed to ( ... ) this is because you want to specifically call .Render(); (using the ( ... ) implicitly calls .Render but at the wrong point for these scenarios) at the end of those components' declaration to make sure they are all rendered correctly.

Related

ClientGroupHeaderTemplate in Excel Export (Kendo ASP.NET MVC)

I have a grid that shows a list of financial arrears grouped by the type of debt, known as Cash Type. These Cash Types can be categorised in a number of ways, or not, which is "Normal". When they are categorised I'm adding a lovely badge in the ClientGroupHeaderTemplate so it stands out to the user. All good so far.
#(Html.Kendo().Grid(Model.Arrears)
.Name("arrearsGrid-" + Model.LeaseId.ToString())
.HtmlAttributes(new { #class = "smallergrid" })
.Columns(columns =>
{
columns.Bound(p => p.InvoiceNumber)
.ClientTemplate("<a class=\"text-primary\" href=\"" + Url.Action("Invoice", "Arrear") + $"/#=InvoiceNumber#?buildingid=#=BuildingId#&leaseid={Model.LeaseId}\" target=\"_blank\">#=InvoiceNumber#</a>");
columns.Bound(p => p.InvoiceDescription);
columns.Bound(p => p.CashType)
.ClientGroupHeaderTemplate("Cash Type: #= getCashTypeName(data.value) # (#= getDebtCategoryName(data.items[0].DebtCategory) #)");
columns.Bound(p => p.InvoiceDate);
columns.Bound(p => p.TransactionDate);
columns.Bound(p => p.DaysOverdue);
columns.Bound(p => p.InvoiceGross)
.HtmlAttributes(new { #class = "text-right" });
columns.Bound(p => p.OutstandingGross)
.HtmlAttributes(new { #class = "text-right" });
})
.Sortable()
.Excel(excel => excel
.FileName("Kendo UI Grid Export.xlsx")
.Filterable(true)
.AllPages(true)
)
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
.Group(g => g.Add(p => p.CashType))
)
.NoRecords(x => x.Template("<div class='empty-grid'></div>"))
)
The problem is the Export to Excel function does no processing on the ClientGroupHeaderTemplate, and shows<span>Cash Type: Rent <span class="d-print-none badge debt-category-1 ml-2">In Query</span></span> in the spreadsheet.
Here's the options I see are available, and some I've discounted. Are these really the best options I have?
CSS (rejected)
As you can see, using the Bootstrap d-print-none does nothing. From all the posts on Export and hidding columns, it seems that Kendo is in no way using a print view of the page, so #media options aren't going to help.
excelExport event
Use the Kendo excelExport event to customise the generated Excel workbook, however, this example is document creation. If I'm going this route I suspect it might be easier to write one from scratch, rather than workaround Kendo limitations. Either way it's a lot of work to remove 1 line of HTML markup.
Use the ProxyURL
Under a Grids Excel object, you can set an endpoint to call when the Excel spreadsheet is created. This might give the chance to tweak a ready-to-save spreadsheet before it is saved. There's a demo of it here. The demo is wrong (the Controller name is not Grid, it's Excel_Export) and it doesn't work for me even when corrected and the standard .ToolBar(tools => tools.Excel()) back in. Maybe it's because I'm not AJAXing my data in, or maybe it's just as broken as the demo. Changing my grid to AJAX will is not beyond the realms of possibility, but it's not a small job either.
Edit: I got this to hit the event by also adding .ForceProxy(true) to the Excel definition. This isn't mentioned in the demo, and the statement that you need to add .ToolBar(tools => tools.Excel()) is also incorrect; you can fire the event from your own buttons that trigger the Excel export.
Give up and go simple
The last option I have is to give up on the badges and just have text. It's the quickest and surest option, but it's solving the problem by ignoring the problem.
So I managed this in yet another way. I'm sure there must be an MVC answer to this problem though.
I added an event to my Grid
#(Html.Kendo().Grid(Model)
...
.Events(e =>
{
e.ExcelExport("exportExcel");
}
...
)
and created a JavaScript middleware function to alter the Excel file before it is saved. Of course you can then do whatever JS allows you to do at this point.
In the code below are examples of setting a column width (4), removing HTML span markup, and converting a string to a number and adding a currency format to that number (7). The method of obtaining the currency symbol is not pretty, but it's a string inside some HTML markup, I don't think it can be pretty.
function exportExcel(e) {
var sheet = e.workbook.sheets[0];
var lastRow = sheet.rows[sheet.rows.length - 1];
var lastCell = lastRow.cells[lastRow.cells.length - 1];
var lastCellValue = lastCell.value.toString().replace(/<[^>]*>/, "").replace("</span>", "");
var currency = lastCellValue.substring(0, 1);
currency += "#,###,##0.00";
sheet.columns[4].autoWidth = false;
sheet.columns[4].width = 125;
$.each(sheet.rows, function (index, row) {
if (index > 0) {
if (row.cells[0] != undefined) {
if (row.cells[0].value != undefined) {
row.cells[0].value = row.cells[0].value.replace(/<[^>]*>/, "(").replace("</span>", ")");
}
}
if (row.cells[7] != undefined) {
if (row.cells[7].value != undefined) {
row.cells[7].value = row.cells[7].value.toString().replace(/<[^>]*>/, "").replace("</span>", "");
row.cells[7].value = Number(row.cells[7].value.toString().replace(/[^0-9\.-]+/g, ""));
row.cells[7].format = currency; // Why this prepends a backslash to the format I do not know
}
}
}
});
};

Regarding #Html.DropDownListFor(...)

Can someone please help me figure this out. I have a Drop Down List in ASP.NET Razor code
#Html.DropDownListFor(model => model.Height, heightlist, new { style = "font-size:120%;" })
My Drop Down List is too big when you click on the list. I would like it to be like the one on the right hand side:
I tried various methods, including the code below, but the issue exists:
#Html.DropDownListFor(model => model.Height, heightlist, new { height="50", style = "font-size:120%; height:30px;" })

ASP.NET MVC: Routing errors on test server

I'm developing a ASP.NET MVC3 website for the 1st time. On my development machine everything works fine.
I bin deployed everything on our test machine. After some missing DLL issues the website seemed to work on the following url:
http://localhost/Test%20Website
But when I clicked the following link (which is created by an inline javascript because I'm using Infragistics Grid which is irrelevant for the question):
<img src=\"../Resources/Edit.png\" align=\"left \">
I get HTTP Error 404.0 - Not Found, which is logical, because the Physical Path is: C:\inetpub\wwwroot\Patient\Edit\537
While the physical Path should be: C:\inetpub\wwwroot\Test Website\Views\Patient\Edit\537 (atleast... I think... don't understand how MVC routing works exactly)
The links which are made by using the ActionLink HTML helper and such work fine by the way.
So this works:
#Html.ActionLink("About", "About", "Home")
And this works:
#Html.Partial("Search", new SearchModel())
So, my question is, how do you solve these issues?
p.s.: All the images in resources don't work either. sigh
UPDATE after an answer
I'm sorry, apparantly it is important to note that this takes place in a javascript function as a string. That's because I'm using the FormatterFunction from Infragistic's JQuery grid. Ok, this is what I've got so far:
"function(val) {return '<img src=\"../Resources/Edit.png\" align=\"left\">'; }"
The name 'val' does not exist in the current context, which is logical. But I don't know how to solve it, 'cause of my limitted knowledge of javascript/Razor/etc... Could you please help? Val in this case is by the way the value of the column it's bound to. In this case the ID of patient.
Ego4eg asked more code
It's Infragistics JQuery grid. This grid has a FormatterFunction which has a string as parameter. This string needs to be a javascript function. To give you an idea, this looks like:
#(Html.Infragistics()
.Grid(Model)
.ID("grid1")
.AutoGenerateColumns(false)
.Columns(column => {
//column.For(p => p.ID).FormatterFunction("function(val) {return '<img src=\"../Resources/Edit.png\" align=\"left\">'; }").Width("25px").HeaderText(" ");
column.For(p => p.ID).FormatterFunction("function(val) {return '<img src=\"../Resources/Edit.png\" align=\"left\">'; }").Width("25px").HeaderText(" ");
column.For(p => p.ID).FormatterFunction("function(val) {return '<img src=\"../Resources/add.png\" align=\"left\">'; }").Width("25px").HeaderText(" ");
column.For(p => p.FullName).DataType("string").HeaderText("Naam").Width("250px");
column.For(p => p.Address).DataType("string").HeaderText("Adres").Width("400px");
column.For(p => p.BSN).DataType("string").HeaderText("BSN").Width("85px");
column.For(p => p.DateOfBirthAsString).DataType("string").HeaderText("Geboortedatum").Width("85px");
column.For(p => p.GeneralPractitionerName).DataType("string").HeaderText("Huisarts");
})
Hope this helps.
It would be better to use Url.Content like:
<a href=\"#Url.Content("~/Patient/Edit/" + val)\">
Try this:
<a href ="Url.Action("Edit", "Patient", new { id = val })" />

Telerik-grid paging and sorting when using an external data source

I am experimenting with using an external data source with a Telerik Grid using their Twitter search sample as my guide
http://demos.telerik.com/aspnet-mvc/razor/grid/externalservicetwitter
I have got their sample running but cannot get paging and sorting to work.
In the sample they set-up the grid server side using the code
#(Html.Telerik().Grid<TwitterItem>()
.Name("Grid")
.Columns(columns =>
{
columns.Template(o => { }).Title("Author").Width(100);
columns.Template(o => { }).Title("Avatar").Width(80);
columns.Bound(o => o.text).Title("Post");
})
.ClientEvents(events => events
.OnDataBinding("onDataBinding")
.OnRowDataBound("onRowDataBound")
)
.Scrollable(scrolling=>scrolling.Height(400)))
So I added .Pageable and .Sortable to the construct like in the other samples but this seems to make no difference
#(Html.Telerik().Grid<TwitterItem>()
.Name("Grid")
.Columns(columns =>
{
columns.Template(o => { }).Title("Author").Width(100);
columns.Template(o => { }).Title("Avatar").Width(80);
columns.Bound(o => o.text).Title("Post");
})
.ClientEvents(events => events
.OnDataBinding("onDataBinding")
.OnRowDataBound("onRowDataBound")
)
.Scrollable(scrolling=>scrolling.Height(400))
.Pageable()
.Sortable()
)
Should this be working? Is there something else I should be doing?
I am having the same problem.
My challenge is that the users want to retreive repeatedly for different criteria and they expect the results to accumulate in the grid until they clear the grid. I am building this capability. I got the accumulation to work, but along the way something is causing the "Displaying items 0 - 0 of 0".
This question has been sitting out here for a long time. It makes me feel discouraged.
My theory is that the custom binding messes up the other settings.
Joe

Problem programmatically setting columns to read-only on a Telerik RadGrid

I'm trying to dynamically make certain columns readonly at runtime using the following code in my Page_Load handler:
GridNumericColumn gncp = grid.MasterTableView.GetColumn("ActualProduction") as GridNumericColumn;
if (gncp != null)
{
gncp.ReadOnly = true;
}
However, the above code only works if the column is the last column in the grid. If I try with the second to last, or columns further left, the Edit command on the row no longer works. No exception is thrown, and the EditCommand fires, but that's where the party stops.
I suspect I may be modifying the grid in the wrong place in the page life cycle, but I really don't want to start looking for the right place by trial and error. I bind my grid using grid_NeedDataSource, not in page load. Any ideas?
Try setting the readonly status inside the PreRender handler of the grid. I think this is more appropriate place to do that. More about columns customization here.
Dick
this is what I'm using for ASP.NET MVC 3 Telerik Grid. I haven't had problems changing the order of the columns. Obviously I'm using the Razor view engine. I hope this helps.
#(Html.Telerik().Grid(Model)
.Name("catGrid")
.DataKeys(k => k.Add(o => o.cat_id))
.Columns(columns =>
{
columns.Bound(m => m.cat_id).ReadOnly(true).Visible(false);
columns.Bound(m => m.tenant_id).ReadOnly(true).Visible(false);
columns.Bound(m => m.date_added).ReadOnly(true).Visible(false);
columns.Bound(m => m.category_name).Title("Category Name").Width(350);
columns.Bound(m => m.status_cd).Title("Status").Width(150);
columns.Command(c =>
{
c.Edit();
c.Delete();
}).Width(250);
})
.DataBinding(b => b.Ajax()
.Select("AjaxGridSelect", "Category")
.Insert("GridInsert", "Category")
.Update("GridUpdate", "Category")
.Delete("GridDelete", "Category")
)
.ToolBar(t =>
{
t.Insert();
})
.Pageable(paging => paging.PageSize(20)
.Style(GridPagerStyles.NextPreviousAndDropDown)
.Position(GridPagerPosition.Both)
)
.Sortable()
.Filterable()
)

Resources