I am using Kendo() grid in my application which has binding with an model.
I want to provide Upload control in Grid against each row. Please see razor view design as follows
#(Html.Kendo().Grid<Model>()
.Name("Grid")
.Columns(col =>
{
col.Template(#<text></text>).ClientTemplate("<a Title='Export' href='" + Url.Action("Export", "RouteFileExport", new { Id = "#= RouteScheduleID #", routeID = "#= RouteID #" }) + "'><img src=" + #Url.Content("~/Content/images/download.png") + "></a>").Title("Export");
col.Template(#<text>#(Html.Kendo().Upload()
.Name("attachments<#= ID #>")
.HtmlAttributes(new { id = "attachments<#= ID #>" })
.Multiple(false)
.Async(async => async
.Save("Save", "Controller", new { folder = "<#= ID #>" })
.AutoUpload(true)
)
)</text>).Title("Import");
col.Command(command =>
{
command.Destroy();
command.Custom("Unlock");
command.Custom("Notification");
}
);
})
With above design i am not able to get the upload control displayed inside grid. Its displaying BLANK column.
Please let me know how can i achieve upload against each kendo grid row.
Thanks
Are you looking for a custom button in the last column? If you use the custom command buttons it can be linked to JQuery or a controller action like below:
columns.Command(cmd => cmd.Custom("Upload").Text("Upload").Click("UploadJqueryScript")).Width(75);
columns.Command(cmd => cmd.Custom("Upload").Action("UploadMethod", "Controller")).Width(75);
Have you tried these options?
Related
I am using a kendo grid and inside the grid i have a column in which i have an image,when i click on the image i have to reload the grid.I am not sure which one is better suited for such requirement whether to use kendo mvc grid or kendo UI javascript.
I am currently using Kendo MVC Grid,but not sure how to reload the grid with other set of data.Can someone please guide me how to go for this requirement.Just a high level view.i have to also implement custom paging for this grid.
#(Html.Kendo().Grid<WebApp.Models.IndexModels>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(e => e.FolderName).ClientTemplate("# if (FolderName!=null) { #" +
"<listleft><img title='' src='" + Url.Content("/RMS/Content/Images/folder.gif") + "'\"/><file-folder-names><a data-role=\"button\" onclick=\"onClickDoc('#: data.ObjectId#', '#: data.objectType#');\" id=\"testa\">#:FolderName#</a></file-folder-names></listleft><listright><img class=\"make-fav vAlign\" src='" + Url.Content("/RMS/Content/Images/u837.png") + "'\"/><img class=\"vAlign object-file-options\" src='" + Url.Content("/RMS/Content/Images/context-menu-down-arrow.png") + "'\"/><div class=\"checkbox\"></div></listright>" +
"# } else { #" +
"<listleft># if (IsVirtualDoc==\"1\") { #<img class='show-sub-grid' src-swap='/RMS/Content/Images/virtual-doc-close.png' src='/RMS/Content/Images/virtual-doc-show.png' /># } #<img title='' src=\"#:ImagePath#\"\"/><file-folder-names><a data-role=\"button\" href=\"/RMS/Home/GetDocumentContent?objId=#:ObjectId#\" target=\"_blank\" id=\"testa\">#:DocumentName#</a></file-folder-names><br /><span class=\"details\">#:DocumentSize# bytes <span class=\"paddingLR10\">|</span> #:DocumentCreatedDate# :# if (!(DocumentCreatedby==null)) { # #:DocumentCreatedby# # } #</span></listleft><listright><img class=\"make-fav vAlign\" src='" + Url.Content("/RMS/Content/Images/u837.png") + "'\"/><img class=\"vAlign object-file-options\" src='" + Url.Content("/RMS/Content/Images/context-menu-down-arrow.png") + "'\"/><div class=\"checkbox\"></div></listright>" +
"# } #"
);
})
.Sortable()
.Pageable(pageable => pageable.ButtonCount(5))
.EnableCustomBinding(true)
.Scrollable()
.ClientDetailTemplateId("template")
.HtmlAttributes(new { style = "height:400px;" })
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(10)
.Read(read => read.Action("ReadDataonPaging", "Home").Data("additionalInfo"))
)
.Events(events => events.DataBound("dataBound"))
This is using javascript
basic commands for reloading Grid with different data:
option 1: use same datasourse
$('#GridName').data('kendoGrid').dataSource.read();
$('#GridName').data('kendoGrid').refresh();
https://stackoverflow.com/a/18399994/423356
option 2: use different datasource: (must be initilized)
$("#GridName").data("kendoGrid").setDataSource(differentDatasourceInitialized);
$('#GridName').data('kendoGrid').dataSource.read();
$('#GridName').data('kendoGrid').refresh();
http://www.telerik.com/forums/grid-datasource-option-vs-setdatasource-method#UbC2YiGq2E2aFa-CnFeh7A
How to send optional data to pick which datasource to use or filter ajax read can be done in image click event and your "additionalInfo" javascript function
Read(read => read.Action("ReadDataonPaging", "Home").Data("additionalInfo"))
http://www.telerik.com/forums/pass-additional-parameters-to-read-ajax-datasource-method---mvc#6-wwFQboTECQByGUQYKKhw
If the new set of data is returned from the same URL you can simply call the "read" method of the Grid DataSource on the client side, and new request to the server will be made with the additional data from the "additionalInfo" function.
"read" method of the dataSource
How to get the Grid client-side object
I need to use multiselect list in kendo grid (inline editing) so that user can select multiple values from the list per row.
Following are my requirements:
At the time of display, kendo grid should show comma separated list of all the selected values.
At the time of Add, kendo grid should show multiselect list and allow to select multiple values.
At the time of Edit, kendo grid should show multiselect list with already selected values. User should be able to modify the select and add/remove items from the list.
When user clicks on update/save button, selected values from multiselect list should be available in code behind (in update ajax action) along with id of row.
Following what I do as of now:
I am taking an approach similar to using a drop down list in kendo inline grid.
I have created an Editor Template for displaying multiselect at the time of add/edit.
Following is the code:
#model List<Namespace.CompanyConnector>
#using Kendo.Mvc.UI
#(Html.Kendo().MultiSelectFor(c=>c)
.Name("company_connector_id")
.DataTextField("connector_name")
.DataValueField("company_connector_id")
.Placeholder("Select connector...")
.AutoBind(false)
.Value((List<int>)ViewData["SelectedValues"])
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetCompanyConnectors", "BrandConnector");
})
.ServerFiltering(true);
})
)
#Html.ValidationMessageFor(m => m)
Explanation: I bind a list of model class to the multiselect and set data source in the read action. For selecting the selected values at the time of edit, I have created a function that returns the ids of selected values and put that in View Data in the read action.
I've used this Editor template in my Index page as following code:
#{Html.Kendo().Grid<Cee.DomainObjects.DomainObjects.BrandConnector>()
.Name("BrandConnectorGrid")
.Filterable()
.Events(e => e.Edit("onEdit"))
.DataSource(dataSource => dataSource
.Ajax()
.Events(e => e.Error("error_handler").RequestEnd("onRequestEnd"))
.ServerOperation(false)
.Model(model =>
{
model.Id(p => p.brand_id);
model.Field(e => e.CompanyConnectorList).DefaultValue(new
List<Cee.DomainObjects.DomainObjects.CompanyConnector>());
})
.Read(read => read.Action("_AjaxBinding", "BrandConnector",new{companyID = 0 }).Type(HttpVerbs.Post))
.Update(update => update.Action("_UpdateBinding", "BrandConnector").Type(HttpVerbs.Post)))
.Columns(columns =>
{
columns.Bound(c => c.brand_connector_id).Width(0).Hidden(true);
columns.Bound(c => c.company_id).Width(0).Hidden(true);
columns.Bound(c => c.brand_id).Width(0).Hidden(true);
columns.Bound(u => u.brand_name).Title("Brand").Width("18%").HtmlAttributes(new { #class = "brkWord", #readonly = "readonly" });
columns.ForeignKey(u => u.connector_name, Model.CompanyConnectorList, "company_connector_id", "connector_name").Title("Connector").Width
("16%").HtmlAttributes(new { #class = "brkWord" }).EditorTemplateName("company_connector_id");
columns.Command(p => p.Edit().Text("Edit").HtmlAttributes(new { #title = "Edit" })).Width("16%").Title("Edit");
})
.Editable(editable => editable.Mode(GridEditMode.InLine).CreateAt(GridInsertRowPosition.Top))
.Pageable(pageable => pageable.Refresh(true).PageSizes(GlobalCode.recordPerPageList).ButtonCount(GlobalCode.PageSize).Input(true).Numeric(true))
.HtmlAttributes(new { #class = "dynamicWidth" })
.Sortable(sorting => sorting.Enabled(true))
.Render();
}
Explanation: I've used ForeignKey. Bound it to the string column "connector_name". Connector_name is a comma separated list of IDs that I send from controller. Editor template is used here.
Issue: It works fine at the time of View/Display in Index but Edit does not show selected value. Also we do not get updated value in code behind on update click.
Is this correct way of implementing multiselect list or do I need to bind a collection property as a column in grid?
If I bind a collection property as a column then how would I be able to show comma separated string at the time of display?
Try below code:
function onEdit(e) {
var multiselect = $("#YourMutliselectDropdown").data("kendoMultiSelect");
var IDArray = [];
$(e.model.propertyName).each(function (index) {
var ID = e.model.propertyName[index].id;
IDArray.push(ID);
});
multiselect.value(IDArray);
}
I assume that propertyName is List of your collection and it contains id as property.
try it:
c.Bound(p => p.CompanyConnectorList).ClientTemplate("#= connectorsToString(data)#").EditorTemplateName("company_connector_id");
and js:
function connectorsToString(data) {
var list = data.company_connector_id;
var result = "";
for (var i = 0; i < list.length; i++) {
result += list[i].Name + ';';
}
return result;
}
I'm using Visual Studio 2012 Internet Application that I've enabled for Kendo UI. This is a MVC4 C# and Razor View Project.
I have more then 6 models i'm eventually going to cascade with these dropdowns
I have been following The Tutorial step by step ( actually copied it and renamed in code ).
When page loads the UI looks great, but NO data is bound to the DropdownLists(/comboboxes)
I'm really only focused on the first DropDownList atm wich is
<p>
<label for="clients">Clients:</label>
#(Html.Kendo().DropDownList()
.Name("clients")
.HtmlAttributes(new { style = "width:300px" })
.OptionLabel("Select Client...")
.DataTextField("Client")
.DataValueField("ClientID")
.DataSource(source => {
source.Read(read => {
read.Action("GetCascadeClients", "ComboBox");
});
})
)
</p>
when the code reaches
.DataSource(source => {
source.Read(read => {
read.Action("GetCascadeClients", "ComboBox");
});
})
it's supposed to call this action, but does not this action is located in the controller for this view
public JsonResult GetCascadeClients()
{
var Clients = db.Clients.AsQueryable();
return Json(db.Clients.Select(c => new { ClientID = c.ClientID, Client = c.Client }), JsonRequestBehavior.AllowGet);
}
My question is what am I doing wrong, it almost has to be something stupid.... ( Yes data is in the database, yes in other controls they bind fine.)
EDIT: Thought it was a little peculiar that the 2 dropdownboxes below show text and the top one doesnt?
Breakpoints not being hit here:
Also i have this scripttag that runs, possibly could be something wrong with it Keep in mind im only looking to fill the first ( if first works the rest should fall in )
<script>
$(document).ready(function () {
var clients = $("#clients").data("kendoDropDownList"),
countys = $("#countys").data("kendoDropDownList"),
townShips = $("#townShips").data("kendoDropDownList");
$("#get").click(function () {
var clientsInfo = "\nclients: { id: " + clients.value() + ", name: " + clients.text() + " }",
countysInfo = "\ncountys: { id: " + countys.value() + ", name: " + countys.text() + " }",
townShipsInfo = "\ntownShips: { id: " + townShips.value() + ", name: " + townShips.text() + " }";
alert("Select Tract To Upload:\n" + clientsInfo + countysInfo + townShipsInfo);
});
});
</script>
#Don Thomas Boyle,I was able to copy your code and use my controller to return json data and I get the Option Label to show "Select Client...". Are you able to get the json string returned by manually calling it in the browser address bar? What is the name of your Controller? "Combobox" sounds like a suspicious controller name to me.
<p>
<label for="clients">Clients:</label>
#(Html.Kendo().DropDownList()
.Name("clients")
.HtmlAttributes(new { style = "width:300px" })
.OptionLabel("Select Client...")
.DataTextField("SiteName")
.DataValueField("ID")
.DataSource(source => {
source.Read(read => {
read.Action("GetSites", "PlayGround");
});
})
)
Here is my controller:
namespace MyWebApp.Controllers
{
public class PlayGroundController : Controller
{
readonly MyEntities context = new MyEntities();
public JsonResult GetSites()
{
var sites = context.vSites.Select(s => new SitesVM
{
ID = s.ID,
SiteName = s.SiteName
}).OrderBy(s => s.SiteName);
return Json(sites, JsonRequestBehavior.AllowGet);
}
}
this line :
.DataTextField("Client")
should be:
.DataTextField("ClientName")
I am working in an MVC 3.0 application. In my project I used Telerk mvc grid for data listing. I made grid edit model as "InCell" and provided key board navigation in my question answer area. Each question will have 2 answer options such as "Facts" and "Actions" and will be numeric value. I have used "integer" editor template for this purpose. My requirement is that when the user presses tab key from "Facts" integer textbook, focus will move it to "Actions" integer textbox and if the user presses tab from "Actions" it will move to next row "Facts" text box. But currently key board navigation goes through all cells in the grid. There are few columns between "Facts" and "Actions". My code for grid listing looks like.
#(Html.Telerik().Grid<AnswerQuestionVM>()
.Name("GridQuestions")
.DataKeys(keys =>
{
keys.Add(p => p.QuestionID);
})
.Columns(columns =>
{
columns.Bound(p => p.QuestionNumber).Format("{0:0.00}").HtmlAttributes(new { style = "text-align:center;" }).Title("#").Width("5%").ReadOnly();
columns.Bound(p => p.QuestionName).Title("Question Name").Width("43%").ReadOnly();
columns.Bound(p => p.Facts).Width("8%");
columns.Template(#<text></text>).ClientTemplate("<img src='" + #Url.Content("~/images/help.gif") + "' name='help' alt='help' title='<#=FactOptions#>' />");
columns.Bound(p => p.Actions).Width("8%");
columns.Template(#<text></text>).Width("2%").ClientTemplate("<img src='" + #Url.Content("~/images/help.gif") + "' name='help' alt='help' title='<#=ActionOptions#>' />");
columns.Template(#<text></text>).Title("Skip").Width("3%").ClientTemplate(
"<# if(Skip==false) {#>" +
"<input type='checkbox' style='cursor:pointer;' class='skipClass' />" +
"<#} else{#>" +
"<input type='checkbox' style='cursor:pointer;' class='skipClass' checked='checked' />" +
"<# } #>"
);
columns.Bound(p => p.Note).Title("Note").Width("26%");
})
.Editable(editing => editing.Mode(Telerik.Web.Mvc.UI.GridEditMode.InCell))
.KeyboardNavigation( navigation => navigation.EditOnTab(true))
.ClientEvents(e => e.OnSave("OnSave"))
.DataBinding(dataBinding =>
{
dataBinding.Ajax().Select("GetQuestion", "AnswerQuestion", new { Area = "question", ajax = true }).Enabled(true);
})
.Scrollable(scrolling => scrolling.Enabled(false))
.Sortable(sorting => sorting.Enabled(true))
.Pageable(paging => paging.Enabled(true))
.Filterable(filtering => filtering.Enabled(true))
.Groupable(grouping => grouping.Enabled(false))
.Footer(true)
)
Code for Integer editor template for "Facts" & "Actions" columns bellow.
#(Html.Telerik().IntegerTextBox()
.Name(ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty))
.InputHtmlAttributes(new { style = "width:100%", pattern = "[0-9]*" })
.MinValue(1)
.MaxValue(5)
.Value(Model)
)
Please provide a solution. Any help is appreciated.
Here is what I can suggest you as a work-around because your goal is not supported out of the box.
Feel free to optimize/change the implementation or to make it more generic (e.g. use classes to find cells and not to rely on indexes)
$(function () {
$('#persons tbody').on('keydown', function (e) {
if (e.keyCode == 9) {
var currentCell = $(e.target).closest('td');
var cellIndex = currentCell.index();
if (cellIndex == 2 || cellIndex == 4) { //if editing cell in third or fifth column, use different indexes if needed
e.stopPropagation();
e.preventDefault();
var grid = $('#persons').data().kendoGrid;
if (cellIndex == 2) {
var cellToEdit = currentCell.parent().find('td:eq(4)');
grid._handleEditing(currentCell, cellToEdit);
}
if (cellIndex == 4) {
var cellToEdit = currentCell.parent().find('td:eq(2)');
grid._handleEditing(currentCell, cellToEdit);
}
setTimeout(function () {
cellToEdit.find('input').focus();
})
}
}
})
})
I´m not really sure how to do this, but have you tried using something like tabindex, perhaps by using it within the htmlAttributes? Anyway, I have never done anything like this but maybe you can try something in that area:
columns.Bound(p => p.Facts).Width("8%").HtmlAttributes(new { tabindex = 1 });
columns.Bound(p => p.Actions).Title("Practice").Width("8%").HtmlAttributes(new { tabindex = 2 });
Since you are using Telerik Grid, you might have to mix this somehow within each item. Then again, maybe I´m misunderstanding your point (I´ve been known to do that) :)
I could create a grid with telerik mvc
<% Html.Telerik().Grid(Model)
.Name("ProductGrid")
.Columns(columns => {
columns.Bound(h => h.ProductName).Width("34%");
columns.Bound(h => h.Description).Width("60%");
columns.Bound(h => h.ProductID).Format(Html.ImageLink("Edit", "Products", new { Id = "{0}" }, "/Content/images/icon_edit.gif", "", new { Id = "edit{0}" }, null).ToString()).Encoded(false).Title("").Sortable(false).Width("3%");
columns.Bound(h => h.ProductID).Format(Html.ImageLink("Delete", "Products", new { Id = "{0}" }, "/Content/images/icon_delete.gif", "", new { onclick = string.Format("return confirm('Are you sure to delete this add on?');") },null).ToString()).Encoded(false).Title("").Sortable(false).Width("3%");
})
.EnableCustomBinding(true)
.DataBinding(databinding => databinding.Ajax().Select("_Index", "ProductGrid"))
.Pageable(settings => settings.Total((int)ViewData["TotalPages"])
.PageSize(10))
.Sortable()
.Render(); %>
but I need to add a serial number column in telerik grid.How can i do this?
I think the best way is to use template column like this.
<%
var sn = 0;
Html.Telerik().Grid(Model).Name("Grid").HtmlAttributes(new { style = "width:auto" })
.EnableCustomBinding(true)
.Columns(columns =>
{
columns.Template(c=> {%> <%: ++sn %> <% }).Title("S/N");
columns.Bound(c => c.CustomerNumber);
columns.Bound(c => c.Narration);
})
.Render(); %>
This way you don't have to be adding serial number property to your view models.
Hope this help?
I think the best way to do this is to add a SerialNumber column to your Product class which is your model and than just add another bound column to the grid like this:
columns.Bound(h => h.SerialNumber)
If you pass a List of Products you can populate the SerialNumber column like this:
List<Product> products = GetList(); // Your method to get data here
int counter = 1;
products.ForEach(x => x.SerialNumber = counter++);
If you want to support consistent numbers with paging you have to calculate yourself the initial value of the counter valuable. For this purpose you must have the current page and page size.
In MVC Web Grid
use this calculation
grid.Column(header: "#",
format: item => item.WebGrid.Rows.IndexOf(item) + 1 + Math.Round(Convert.ToDouble(grid.TotalRowCount / grid.PageCount) / grid.RowsPerPage) * grid.RowsPerPage * grid.PageIndex),