how do i conditional set the visibility of the Command.Edit button on a row by row basis?

2 Answers 6365 Views
Grid
Atlas
Top achievements
Rank 1
Atlas asked on 30 Mar 2013, 12:03 AM

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?

ManniAT
Top achievements
Rank 2
commented on 10 Aug 2015, 10:25 PM

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

Dimiter Madjarov
Telerik team
commented on 11 Aug 2015, 10:59 AM

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
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
ManniAT
Top achievements
Rank 2
commented on 12 Aug 2015, 01:05 PM

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

ManniAT
Top achievements
Rank 2
commented on 12 Aug 2015, 01:30 PM

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...

Dimiter Madjarov
Telerik team
commented on 12 Aug 2015, 04:33 PM

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
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
Jared
Top achievements
Rank 2
commented on 28 Jan 2016, 09:20 PM

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.  

Nick
Top achievements
Rank 1
commented on 29 Jan 2016, 07:47 AM

[quote]Jared said:

 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.

 

Dimiter Madjarov
Telerik team
commented on 29 Jan 2016, 12:10 PM

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
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
Jared
Top achievements
Rank 2
commented on 29 Jan 2016, 03:53 PM

I agree with you guys and I already have this validation in place.  Both in the code click button and server-side.  But my question still remains.  Can you do more than just hide the button?  
Dimiter Madjarov
Telerik team
commented on 29 Jan 2016, 04:23 PM

Hello Jared,

Could you elaborate what exactly are you trying to achieve which is different, than the described approach?

Regards,
Dimiter Madjarov
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
Jared
Top achievements
Rank 2
commented on 29 Jan 2016, 04:27 PM

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.  

Dimiter Madjarov
Telerik team
commented on 29 Jan 2016, 04:44 PM

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.

I hope this information helps. Have a great weekend!

Regards,
Dimiter Madjarov
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 

2 Answers, 1 is accepted

Sort by
0
Dimiter Madjarov
Telerik team
answered on 01 Apr 2013, 09:30 AM
Hi Atlas,


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
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
Nick
Top achievements
Rank 1
commented on 30 May 2013, 03:54 PM

Ouch!  So I can't just put in a lambda to determine this?  Can I request this to be changed?   I'd love to be able to do something like this...
@(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
Dimiter Madjarov
Telerik team
commented on 31 May 2013, 08:38 AM

Hello 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
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
Tyrone
Top achievements
Rank 1
commented on 12 Sep 2014, 06:39 PM

Any idea why this would not work... after putting some console.log statements in, this code is executing down to the point of the hide.  It find the edit button, but when asked to hide the button, it does not.  Could this have to do with lockable columns?  I tried both putting my buttons in a locked column and an unlocked column, but no luck...
<!-- 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 -->
Dimiter Madjarov
Telerik team
commented on 15 Sep 2014, 10:51 AM

Hello Tyrone,


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
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
Tyrone
Top achievements
Rank 1
commented on 15 Sep 2014, 12:52 PM

I had wanted to use DataBound, but it was not available for use in my razor view.  I do not know why it is not available...
But I do not think that would prevent my buttons from hiding, would it?
Dimiter Madjarov
Telerik team
commented on 15 Sep 2014, 01:13 PM

Hi Tyrone,


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"))
The reason for using it is that the rows are not yet existing in the table before that.

Regards,
Dimiter Madjarov
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
Tyrone
Top achievements
Rank 1
commented on 15 Sep 2014, 01:22 PM

The very simplicity of your questions solved my problem, thank you...
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...
Dimiter Madjarov
Telerik team
commented on 15 Sep 2014, 02:29 PM

Hello Tyrone,


Thanks for the update.

I wish you a great day!

Regards,
Dimiter Madjarov
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
Ziad
Top achievements
Rank 1
commented on 13 Apr 2015, 03:29 PM

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

Dimiter Madjarov
Telerik team
commented on 14 Apr 2015, 08:27 AM

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
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
Maxime
Top achievements
Rank 1
commented on 26 Oct 2016, 02:39 PM

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 ?

Dimiter Madjarov
Telerik team
commented on 27 Oct 2016, 07:41 AM

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.

Regards,
Dimiter Madjarov
Telerik by Progress
 
Build rich, delightful, *native* Angular 2 apps with Kendo UI for Angular 2. Try it out today! Kendo UI for Angular 2 (currently in beta) is a jQuery-free toolset, written in TypeScript, designed from the ground up to offer true, native Angular 2 components.
 
0
Mark
Top achievements
Rank 1
Veteran
answered on 25 Sep 2016, 02:27 PM

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

Tags
Grid
Asked by
Atlas
Top achievements
Rank 1
Answers by
Dimiter Madjarov
Telerik team
Mark
Top achievements
Rank 1
Veteran
Share this question
or