Adding New Row Restriction in Kendo Grid MVC - kendo-ui

I have a Kendo grid and a Save button on top of the page. When I click on “Add New Record” toolbar, a new row is added in the grid (client side). When I click on save button, I get the updated viewmodel in my controller’s action method which in turns add/update data in the database.
Now, I want to restrict adding a row in the grid if the grid has already 5 rows in it which means user will not be able to add a new row if the grid reaches its limit (which is 5 rows).
Can anyone of you please give me a sample client side script(jquery) that will restrict user to add new row in the grid?
Thank you very much!!!!!!!
Index.cshtml
#using (Html.BeginForm("Save", "UDF", FormMethod.Post))
{
<input class="button" type="submit" name="save" value="Save"/>
#(Html.Kendo().Grid(Model.List1)
.Name("List1")
.HtmlAttributes(new { style = "width:auto;height:100%" })
.ToolBar(toolbar => toolbar.Create().Text("Add New Record"))
.Editable(editable => editable.Mode(GridEditMode.InCell).CreateAt(GridInsertRowPosition.Top))
.Columns(columns =>
{
columns.Bound(p => p.Title)
.ClientTemplate("#= Title #" +
"<input type='hidden' name='DateFields[#= index(data)#].Title' value='#= Title #' />")
.Title("Title").HtmlAttributes(new { style = "width:30%" });
columns.Bound(p => p.MaxPrecision).Title("Decimal Places")
.ClientTemplate("#= MaxPrecision #" +
"<input type='hidden' name='DateFields[#= index(data)#].MaxPrecision' value='#= MaxPrecision #' />");
columns.Bound(p => p.IsObsolete).Title("Obsolete")
.ClientTemplate("#= IsObsolete #" +
"<input type='hidden' name='DateFields[#= index(data)#].IsObsolete' value='#= IsObsolete #' />");
})
.DataSource(datasource => datasource
.Ajax()
.Model(model =>
{
{
model.Id(p => p.Title);
model.Field(p => p.Title).Editable(true);
model.Field(p => p.MaxPrecision).Editable(true);
model.Field(p => p.IsObsolete).Editable(true);
}
}
)
)
)
}

You can use the toolbar template, like the one demonstrated here.
The template can look something like this:
<button class="k-button" id="myAdd">My Custom Add</button>
Once the Grid is initialized you can attach click handler which adds the new row based on your condition.
$('#myAdd).click(function(){
var gr = $('#gridName').data('kendoGrid');
if(gr.dataSource.data().length<5){
gr.addRow();
}
})
The methods used above are all covered in the documentaion.

Related

Passing data from Kendo window selected rows to parent grid

I am trying to pass data back from a Kendo window to the parent page but its not working. Here is my code. Any help would be appreciated
Any help resolving this would be appreciated. Everything works except the grid on the parent page is not getting populated. Javascript is crashing when it tries to populate the parent pages grid.
<h5 class="bold"><a name="associates"></a>Known Associates</h5>
<div id="GridMessage_Associate" style="display: none;"></div>
#(Html.Kendo().Grid<PeopleSearchResultDO>()
.Name("AssociateGrid")
.AutoBind(false)
.HtmlAttributes(new { style = "display:none;" })
.Columns(columns =>
{
columns.Bound(p => p.PersonId).ClientTemplate("#= PersonId #" + "<input type='hidden' name='PersonAssociates[#= indexAssociate(data) #].PersonId' value='#= PersonId #' />");
columns.Bound(p => p.FirstName).ClientTemplate("#= FirstName #" + "<input type='hidden' name='PersonAssociates[#= indexAssociate(data) #].FirstName' value='#= FirstName #' />");
columns.Bound(p => p.MiddleName).ClientTemplate("#= MiddleName #" + "<input type='hidden' name='PersonAssociates[#= indexAssociate(data) #].MiddleName' value='#= MiddleName #' />");
columns.Bound(p => p.LastName).ClientTemplate("#= LastName #" + "<input type='hidden' name='PersonAssociates[#= indexAssociate(data) #].LastName' value='#= LastName #' />");
columns.Bound(p => p.DOB).ClientTemplate("#= DOB #" + "<input type='hidden' name='PersonAssociates[#= indexAssociate(data) #].DOB' value='#= DOB #' />");
columns.Bound(p => p.Age).ClientTemplate("#= Age #" + "<input type='hidden' name='PersonAssociates[#= indexAssociate(data) #].Age' value='#= Age #' />");
columns.Bound(p => p.LastFourOfSSN).ClientTemplate("#= LastFourOfSSN #" + "<input type='hidden' name='PersonAssociates[#= indexAssociate(data) #].LastFourOfSSN' value='#= LastFourOfSSN #' />");
columns.Bound(p => p.AddressLine1).ClientTemplate("#= AddressLine1 #" + "<input type='hidden' name='PersonAssociates[#= indexAssociate(data) #].AddressLine1' value='#= AddressLine1 #' />");
columns.Bound(p => p.CityOther).ClientTemplate("#= CityOther #" + "<input type='hidden' name='PersonAssociates[#= indexAssociate(data) #].CityOther' value='#= CityOther #' />");
columns.Bound(p => p.GenderShortName).ClientTemplate("#= GenderShortName #" + "<input type='hidden' name='PersonAssociates[#= indexAssociate(data) #].GenderShortName' value='#= GenderShortName #' />");
columns.Bound(p => p.RaceShortName).ClientTemplate("#= RaceShortName #" + "<input type='hidden' name='PersonAssociates[#= indexAssociate(data) #].RaceShortName' value='#= RaceSHortName #' />");
}
)
.DataSource(
dataSource => dataSource
.Ajax()
.ServerOperation(false)
)
)
<br />
<br />
<!-- Modal -->
<input id="openassociates" value="Search for an Associate" class="btn btn-default btn-lg" />
#(Html.Kendo().Window()
.Name("associatewindow")
.Width(1400)
.Height(500)
.Draggable()
.Resizable()
.Title("Add New Person")
.Visible(false)
.Modal(true)
.Actions(actions => actions
.Minimize()
.Maximize()
.Close().Refresh()
)
.Content("loading associates ...")
.LoadContentFrom("LoadAssociatesForm", "Person")
.Events(ev => ev.Close("onClose"))
)
<div class="responsive-message"></div>
<script>
function onClose() {
$("#openassociates").show();
}
$(document).ready(function () {
$("#openassociates").bind("click", function () {
$("#associatewindow").data("kendoWindow").open();
$("#openassociates").hide();
});
});
</script>
<p>
<input type="submit" id="btnPersonSave" value="Save" class="btn btn-lg btn-primary" />
</p>
}
</div>
<script type="text/javascript">
function error_handler(e) {
if (e.errors) {
var message = "Errors:\n";
$.each(e.errors, function (key, value) {
if ('errors' in value) {
$.each(value.errors, function () {
message += this + "\n";
});
}
});
alert(message);
}
}
function indexAssociate(dataItem) {
var data = $("#AssociateGrid").data("kendoGrid").dataSource.data();
return data.indexOf(dataItem);
}
**Here is the popup Window content**
<script type="text/javascript">
function getPeopleSearchCriteria() {
var searchInput = {
FirstName: $("#PeopleSearchForm").find("#PeopleSearchInput_FirstName").val(),
MiddleName: $("#PeopleSearchForm").find("#PeopleSearchInput_MiddleName").val(),
LastName: $("#PeopleSearchForm").find("#PeopleSearchInput_LastName").val(),
LegalFullName: $("#PeopleSearchForm").find("#PeopleSearchInput_LegalFullName").val(),
Address1: $("#PeopleSearchForm").find("#PeopleSearchInput_Address1").val(),
Address2: null,
Address3: null,
StateId: $("#PeopleSearchForm").find("#PeopleSearchInput_StateId").val(),
PostalCode: $("#PeopleSearchForm").find("#PeopleSearchInput_PostalCode").val(),
PhoneNumber: $("#PeopleSearchForm").find("#PeopleSearchInput_PhoneNumber").val(),
DateOfBirthStart: $("#PeopleSearchForm").find("#PeopleSearchInput_DateOfBirthStart").val(),
DateOfBirthEnd: $("#PeopleSearchForm").find("#PeopleSearchInput_DateOfBirthEnd").val(),
GenderId: $("#PeopleSearchForm").find("#PeopleSearchInput_GenderId").val(),
EthnicityId: null,
LastFourOfSsn: $("#PeopleSearchForm").find("#PeopleSearchInput_LastFourOfSSN").val(),
RaceId: $("#PeopleSearchForm").find("#PeopleSearchInput_RaceId").val(),
CaseId: $("#PeopleSearchForm").find("#PeopleSearchInput_CaseId").val(),
DocketNumber: $("#PeopleSearchForm").find("#PeopleSearchInput_DocketNumber").val(),
CaseOpenStartDate: $("#PeopleSearchForm").find("#PeopleSearchInput_CaseOpenStartDate").val(),
CaseOpenEndDate: $("#PeopleSearchForm").find("#PeopleSearchInput_CaseOpenEndDate").val(),
CasePersonTypeId: $("#PeopleSearchForm").find("#PeopleSearchInput_CasePersonTypeId").val(),
}
var model = {
PeopleSearchInput: searchInput
}
return model;
}
#(Html.Kendo().Grid<PeopleSearchResultDO>()
.Name("AssociateResultsGrid")
.AutoBind(false)
.HtmlAttributes(new { style = "display:none;" })
.Columns(columns =>
{
columns.Select().Width(50);
columns.Bound(p => p.PersonId).Hidden(true);
columns.Bound(p => p.FirstName).ClientTemplate("<strong>#: FirstName #</strong>");
columns.Bound(p => p.MiddleName).ClientTemplate("<strong>#: MiddleName #</strong>");
columns.Bound(p => p.LastName).ClientTemplate("<strong>#: LastName #</strong>");
columns.Bound(p => p.DOB);
columns.Bound(p => p.Age);
columns.Bound(p => p.LastFourOfSSN);
columns.Bound(p => p.AddressLine1);
columns.Bound(p => p.CityOther);
columns.Bound(p => p.GenderShortName);
columns.Bound(p => p.RaceShortName);
})
//there is a bug with persisting right now. We want to persist the selected rows even after paging or sorting.
//.PersistSelection()
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
.Read(read =>
read.Action("AssociatesSearchResults", "Person")
.Data("getPeopleSearchCriteria").Type(HttpVerbs.Post)
)
//we are disabling paging and sorting until the issue with persisitng is resolved
//.PageSize(10)
//.Sortable()
)
.NoRecords(n => n.Template("<div class='alert alert-danger'><h3 class='text-danger bold'>No records returned!</h3></div>"))
//.Scrollable(s => s.Height("auto"))
.Scrollable(s => s.Height("400px"))
//.Pageable(p => p.PageSizes(new int[] { 5, 10, 20, 50, 100 }))
)
<p> <input type="button" id="btnAddAssociate" value="Add Selected Associate(s)" class="btn btn-default bold" style="display: none;" />
</p>
<script type="text/javascript">
$("#btnAddAssociate").click(function () {
$("#GridMessage_Associate").css("display", "none");
var entityGrid = $("#AssociateResultsGrid").data("kendoGrid");
var rows = entityGrid.select();
//finally close modal window
var myxxWindow = $("#associatewindow");
myxxWindow.data("kendoWindow").close();
if (rows !== undefined) {
rows.each(function (index, row) {
var selectedItem = entityGrid.dataItem(row);
// selectedItem has EntityVersionId and the rest of your model
var assogrid = $("#AssociateGrid").data("KendoGrid");
assogrid.dataSource.add(
{
PersonId: selectedItem.PersonId,
FirstName: selectedItem.FirstName,
MiddleName: selectedItem.MiddleName,
LastName: selectedItem.LastName,
DOB: selectedItem.DOB,
Age: selectedItem.Age,
LastFourOfSSN: selectedItem.LastFourOfSSN,
AddressLine1: selectedItem.AddressLine1,
CityOther: selectedItem.CityOther,
GenderShortName: selectedItem.GenderShortName,
RaceShortName: selectedItem.RaceShortName
});
$("#AssociateGrid").css("display", "block");
//clear selected items in parent grid
});
}
else {
$("#AssociateGrid").css("display", "none");
}
})
</script>
The problem was with typos and case-sensitivity. For example, I used .data("KendoGrid") instead of .data("kendoGrid"). I also had a typo in line
var selectedItem = entityAssociateGrid.dataItem(row)
it should have been
var selectedItem = entityAssociateGridDS.dataItem(row)

CheckBox and id value to actionresult in kendo ui with ajax binding

I am developing a MVC with kendo UI grid. In which I have grid and one Button. Grid contains check-box. When We click on button check box value(true/false) and Record id should go to action result.
using (Html.BeginForm("Update", "Model"))
{
Html.Kendo().Grid(Model.Users)
.Name("grid")
.Columns(columns =>
{
columns.Bound(o => o.UserName).Width("300px");
columns.Bound(o => o.IsLicensed).Template(o =>
{%><%: Html.CheckBox("license",o.IsLicensed)%> <%: Html.Hidden("id", o.UserId) %><%}).Width("200px");
})
.Resizable(resize => resize.Columns(true))
.Sortable(sorting => sorting.Enabled(true))
.Filterable(f => f.Enabled(true))
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(new int[] {10, 20, 50, 100})
.ButtonCount(5))
.Render();
%>
<p>
<input class="k-primary k-button" type="submit" value="Save" name="selectedValues"/>
</p>
<%
Html.EndForm();
}
%>
</div>
<% });
And my actionresult looks as below
public ActionResult Update(string[] license, string[] id)
Now here I am using ajax binding and giving datasource. So I can't use Template. We need to use ClientTemplate. ClientTemplate code changes are shown as below.
.Columns(columns =>
{
columns.Bound(o => o.UserName).Width("300px");
columns.Bound(o => o.IsLicensed).Width("300px").ClientTemplate("<input type='checkbox' name='license' ${ IsLicensed == true ? checked='checked' : ''} enabled />" + "<input type='hidden' name='id' value='#= UserId#' />");
})
.DataSource(datasource => datasource.Ajax().Read(read => read.Action("Customers_Read", "UsersLicensing")).PageSize(10))
.Render();
In previous case when Update actionresult is called both parameter are array of 10 as pagesize is 10 and I can update database. But in this case(with ajax and clientTemplate) id parameter is coming as array of 10 items but license parameter depends on number of checkbox selected(if 3 checkbox is selected then license contains 3 element). So I can't make one to one mapping.
Can anybody help me with this or suggest any better idea?
Try this....Worked for me
columns.Template(#<text></text>).
ClientTemplate("<input type='checkbox' class='chkbx' onclick='chkRoleChkBox(this)'
value='#=RoleId#' # if (DefaultRoleflag == 'Y') { # disabled='disabled' # } #/>").Width(30);
You should be able to change your client template as such:
.ClientTemplate("<input type='checkbox' name='license' ${ IsLicensed == true ? checked='checked' : ''} enabled value='#= UserId#' />")
Put the UserId directly into the value of the checkbox. Then when you post, instead of getting an array of "true" you should get an array of the value (which is the UserId) for the checked items.
Update
If you want to be able to get both the checked and unchecked lists, then you can add the hidden field back to the ClientTemplate.
.ClientTemplate(
"<input type='checkbox' name='license' ${ IsLicensed == true ? checked='checked' : ''} enabled value='#= UserId#' />" +
"<input type='hidden' name='id' value='#= UserId#' />"
)
Then when you post you will have an array of all of the IDs in string[] id and an array of the checked IDs in string[] license. Then to get the unchecked, you can use use System.Linq namespace and use Enumerable.Except.
public ActionResult Update(string[] license, string[] id)
{
//....
var unchecked = id.Except(license).ToArray();
//...
}

How to use Kendo Grid Ajax Read event on demand

I have page with DropDownList and Telerik's Kendo UI Grid Control. When first time page is opened DropDownList has no item selected in it. When user selects value in DropDownList only then Grid should make Ajax call to the server and load corresponding data.
My code works fine when user selects item in DropDownList, but the problem is that first time when page is opened I there is no value in DropDownList and Grid should not make a call to the server.
My question is how can I prevent grid not to make a call to the server if there is no item selected in DropDowList?
<div>
#Html.Kendo().DropDownList().Name("broker").DataTextField("GrandParentName").DataValueField("Id").BindTo(Model).SelectedIndex(#selectedIndex).Events(e => e.Change("brokerChanged"))
</div>
#(Html.Kendo().Grid<OrderViewModel>()
.Name("Orders")
.HtmlAttributes(new {style = "height: 500"})
.Columns(c =>
{
c.Bound(p => p.Id)
.Width(50)
.Title("")
.Sortable(false)
.IncludeInMenu(false)
.ClientTemplate((#Html.ActionLink("Edit", "Index", "Splits", new {Id = "OrderId"}, null).ToHtmlString().Replace("OrderId", "#=Id#")));
c.Bound(p => p.TradeDate)
.Title("Trd Dt")
.Format("{0:d}")
.Width(90)
.HtmlAttributes(new {style = "text-align: right"});
c.Bound(p => p.Price)
.Title("Price")
.Format("{0:n}")
.Width(100)
.HtmlAttributes(new {style = "text-align: right"});
c.Bound(p => p.Status)
.Title("Status");
c.Bound(p => p.Notional)
.Title("Notional")
.Format("{0:n}")
.HtmlAttributes(new {style = "text-align: right"});
})
.Sortable()
.Scrollable()
.ColumnMenu()
.Pageable(x =>
{
x.Enabled(true);
x.PreviousNext(false);
x.PageSizes(false);
x.Info(true);
x.Input(false);
x.Numeric(false);
x.Refresh(true);
x.Messages(y => y.Display("{2} Order(s)"));
})
.Resizable(resize => resize.Columns(true))
.Reorderable(reoder => reoder.Columns(true))
.DataSource(ds => ds.Ajax()
.ServerOperation(false)
.Read(read => read.Action("Action", "MyController").Data("selectedBrokerId")))
)
<script type="text/javascript">
function brokerChanged() {
var grid = $("#Orders").data("kendoGrid");
grid.dataSource.read();
}
function selectedBrokerId() {
var obj = { brokerId: $("#broker").data("kendoDropDownList").value() };
return obj;
}
</script>
Thanks a lot for your time and help.
There is an autobind function for the grid. You can use this to determine whether or not to read when the page first loads. This should work (assuming that selectedIndex determines if a dropdown value is selected):
#(Html.Kendo().Grid<OrderViewModel>()
.Name("Orders")
.HtmlAttributes(new {style = "height: 500"})
.AutoBind(selectedIndex > 0)
//rest of your grid declaration

Rebind Kendo Grid in MVC

I am trying to rebind Kendo Grid on a button click after filtering data using the JavaScript below, but it is not working. What should I do?
My HTML code using Kendo.Mvc.Dll:
Html.Kendo().Grid<EquityStreet.Data.ESData.Proc_GetESManagersListAndFilterResult>().Name("GridESManager").BindTo(Model.ESManagersList).Columns(columns =>
{
columns.Bound(m => m.pkESManagerId).Template(#<input type="checkbox" id="#item.pkESManagerId" />).Title("").Width("2%");
columns.Bound(m => m.pkESManagerId).Template(#<text> #item.FirstName #item.LastName</text>).Title("Name");
columns.Bound(m => m.CompanyName).Title("Company");
columns.Bound(m => m.MobileNo).Title("Phone Number");
columns.Bound(m => m.ESManagerStatus).Template(#<text>#(item.ESManagerStatus == 1 ? "Active" : "Inactive")</text>).Title("Status");
columns.Bound(m => m.pkESManagerId).Template(#<text> <a href="../Utilities/NewESManager?EId=#item.pkESManagerId" class="access_btn">
</a><a href="../Utilities/NewESManager?EId=#item.pkESManagerId" class="edit_btn">
</a>
</text>).Title("Actions");
}).ToolBar(tb =>
{
tb.Template("<div class='GridSearchHeader'><div style='float:left'><input type='button' value='Reset Pwd'><input type='button' value='Delete'></div><label>Filter: </label><input type='search' style='width: 230px' id='txtSearch'><select id='Status'><option value=-1>Select</option><option value=1>Active</option><option value=0>Inactive</option></select><input type='button' onclick='FilterList()' value='Go'><input type='button' value='Reset'></div>");
}).Pageable()
)
JavaScript:
$.post('#Url.Action("FilterESManagerList", "../../Utilities")', { Keyword: Search, UserStatus: status }, function (result) {
var grid = $("#GridESManager").data("kendoGrid");
grid.dataSource.data(result);
grid.refresh();
alert(grid);
});
Calling grid.dataSource.data(result) should rebind the grid unless the result is not in the expected format.
It looks that when using ajax-binding, calling grid.dataSource.fetch() will trigger the read method defined in the datasource and rebind automatically.
try this:
$("#gridName").data("kendoGrid").dataSource.sync();

Telerik MVC Grid - HiddenIndexerInputForModel in ClientTemplate

MVC3 and using the Telerik Grid.
I'm using Phil Haacks Hidden Indexer Input For Model to bring form values back. Only problem is that when using Ajax as the databinder any Templates used need to have a corresponding ClientTemplate. This is where I'm having a problem. How do I insert this, and the iterator into the ClientTemplate, which is expecting a string?
This is what I've tried to no avail ... when I run the page I get an error saying 'Iter' is not defined.
<% int Iter = 0; %>
<% Html.Telerik().Grid(Model.TransferStudents)
.Name("TransferStudents")
.Columns(columns =>
{
columns.Bound(o => o.Name)
.Width(250);
columns.Template(o =>{%>
<%: Html.HiddenFor(model => Model.TransferStudents[Iter].StudentId)%>
<%: Html.CheckBoxFor(model => Model.TransferStudents[Iter].Transfer)%>
<%})
.ClientTemplate("<input type='hidden' id='StudentId' value='<#= StudentId #>' /><input type='checkbox' name='Transfer' <#= Transfer? \"checked='checked'\" :\"\" #> />")
.HtmlAttributes(new { #style = "text-align: center;" })
.HeaderHtmlAttributes(new { #style = "text-align: center;" })
.HeaderTemplate("Check All <input type='checkbox' id='chkAll' />")
.Width(105);
columns.Template(o =>{ %><% Iter = Iter + 1; %><%})
.ClientTemplate("<# Iter = Iter + 1; #>")
.Hidden();
columns.Template(o =>{ %><%: Html.HiddenIndexerInputForModel()%><% })
.ClientTemplate("<#= Html.HiddenIndexerInputForModel() #>")
.Hidden();
})
.DataBinding(dataBinding => dataBinding.Ajax().OperationMode(GridOperationMode.Server).Select("_Transfer", "Administration"))
.Pageable(paging => paging.Style(pagerStyles).PageSize(2, new[] { 5, 10, 15, 25, 50, 200 }).Position(GridPagerPosition.Top).Total((int)ViewData["total"]))
.Sortable()
.NoRecordsTemplate("<p class='instructions'>No Records Available</p>")
.Render();
%>
Any pointers would be appreciated.
The ClientTemplate expects a string which will be translated to JavaScript and executed in the browser (client-side). Any server code such as Html.HiddenIndexerInputForModel() won't work - there is no JavaScript equivalent. You need to use plain html as you have done in the other column.

Resources