How do you show carriage returns inside a MVCContrib Grid? I've tried replacing the returns with "<br>", however that is actually showing a <br> in my display "test<br>test"
<div id="noteList">
#Html.Grid(Model).Columns(column => {
column.For(x => x.TimeStamp);
column.For(x => x.UserName);
column.For(x => x.Note.Replace("\r\n","\"<br>\"")).Named("Note");
}).Attributes(Style => "text-aligh: center", #Class => "linkGrid")
</div>
Is there a way to get the browser to render the original return's "\r\n"?
You could use a custom column:
column.Custom(item => #item.Note.Replace("\r\n", "<br/>")).Named("Note");
But a safer and IMHO a more robust solution would be to use a custom HTML helper:
public static class HtmlExtensions
{
public static IHtmlString FormatNote(this HtmlHelper html, string note)
{
if (string.IsNullOrEmpty(note))
{
return MvcHtmlString.Empty;
}
var lines = note.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
return MvcHtmlString.Create(string.Join("<br/>", lines.Select(x => html.Encode(x))));
}
}
and then:
column.Custom(item => Html.FormatNote(item.Note)).Named("Note");
Related
I think I'm close. Its not throwing any errors but its also not displaying any data... Im just trying to get it to display a list of Company Names and Company IDs from my TblCompanyInfo table.
This is my controller:
public async Task<IActionResult> Index()
{
var apptReminderContext = _context.TblCompanyInfos.Include(t => t.AcctType).Include(t => t.CompanyStatus).Include(t => t.OnHoldReason);
return View(await apptReminderContext.ToListAsync());
//return View();
}
public JsonResult Products_Read([DataSourceRequest] DataSourceRequest request)
{
DataSourceResult result = _context.TblCompanyInfos.ToDataSourceResult(request,
model => new TblCompanyInfo
{
CompanyId = model.CompanyId,
CompanyName = model.CompanyName
});
return Json(result);
}
and my view...
#model IEnumerable<AppointmentRemindersNetCoreMVC.Models.TblCompanyInfo>
#{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
#using AppointmentRemindersNetCoreMVC.Data
#using Kendo.Mvc.UI
#addTagHelper *, Kendo.Mvc
#inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
#Html.AntiForgeryToken()
#(Html.Kendo().Grid<AppointmentRemindersNetCoreMVC.Models.TblCompanyInfo>()
.Name("grid")
.DataSource(dataSource => dataSource.Ajax()
.Read(read => read.Action("Products_Read", "Company"))
.PageSize(20)
//.ServerOperation(false)
//.Model(model => model.Id(c => c.CompanyId))
//.Read("Products_Read", "Company")
//.Read(read => read.Action("Products_Read", "Company"))
.Update("UpdateCustomer", "Home")
.Create("InsertCustomer", "Home")
.Destroy("DeleteCustomer", "Home"))
.Columns(columns =>
{
columns.Bound(product => product.CompanyName);
columns.Bound(product => product.CompanyId);
})
.Pageable()
.Sortable()
)
Also I know that the Products_Read function is being called by the view and I also know that the "result" contains 32 rows of data. However, nothing is displayed in the grid.
Figured it out! Turns out that json camelcases the return string so the model properties did not match what was returned by json. The solution was to add this line to the Startup.cs file.
services.AddControllers()
.AddJsonOptions(options =>
options.JsonSerializerOptions.PropertyNamingPolicy = null);
I'm having trouble with an AJAX POST. I'm defining where I want the AJAX call to be posted, but it's posting elsewhere. Please help.
I'm using an MVC Telerik Grid. It probalby doesn't matter if you aren't familiar with it. I'm following the example at http://demos.telerik.com/aspnet-mvc/razor/grid/editingbatch
From that example, Important pieces to this Grid puzzle include:
.Editable(editing => editing.Mode(GridEditMode.InCell))
Also from that example, defining the url for the AJAX call:
.DataBinding(dataBinding => dataBinding.Ajax()
.Select("_SelectContactsBatchEditing", "Ajax", new {FirstName = #ViewData["FirstName"], LastName = #ViewData["LastName"]})
.Update("_SaveContactsBatchEditing", "Ajax", new {FirstName = #ViewData["FirstName"], LastName = #ViewData["LastName"]})
)
For both Select() and Update() methods, the first parameter is the Action and the second parameter is the Controller. I have a third optional parameter which contains the other data to send back in the post.
My grid is Master/Detail. I've taken out the Detail portion and I'm still having the issue. I've giving you my entire grid. For now please let's focus on the Master portion.
#(Html.Telerik().Grid<ContactView>()
.Name("ContactsGrid")
.Columns(columns =>
{
columns.Bound<int>(c => c.Id).Width(65).ReadOnly();
columns.Bound<string>(c => c.FirstName).Width(100);
columns.Bound<string>(c => c.LastName).Width(100);
columns.Bound<string>(c => c.Phone).Width(120);
columns.Bound<string>(c => c.Street).Width(200);
columns.Bound<string>(c => c.City).Width(100);
columns.Bound<string>(c => c.Province).Width(50).Title("Prov");
columns.Bound<string>(c => c.PostalCode).Width(80).Title("PC");
columns.Bound<string>(c => c.Email).Width(100);
columns.Bound<bool>(c => c.OkToContact).Width(40).Title("Ok")
.ClientTemplate("<input type='checkbox' disabled='disabled' name='OkToContact' <#=OkToContact? checked='checked' : '' #> />");
columns.Command(commands =>
{
commands.Delete();
}).Width(100);
})
.DetailView(details => details.ClientTemplate(
Html.Telerik().Grid<DonationView>()
.Name("Donations_<#= Id #>")
.Resizable(resizing => resizing.Columns(true))
.Editable(editing => editing.Mode(GridEditMode.InCell).DefaultDataItem(new DonationView(){Description = "Internal Cause"}))
.DataKeys(d => d.Add<int>(a => a.Id).RouteKey("Id"))
.Columns(columns =>
{
columns.Bound(o => o.Id).Width(65).ReadOnly();
columns.Bound(o => o.Description).Width(400);
columns.Bound(o => o.Amount).Width(80);
columns.Bound(o => o.Date).Format("{0:d}");
})
/*.ClientEvents(events => events.OnRowDataBound("cause_onRowDataBound"))*/
.DataBinding(dataBinding => dataBinding.Ajax()
.Select("_SelectDonationsHierarchyBatchEditing", "Ajax", new { ContactID = "<#= Id #>" })
.Update("_SaveDonationsHierarchyBatchEditing", "Ajax", new {ContactID = "<#= Id #>"})
)
.Sortable()
.ToolBar(commands => {
commands.Insert();
commands.SubmitChanges();
})
/*.Filterable()*/
.ToHtmlString()
))
.DataBinding(dataBinding => dataBinding.Ajax()
.Select("_SelectContactsBatchEditing", "Ajax", new {FirstName = #ViewData["FirstName"], LastName = #ViewData["LastName"]})
.Update("_SaveContactsBatchEditing", "Ajax", new {FirstName = #ViewData["FirstName"], LastName = #ViewData["LastName"]})
)
.Resizable(resizing => resizing.Columns(true))
//.Pageable(paging => paging.PageSize(25))
.Editable(editing => editing.Mode(GridEditMode.InCell))
.DataKeys(d => d.Add<int>(a => a.Id).RouteKey("Id"))
.Scrollable(scrolling => scrolling.Height(500))
.ToolBar(commands => {
commands.Insert();
commands.SubmitChanges();
})
//.HtmlAttributes(new { style = "width: 1200px" } )
.Sortable()
)
My Select() method calls correctly, however my Update() method does not. It simply posts to the same page the grid resides on. I had this working but didn't bother to check in (stupid), and broke it a few days later. No amount of Ctrl+Z has helped me.
Here is the action in my Ajax Controller. Details removed since they don't matter. The method just isn't getting called.
[GridAction]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult _SaveContactsBatchEditing([Bind(Prefix = "inserted")]IEnumerable<ContactView> insertedContacts,
[Bind(Prefix = "updated")]IEnumerable<ContactView> updatedContacts,
[Bind(Prefix = "deleted")]IEnumerable<ContactView> deletedContacts, string FirstName, string LastName)
{
ISession session = SessionManager.OpenSession();
ContactProvider cp = new ContactProvider(session);
if (insertedContacts != null)
{
//stuff
}
if (updatedContacts != null)
{
//stuff
}
if (deletedContacts != null)
{
//stuff
}
IList<ContactView> Contacts = new List<ContactView>();
ContactViewProvider Provider = new ContactViewProvider(SessionManager.OpenSession());
Contacts = Provider.GetContactsByName(FirstName, LastName);
//return View(new GridModel(Contacts));
return new LargeJsonResult
{
MaxJsonLength = int.MaxValue,
JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet,
Data = new GridModel<ContactView>
{
Data = Contacts
}
};
}
When I click the Save button in my grid's toolbar, I can use firebug to see the Select() method makes the proper AJAX call but the Update() method doesn't: (See http://i.stack.imgur.com/GPCS6.png)
In this image the first post url corresponds with the values passed into my Select() method. The second post url does not correspond with my Update() method.
What's going on here? Thanks in advance
So it turns out there is nothing wrong with what I did. The MVC project somehow became messed up.
I created a throwaway project to try to reproduced the issue but I couldn't - the throwaway was working. So I deleted the MVC project in my solution and copied the pieces into the new project one by one and sure enough, it works. I have no idea how it became discombopulated in the first place but at least the issue is rectified. For anyone having the same issue, I suggest you try this!
I am using the MVC Contrib Grid for rendering, sorting and filtering my data grid, but I am having problems now that it has been upgraded for MVC3 and Razor. The Custom method in my columns collection does not work for aspx pages , and the columns Action method is now obsolete.
I use grids action method to render my columns like this in MVC 2:
...
<% Html.Grid(Model).Columns(column => {
column.For(x => x.Id);
column.For(x => x.Name);
column.For(x => x.Email);
column.For(x => x.DateOfBirth);
column.For("View User").Named("Tools").Action(x => { %>
<td>
<%= Html.ActionLink("View", "View", new { id = p.Id })%>
<%= Html.ActionLink("Edit ", "Edit", new { id = p.Id })%>
//Snip as there are too many tools :-)
//.....
<%= Html.ActionLink("Delete", "Delete", new { id = p.Id })%>
</td>
<% });
...
Now with the latest version there is a Custom method that replaces the obsolete Action method. I looked at how it can be done in here, which basically works for me now, but I loose all my helpers in the aspx view (url, etc), and now need to render my contents in another method in my model like below:
...
<% Html.Grid(Model).Columns(column => {
column.For(x => x.Id);
column.For(x => x.Name);
column.For(x => x.Email);
column.For(x => x.DateOfBirth);
//the new custom column
column.Custom(Model.ToolsRenderer);
<% });
...
The grid model method below called ToolsRenderer is used to render my html string.
public UserManagementViewModel : BaseModel {
//..snip
//
public object ToolsRenderer(Client client)
{
List<string> links = new List<string>();
var editLink = new TagBuilder("a");
// here is my biggest problem, before Html.ActionLink used to make
// sure that I don't have any missing links or help me if i need to
// refactor an action / controller name :-(
editLink.Attributes["href"] = GetEditUserLink(client, HttpContext.Current.Request.Url.AbsoluteUri);
editLink.SetInnerText("edit");
links.Add(editLink.ToString());
...
...lots of links to be generated here
...
return MvcHtmlString.Create(string.join(" |", links))
}
//..snip
}
This works for now, but is there a way to get my aspx page working like the razor views like below?
#Html.Grid(Model).Columns(column =>
{
column.For(x => x.Id).
column.For(x => x.Name);
column.Custom(#<td><a href='#Html.Actionlink("edit","user",new {id})' alt="#item.email"/><a></td>)
})
I want to say something like:
...
column.Custom(%><td><a href='<%=Html.Actionlink("edit","user",new {id})%>' alt="<%=item.email%>"/><a></td><%)
...
Finally managed to find a work around with some help and digging, and instead of using the custom column, use column.for and push in the Html.Partial. Something like the code below.
<% Html.Grid(Model).Columns(column => {
column.For(x => x.Id);
column.For(x => x.Name);
column.For(x => x.Email);
column.For(x => x.DateOfBirth);
// could use RenderPartial() to
column.For(x =>Html.Partial("UserActionColumn", x));
<% });
For Razor case #helper can be used for custom fields.
For example:
column.For(r => Status(r.Status)).Encode(false).Named("Status");
#helper Status(string value)
{
if (value == RequestStatus.Pending)
{
<span class="label label-info">#value</span>
}
...
}
Complementing the other answers, if you want to sort by that custom column, don't forget to add a SortColumnName. If you don't do this, the grid will use the Named argument as the column name, but Named is also used to give a title to the column. I just got a headache because my column name didn't match the title:
column.For(c => "custom text").Named("Column Name").SortColumnName("ColumnName");
In my editor for insert telerik show only common textbox (not integer,decimal etc).
this is my view:
#(Html.Telerik().Grid <GamePlayer2>(Model).Name("za11").DataKeys(keys => keys.Add(c => c.Id))
.ToolBar(commands => commands.Insert()
.ButtonType(GridButtonType.ImageAndText))
.DataBinding(dataBinding => dataBinding.Server()
.Insert("PlayerAdd", "Player", new { })
.Update("PlayerUpdate", "Player", new { })
.Delete("PlayerDelete", "Player", new { })
)
.Columns(columns =>
{
columns.Bound(b => b.Name);
columns.Bound(b => b.Price);
columns.Command(commands =>
{
commands.Edit();
commands.Delete();
}).Width(200);
})
.Editable(editing => editing.Mode(GridEditMode.PopUp)))
model:
public class GamePlayer2
{
public int Id { get; set; }
public string Name { get; set; }
[DataType(DataType.Currency)]
public decimal Price{ get; set; }
}
Scripts are registered on _Layout. Where is a problem? Why currency(integer,date etc) textbox won't display for fields?
Make sure you have added the EditorTemplates under the Shared/EditorTemplates folder. Basically they are automatically added if you have used the wizard to create your project. If not create a demo project and copy-paste them from there.
I am using free Telerik.Web.Mvc grid and following this example: http://demos.telerik.com/aspnet-mvc/grid/hierarchyajax
My Issue:
I am populating the grid with search results after user input some data and submit with a search button
In the DetailView() method I reference my 'SearchQuote_QuotesForHierarchyAjax' method, which is in defined in my Controller when DetailView executes data should be fetched, but this controller action does not execute for me.
If i load the grid first time page loads it execute. but not when the grid is loaded in a search button click
The Code in my project:
My SearchQuote.aspx View looks like this
<%= Html.Telerik().Grid(Model.QuoteSummaryList)
.Name("SearchQuoteGrid")
.Columns(columns =>
{
columns.Bound(q => q.QuoteId).Title("Quote #").Width(50);
columns.Bound(q => q.AxiomId).Title("Axiom Id").Width(180);
})
.ClientEvents(events => events.OnRowDataBound("quotes_onRowDataBound"))
.DetailView(details => details.ClientTemplate(
Html.Telerik().Grid(Model.QuoteSubSummaryList)
.Name("Quotes_<#= QuoteId #>")
.Columns(columns =>
{
columns.Bound(o => o.PositionCode).Width(101);
columns.Bound(o => o.Group).Width(140);
})
.DataBinding(dataBinding => dataBinding.Ajax()
.Select("SearchQuote_QuotesForHierarchyAjax", "SearchQuote", new
{quoteid ="<#= QuoteId #>"}))
.Pageable()
.Sortable()
.Filterable()
.ToHtmlString()
))
.DataBinding(dataBinding => dataBinding.Ajax()
.Select("SearchQuote_Select", "SearchQuote"))
.Sortable()
.Pageable(p => p.PageSize(3))
%>
<script type="text/javascript">
function expandFirstRow(grid, row) {
if (grid.$rows().index(row) == 0) {
grid.expandRow(row);
}
}
function quotes_onRowDataBound(e) {
var grid = $(this).data('tGrid');
expandFirstRow(grid, e.row);
}
</script>
And SearchQuoteController has this code.
[AcceptVerbs(HttpVerbs.Post)]
[GridAction]
public ActionResult SearchQuote_QuotesForHierarchyAjax(int quoteid)
{
List<QuoteLineSummaryDM> sublist = new List<QuoteLineSummaryDM>();
QuoteLineSummaryDM a = new QuoteLineSummaryDM();
a.PositionCode = "50";
a.Group = "1";
sublist.Add(a);
QuoteLineSummaryDM b = new QuoteLineSummaryDM();
b.PositionCode = "40";
b.Group = "2";
sublist.Add(b);
var qrows = (from r in sublist
select r).AsQueryable();
return View(new GridModel(qrows));
}
What am I missing? My version is even simpler than the demo. Any ideas?
Thanks.
I found another grid that does what I want to do. It's called jqGrid