Is there a nice clean solution for styling columns that may or may not be editable? So the user can tell without clicking in the cell if they can edit it.
I know its easy enough to add a css class to columns if you know they are always going to be editable or not. But in my case the editable fields will be different based on other values of the record and/or permissions of the user.
Thanks
15 Answers, 1 is accepted
If the fields could be editable or not at any given time, there is no clean solution to apply a CSS class to the non-editable columns.
Could you please elaborate on the exact use case? When do we know if a column will be editable or not? After getting the data or runtime? This information will help me in understanding the case and I will be able to provide an approach that fits best the exact scenario.
I look forward to your reply.
Regards,
Preslav
Progress Telerik
assuming the permissions are known as soon as the page is rendered and not determined by an asynchronous call, then you can go safely with adding the class names.
In addition, if the data is asynchronous, you could add the said class names during the databound event.
Regardless of the scenario, as long as the permissions data is available at any point in time, you could apply the styling from that moment onward, be it on page render, grid databount etc.
We would go into more details, but thus far we have noting concrete to cling to. If you could prepare a sample project and attach it to this thread, we could evaluate it and write back.
Just a minor note, this here is a forum thread and you are limited to the types of attachments you add. If you want, we could convert the forum thread to support thread, or if you prefer, you could start a new support thread.
Regards,
Ivan Zhekov
Progress Telerik
The logic could be rendered on the server, but I'm struggling with the proper way to pass this to a kendo grid. Consider a grid with 25-30 columns, in the model section there could be code like this (using mvc wrappers)
model.Field(f => f.Name).Editable(Model.IsPurchaser || Model.IsRequester || Model.IsAdmin);
model.Field(f => f.Status).Editable(Model.IsRequester || Model.IsAdmin || or if status of the record is not closed );
model.Field(f => f.IsConsolidated).Editable(false);
I'd prefer this this business logic not to reside in the UI layer. Is there a suggested pattern that I might follow?
One way is to use the approach you described below.
Another way, using a similar approach, you could use a controller to generate all or some grid settings in json form and pass it to the grid:
<
div
id
=
"grid1"
></
div
>
<
script
>
$(document).ready(function() {
var endPoint = ""; // some URL
$.get( endpoint, function(data) {
$("#grid1").kendoGrid(data);
}, "json");
});
</
script
>
The above examples shows passing the entire options. You could patch certain settings e.g.:
$(
"#grid1"
).kendoGrid({
dataSource: data
})
And since whether or not a column is editable is part of the datasource, you should definitely patch that one.
As for recommendations, the best way is the one that suits you and the project you work on. It's also important to be consistent with the rest of the project (or parts of it) for reducing future maintainability.
Finally, if your only concern is the location of the business logic, you can always use a delegate / external method to populate the fields of the model.
Regards,
Ivan Zhekov
Progress Telerik
Ivan, thanks for your response, but I don't think we are on the same page.
I'm simply trying to understand if conditionally applying an editable boolean and css is supported at runtime. In reading some older posts, it looks like it wasn't 4-5 years ago.
My current solution which I don't feel very good about is to define handler for both the template and the editable property along with an addition boolean property in the viewmodel for each field which may or may not be editable like below. I'm hopeful a better solution can be recommended preferrably without javascript.
in grid
columns.Bound(c => c.SomeProperty).ClientTemplate("#=editableTemplate(SomeProperty, SomePropertyEditable)#").Editable("SomePropertyEditable");
in js:
function somePropertyEditable(dataItem) {
return dataItem.SomePropertyEditable;
}
function editableTemplate(fieldValue, isEditable) {
if (isEditable) {
return "<
div
class
=
'editable'
>" + fieldValue + " </
div
>";;
} else {
return fieldValue;
}
}
I'm glad to hear that you have found a solution.
Currently, the desired result can be achieved only using client-side JavaScript functions as the Editable property accepts only function string:
Editable MVC
https://docs.telerik.com/aspnet-mvc/helpers/grid/how-to/editing/conditionally-editable-columns
The ClientTemplate is also executed on the client that is why it does not have access to the server values from the model:
https://docs.telerik.com/aspnet-mvc/helpers/grid/configuration#clienttemplate
Let me know if you need additional information on this matter.
Regards,
Stefan
Progress Telerik
I have a problem with the solution I described above. We are allowing users to persist the state of the grid so they can have custom views.
When they load a custom view via the kendo 'setOptions', all of the fields become editable rather than just the ones that were conditionally set on the initial load.
Is this a known issue?
Reproduced here: http://dojo.telerik.com/@md1037/AWADA/5
Thank you for the example.
The issue occurs because after assigning the function reference to the options the result is again stringified before passing it to the setOptions method which is causing the references to be lost. If the second kendo.stringify is removed the example is working as expected:
http://dojo.telerik.com/EnELA
This is described in the setOptions method documentation:
https://docs.telerik.com/kendo-ui/api/javascript/ui/grid/methods/setoptions
Regards,
Stefan
Progress Telerik
Thanks for your reply. We are storing the grid options in a database, so the data needs to serialized/deserialized from a json string.
Can you advise on how we would persist the functions in a json string?
In thinking about it I can probably add the function after retrieving the json from the database. Let me know if there may be a better approach. Here is the code I'm evaluating.
var originalOptions = grid.getOptions();
var savedOptions = jQuery.parseJSON(jsonFromDatabase);
if (savedOptions && savedOptions.columns && savedOptions.columns.length > 0) {
for (var i = 0; i < savedOptions.columns.length; i++) {
var col = savedOptions.columns[i];
var editableFunction = originalOptions.columns[i].editable;
if (editableFunction) {
col.editable = editableFunction;
}
}
}
grid.setOptions(savedOptions);
The provided approach looks good.
It is one of the approaches we recommend in our documentation as well:
"JSON.stringify() cannot serialize function references (e.g. event handlers), so if stringification is used for the retrieved Grid state, all configuration fields, which represent function references, will be lost. You have two options to avoid this limitation: use a custom implementation to serialize JavaScript functions, or add the function references back to the deserialized configuration object before passing it to the setOptions method."
Regards,
Stefan
Progress Telerik