I have the following grid:
Html.Kendo().Grid<
ABC
>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(p => p.Apply).Width(155);
columns.Bound(p => p.Number).Width(155);
columns.Bound(p => p.Paid).Width(155);
columns.Bound(p => p.Note);
columns.Bound(p => p.CompanyName);
columns.Bound(p => p.ReferenceNumber);
columns.Bound(p => p.ProcessedDate).Format("{0:d}");
columns.Bound(p => p.ErrorMessage);
columns.Command(command => command.Edit()).Width(100).Visible(???);
})
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Events(events => events.DataBound("onDataBound"))
How do I set the visibility on a row by row basis? I want the edit button to be invisible if the ProcessedDate has a value.
The edit command contains a visible property, but I don't see a way to write a lambda expression within the visible property to set it.
There is also an DataBound event, but I can't find an example of how to use this or some other grid event to check the value of the ProcessedDate so that I can hide or show the edit button.
The regular ASP.Net Grid has an onItemDataBound event, what is the equivelant in MVC?
2 Answers, 1 is accepted
You could achieve this in several ways, depending on the dataSource binding, which is used in the current scenario. I'll cover both Ajax and Server binding.
If a Server binding is used, you could use the RowAction method and assign a custom class to the rows, that will not be editable.
E.g.
.RowAction(row =>
{
if
(row.DataItem.ProcessedDate !=
null
)
{
row.HtmlAttributes[
"class"
] =
"custom"
;
}
})
.custom .k-grid-edit
{
display
:
none
;
}
If an Ajax binding is used, you could bind to the dataBound event of the Grid, traverse the items and hide the buttons manually.
E.g.
.Events(e => e.DataBound(
"onDataBound"
))
function
onDataBound(e) {
var
grid = $(
"#grid"
).data(
"kendoGrid"
);
var
gridData = grid.dataSource.view();
for
(
var
i = 0; i < gridData.length; i++) {
var
currentUid = gridData[i].uid;
if
(gridData[i].ProcessedDate !=
null
) {
var
currenRow = grid.table.find(
"tr[data-uid='"
+ currentUid +
"']"
);
var
editButton = $(currenRow).find(
".k-grid-edit"
);
editButton.hide();
}
}
}
Wish you a great day!
Greetings,
Dimiter Madjarov
the Telerik team
@(Html.Kendo().Grid<
MyProject.Web.Models.Scenarios.ClientGridClientViewModel
>()
.Name("ClientGrid")
.Columns(c => {
c.Bound(client => client.Name);
c.Bound(client => client.ScenarioCount);
c.Bound(client => client.ActiveScenarioName);
c.Bound(client => client.LastModifiedBy);
c.Bound(client => client.LastModifiedOn).Format("{0:G}");
c.Command(cmd => cmd.Custom("Change").Click("showScenarios"));
c.Command(cmd => cmd.Custom("Edit").Click("editScenario")).Visible(client => client.ScenarioCount > 0);
})
.Filterable()
.DataSource(d => d
.Ajax()
.Events(e => {
e.Error("datasourceError");
})
.Model(model => {
model.Id(client => client.Id);
})
.ServerOperation(true)
.Sort(x => x.Add("Name"))
.Read("ClientGridRead", "Scenarios")
)
)
I hope you could do something along these lines.
Cheers,
Nick
Currently the Grid does not support such configuration option. If you consider that it would be a useful addition, I would suggest you to post it as a feature request in our Kendo User Voice portal. If it gets popular among the community we will consider to implement it in future releases of Kendo UI.
Regards,
Dimiter Madjarov
Telerik
<!-- BEGIN Grid -->
@(Html.Kendo().Grid<CapacityPlanningStaffingResourceRecord>()
.Name(
"grid"
)
.Columns(columns =>
{
//Command Column
columns.Bound(p => p.RecordID).Width(200).Locked(
true
).Lockable(
false
); ;
columns.Bound(p => p.StaffingPlanRecordId).Width(200).Locked(
true
).Lockable(
false
); ;
columns.Bound(p => p.RecordType).Width(100).Locked(
true
).Lockable(
false
);
columns.Bound(p => p.HireDate).Format(
"{0:MM/dd/yyyy}"
).Width(140).Locked(
true
).Lockable(
true
).HeaderHtmlAttributes(
new
{ style =
"overflow: visible; white-space: normal"
}).EditorTemplateName(
"Date"
);
columns.Bound(p => p.JobProfile).Width(210).Locked(
false
).Lockable(
true
).HeaderHtmlAttributes(
new
{ style =
"overflow: visible; white-space: normal"
}).EditorTemplateName(
"cJobProfile"
);
columns.Bound(p => p.CountOfResources).Format(
"{0:N0}"
).Width(140).Locked(
false
).Lockable(
true
).HeaderHtmlAttributes(
new
{ style =
"overflow: visible; white-space: normal"
}).EditorTemplateName(
"Integer"
);
columns.Command(command => { command.Edit(); command.Destroy(); }).Width(180).Locked(
false
).Lockable(
false
); ;
})
.ToolBar(toolbar => toolbar.Create())
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Pageable()
.Sortable()
.Scrollable()
.Filterable()
.Events(events => events.DataBound(
"dataBound"
))
.HtmlAttributes(
new
{ style =
"font-size:13px;width:1400px; height:700px"
})
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(36)
.Events(events => events.Error(
"error_handler"
).Change(
"onRequestEnd"
))
.Model(model => model.Id(p => p.RecordID))
.Model(model => model.Field(
"HireDate"
,
typeof
(DateTime)))
.Model(model => model.Field(
"CountOfResources"
,
typeof
(
int
)))
.Model(model => model.Field(
"RecordID"
,
typeof
(
long
)))
.Model(model => model.Field(
"StaffingPlanRecordId"
,
typeof
(
long
)))
.Read(read => read.Action(
"ReadCapacityPlanningStaffingPlanRecord"
,
"CapacityPlanningProcessor"
).Type(HttpVerbs.Post))
.Create(update => update.Action(
"CreateCapacityPlanningStaffingPlanRecord"
,
"CapacityPlanningProcessor"
).Type(HttpVerbs.Post))
.Update(update => update.Action(
"UpdateCapacityPlanningStaffingPlanRecord"
,
"CapacityPlanningProcessor"
).Type(HttpVerbs.Post))
.Destroy(update => update.Action(
"DestroyCapacityPlanningStaffingPlanRecord"
,
"CapacityPlanningProcessor"
).Type(HttpVerbs.Post))
)
)
<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 onRequestEnd(e) {
var grid = $(
"#grid"
).data(
"kendoGrid"
);
var gridData = grid.dataSource.view();
for
(var i = 0; i < gridData.length; i++) {
var currentUid = gridData[i].uid;
console.log(i +
' '
+ gridData[i].RecordType);
if
(gridData[i].RecordType !=
"Model"
) {
console.log(
"Model: "
+ i +
' '
+ gridData[i].RecordType +
" UID:"
+ currentUid);
var currenRow = grid.table.find(
"tr[data-uid='"
+ currentUid +
"']"
);
var editButton = $(currenRow).find(
".k-grid-edit"
);
console.log(editButton);
editButton.hide();
}
}
}
</script>
<!-- END Grid -->
The code looks correct, but I would suggest to execute it in the dataBound event of the Grid instead of the change event of the dataSource.
Let me know if this resolved the issue or I could provide further assistance.
Regards,
Dimiter Madjarov
Telerik
But I do not think that would prevent my buttons from hiding, would it?
I am not sure what do you mean by "it is not available". It seems that you have bound to it in the provided sample code:
Events(events => events.DataBound(
"dataBound"
))
Regards,
Dimiter Madjarov
Telerik
I had actually put the event in the DataSource events, not the grid events. That is why I did not have DataBound available and also why my code was not working. By adding the event to the grid not the data source, it is hiding the buttons as it should.
I am sorry, I should have picked that up earlier...and thanks for taking the time to ask the question...
Thanks for the update.
I wish you a great day!
Regards,
Dimiter Madjarov
Telerik
Hi Dimiter,
The post is very helpful for me. But I am confused where do I paste this chunk / in which CSS?
.custom .k-grid-edit{ display: none;}
Hello Ziad,
The CSS should be added to the page where the Grid is displayed.
Let me know if I could assist further regarding the case.
Regards,Dimiter Madjarov
Telerik
Hello everyone,
I used the Events(events => events.DataBound("dataBound")) as suggested by Dimiter.
for each user, I have 2 buttons (edit and delete) but for some of them i remove the delete one.
But now, when i edit one of this un-deletable user. if i cancel the changes the cancel button reappears.
Did someone know how can i delete the button again ?
Hello Maxime,
You could attach a handler to the cancel event of the Grid
http://docs.telerik.com/kendo-ui/api/javascript/ui/grid#events-cancel
and execute the same logic for hiding in a setTimeout() call inside of it.
Dimiter Madjarov
Telerik by Progress

In case it's helpful to someone I had a case where I was attempting the same with an ajax-bound grid that had grouped columns and had to modify the loop in the onDataBound function in Dimiter's solution to something like:
for
(
var
g = 0; g < gridData.length; g++) {
for
(
var
i1 = 0; i1 < gridData[g].items.length; i1++) {
for
(
var
i2 = 0; i2 < gridData[g].items[i1].items.length; i2++) {
for
(
var
i3 = 0; i3 < gridData[g].items[i1].items[i2].items.length; i3++) {
var
currentUid = gridData[g].items[i1].items[i2].items[i3].uid;
if
(gridData[g].items[i1].items[i2].items[i3].ProcessedDate !=
null
) {
var
currentRow = grid.table.find(
"tr[data-uid='"
+ currentUid +
"']"
);
$(currentRow).find(
".k-grid-Edit"
).hide();
}
}
}
}
}
I have the following code (copied from above):
...
...
...
columns.Command(command => command.Custom("Bestellung").Click("showDetails")).Width(100);
})
.Events(e => e.DataBound("onDataBound"))
.Scrollable()
.DataSource(dataSource => dataSource.Ajax()
.Group(grp => { grp.Add(a => a.WeekNumber); })
.Model(model => {
model.Id(p => p.ID);
model.Field(p => p.Salads).DefaultValue(new List<
EECanteen.Models.FoodItem
>());
model.Field(p => p.WeekNumber).Editable(false); })
.Read(read => read.Action("DaysMeals_Read", "Home"))
)
)
<
script
>
function onDataBound(e) {
var grid = $("#grid").data("kendoGrid");
var gridData = grid.dataSource.view();
for (var i = 0; i <
gridData.length
; i++) {
var
currentUid
=
gridData
[i].uid;
if (gridData[i].CanOrder) {
var
currenRow
=
grid
.table.find("tr[
data-uid
=
'" + currentUid + "'
]");
var editButton = $(currenRow).find(".k-grid-edit");
editButton.hide();
}
}
}
</script>
Although (checked with alerts) the code runs and "editButton" is a valid object the button is not hidden.
What is wrong here?
Manfred
Hello,
The sample code seems correct. You could debug it and assure that the editButton variable is set to the correct element. If the problem is still reproducing, please send small isolated runnable example, so we could inspect it locally.
Regards,Dimiter Madjarov
Telerik
I could isolate the problem - it has something to do with the grouping.
As soon as I remove the .Group(grp => { grp.Add(a => a.WeekNumber); }) from the datasource the thing works...
But I need it with grouping....
How easy could it be with a property on the Column instead of fiddling around with script code...
In my case something like columns.Command(command => command.Custom("Bestellung").Click("showDetails")).Hidden(a=>a.CanOrder)....
Anyhow - I guess it is a simple "missing thing" to make the hidden button available even if grouping is active
Ok - I got it - trial and error - frustrating....
The "problem" - with the above suggested (from Nick)
c.Command(cmd => cmd.Custom("Edit").Click("editScenario")).Visible(client => client.ScenarioCount > 0);
such scenarios would work very simple (also "Disabled") would be an option in this case.
I think "disabling / enab​ling" (show / hide) an element depending on the data is a very common task - such controls should implemt such functionallity.
RAD - ​means "have options like this" - and not force us to write scripts which by the way change - dependig on "is grouped" or whatever...
Hello ManniAT,
I am glad the issue is resolved. Let us know if further help is required.
Regarding the last suggestion, Kendo UI is not part of the Rad toolkit. It is a JavaScript framework and tends to not implement tasks, that could be achieved directly via jQuery.
Regards,Dimiter Madjarov
Telerik
Any possible way to do more than just to hide a button in a custom command column? I'm hiding the button on certain rows but I'm worried someone with basic HTML knowledge could go into a browser's developer tools and unhide the button. Therefore giving them access to what is behind the button, which is what I'm trying to avoid.
Yes, I can add a 2nd check to what's behind the button in case this happens and stop them. But I'm wondering if I can avoid that.
Yes, I can add a 2nd check to what's behind the button in case this happens and stop them. But I'm wondering if I can avoid that. [/quote]
Honestly, you should always be validating client input on the server side. There's nothing stopping someone using a tool like Fiddler or Postman to just make up their own http calls and completely sidestep any UI you have constructed.
Hello Jared,
Indeed, even if the command is removed for some rows and not just hidden, a server side validation is always recommended.
Regards,Dimiter Madjarov
Telerik
Hello Jared,
Could you elaborate what exactly are you trying to achieve which is different, than the described approach?
Regards,Dimiter Madjarov
Telerik
Instead of just calling .hide() on the button's HTML element, I'd rather the button not get created at all.
Or if there is no way to prevent it from being created, can we destroy the button instead of just hiding it. This would be one more way to stop someone from someone just tweaking the CSS to show the button.
Hello Jared,
You could directly remove the command instead of just hiding it or for example use a templated column with conditional logic that adds the command only to certain rows. This way the mark up will not be present in the DOM, if this is your concern. Keep in mind that this will also not stop someone from tweaking the DOM, manually copy/paste the command markup from the other rows and add to the current one, so a validation on the back end is always recommended.
Regards,I hope this information helps. Have a great weekend!
Dimiter Madjarov
Telerik