Custom css for conditionally editable columns

16 posts, 0 answers
  1. Marc
    Marc avatar
    123 posts
    Member since:
    Jul 2010

    Posted 21 Dec 2017 Link to this post

    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

  2. Preslav
    Admin
    Preslav avatar
    455 posts

    Posted 22 Dec 2017 Link to this post

    Hi Marc,

    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
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  3. Marc
    Marc avatar
    123 posts
    Member since:
    Jul 2010

    Posted 22 Dec 2017 in reply to Preslav Link to this post

    The exact use case is that different fields will be editable based on the status of the record and the permission levels of the user. These are also large datasets, so I suspect having a javascript based template to evaluate every record and style the cells individually would not be performant.
  4. Ivan Zhekov
    Admin
    Ivan Zhekov avatar
    646 posts

    Posted 25 Dec 2017 Link to this post

    Marc,

    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
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  5. Marc
    Marc avatar
    123 posts
    Member since:
    Jul 2010

    Posted 27 Dec 2017 in reply to Ivan Zhekov Link to this post

    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?

  6. Marc
    Marc avatar
    123 posts
    Member since:
    Jul 2010

    Posted 27 Dec 2017 in reply to Marc Link to this post

    Also InCell editing is a requirement here.
  7. Ivan Zhekov
    Admin
    Ivan Zhekov avatar
    646 posts

    Posted 29 Dec 2017 Link to this post

    Hello, Marc.

    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
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  8. Marc
    Marc avatar
    123 posts
    Member since:
    Jul 2010

    Posted 03 Jan in reply to Ivan Zhekov Link to this post

    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.

  9. Marc
    Marc avatar
    123 posts
    Member since:
    Jul 2010

    Posted 03 Jan in reply to Marc Link to this post

    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;
        }
    }

     

     

  10. Stefan
    Admin
    Stefan avatar
    2056 posts

    Posted 05 Jan Link to this post

    Hello, Marc,

    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
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  11. Marc
    Marc avatar
    123 posts
    Member since:
    Jul 2010

    Posted 17 Jan Link to this post

    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?

     

     

     

  12. Marc
    Marc avatar
    123 posts
    Member since:
    Jul 2010

    Posted 17 Jan in reply to Marc Link to this post

    Reproduced here: http://dojo.telerik.com/@md1037/AWADA/5

     

     

  13. Stefan
    Admin
    Stefan avatar
    2056 posts

    Posted 18 Jan Link to this post

    Hello, Marc,

    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
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  14. Marc
    Marc avatar
    123 posts
    Member since:
    Jul 2010

    Posted 18 Jan Link to this post

    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?

  15. Marc
    Marc avatar
    123 posts
    Member since:
    Jul 2010

    Posted 18 Jan Link to this post

    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);
  16. Stefan
    Admin
    Stefan avatar
    2056 posts

    Posted 22 Jan Link to this post

    Hello, Marc,

    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
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Back to Top