This is a migrated thread and some comments may be shown as answers.

Setting cell as edited (red marker)

7 Answers 431 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Russell
Top achievements
Rank 1
Russell asked on 18 Nov 2016, 09:34 PM

I am updating a grid cell with a date value on a button click from a custom command in the row (see code below).  I am able to successfully add the value to the cell but I would like to have the cell show the red triangle in the upper left corner (see attached pic) that shows the user the value in the cell has been edited.

function activate_deactivate(e) {
    e.preventDefault();
    var tr = $(e.target).closest("tr"); //get the row
    var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
    var data = this.dataItem(tr); //get the row data so it can be referred later
 
    var ad = dataItem.ActivatedOn;
 
    if (isDateActive(dataItem.ActivatedOn, dataItem.DeactivatedOn) || !dataItem.DeactivatedOn)
    {
        //set the deactivated date
        var strTodaysDate = getShortDate();
        data.set("DeactivatedOn", strTodaysDate);
    }
    else
    {
        //clear the deactivated date (Now Active)
        data.set("DeactivatedOn", null);
    }
}

7 Answers, 1 is accepted

Sort by
0
Konstantin Dikov
Telerik team
answered on 22 Nov 2016, 01:38 PM
Hello Russel,

You can either manually add the dirty indicator the edited cell (by appending the span element used for the indicator) or call the following method after changing the value:
var grid = $("#grid").data("kendoGrid");
grid._modelChange({field:"ProductName", model: grid.dataSource.view()[0]}) //grid.dataSource.view()[0] should be replaced with the model you are editing

On a side note, please have in mind that the correct way of changing values is through the set method of the model: dataItem.set("fieldName", value);

Hope this helps.


Regards,
Konstantin Dikov
Telerik by Progress
Telerik UI for ASP.NET MVC is ready for Visual Studio 2017 RC! Learn more.
0
Russell
Top achievements
Rank 1
answered on 25 Nov 2016, 04:49 AM

I am using the data.set method in my code (see below) but the dirty flag is not being displayed.  Do I need to do more to show the dirty flag?

function activate_deactivate(e) {
    e.preventDefault();
    var tr = $(e.target).closest("tr"); //get the row
    var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
    var data = this.dataItem(tr); //get the row data so it can be referred later
 
    var ad = dataItem.ActivatedOn;
 
    if (isDateActive(dataItem.ActivatedOn, dataItem.DeactivatedOn) || !dataItem.DeactivatedOn)
    {
        //set the deactivated date
        var strTodaysDate = getShortDate();
        data.set("DeactivatedOn", strTodaysDate);
    }
    else
    {
        //clear the deactivated date (Now Active)
        data.set("DeactivatedOn", null);
    }
 
}
0
Konstantin Dikov
Telerik team
answered on 28 Nov 2016, 11:25 AM
Hello Russell,

The set method should be used in combination with manually appending the span element for the dirty flag to the cell:
<span class='k-dirty'></span>

You can refer to the following example for manually adding a dirty flag (although it is a different requirement, you can have it as a reference):
However, using the private _modelChange method should handle the changing of the value and the appending of the dirty flag, so I would suggest that you test that approach first and see if everything will work as expected with it.


Regards,
Konstantin Dikov
Telerik by Progress
Telerik UI for ASP.NET MVC is ready for Visual Studio 2017 RC! Learn more.
0
Matt
Top achievements
Rank 1
answered on 04 Feb 2018, 08:35 PM

Konstantin,

I was able to get an editable, sortable drop down for the ticket that we had discussed recently. (I ended up finding some time to delve further.)

I found this link:

http://jsbin.com/itevab/2/edit?html,js,output

very helpful in constructing the solution.

I came across that link from this link: 

https://www.telerik.com/forums/kendo-grid---sort-on-column-bound-to-an-object

 

I was also able to get the dirty flag to appear using the manual append suggestion and the link you had provided

(https://docs.telerik.com/kendo-ui/controls/data-management/grid/how-to/Editing/preserve-the-dirty-indicator-in-incell-editing-and-client-operations?_ga=2.109639621.1731990048.1517769467-579472094.1515537534)

Thank you for that!

Just for a deeper understanding and to explore another option, I was wondering if you could clarify the _modelChange option. I don't understand what how to replace "grid.dataSource.view()[0]" with the model that I am editing.

I included my attempt do so within my update function (which appears within my editor template file):

@model object
 
<script type="text/javascript">
    function parentChange(e) {
        $("#childGrid").data("kendoGrid").dataItem(this.element.closest("tr")).set("ParentDropDown", this.dataItem().ToJson());
        //var grid = $("#childGrid").data("kendoGrid");
        //grid._modelChange({ field: "ParentDropDown", model: grid.dataSource.view()[0]});
        if (e.action == "itemChange") {
            e.items[0].dirtyFields = e.items[0].dirtyFields || {};
            e.items[0].dirtyFields[e.field] = true;
       }
    }
</script>
 
@(Html.Kendo().DropDownListFor(m => m)
    .Name("ParentDropDown")
    .Events(c => c.Change("parentChange"))
    .DataValueField("ParentID")
    .DataTextField("ParentName")
    .DataSource(dataSource => dataSource
        .Read(read =>
        {
            read.Action("ParentDropDownRead", "MultiBillTo");
        })
        .ServerFiltering(true)
    )
)

 

Here is my grid with the javascript function for adding the dirty edit flag.

<script type="text/javascript">
    function dirtyField(data, fieldName) {
        if (data.dirty && data.dirtyFields[fieldName]) {
            return "<span class='k-dirty'></span>";
        }
        else {
            return "";
        }
 
    }
</script>
 
@(Html.Kendo().Grid<LDM.WebUI.Areas.Pricing.Models.MultiBillToChildViewModel>()
        .Name("childGrid")
        .Columns(columns =>
        {
            columns.Bound(c => c.ParentDropDown.ParentName)
                 //.HtmlAttributes(new { @class = "templateCell" })
                 .ClientTemplate("#=dirtyField(data, 'ParentDropDown')# #=ParentDropDown.ParentName#")
                 .EditorTemplateName("ParentDropDown")
                 .Title("Parent")
                 .Width(350);
            //columns.ForeignKey(c => c.ParentID, (System.Collections.IEnumerable) ViewData["parentDropDowns"], "ParentID", "ParentName").EditorTemplateName("ParentDropDown");
            //columns.Bound(c => c.ParentDropDownName).Title("Parent").Width(350);
            columns.Bound(c => c.ParentDropDown.ParentName).Title("ParentSortable").Width(350);
            columns.Bound(c => c.CustomerID).Width(100);
            columns.Bound(c => c.CustomerName).Width(350);
            columns.Bound(c => c.ChildNotes).Width(500);
        })
        .DataSource(dataSource => dataSource
            .Ajax()
            .Batch(false)
            .ServerOperation(false)
            .Model(model =>
            {
                model.Id(c => c.RowID);
                //model.Field(c => c.ParentDropDown).DefaultValue(ViewData["defaultDropDown"]);
                //model.Field(c => c.ParentID).DefaultValue(ViewData["defaultDropDown"]);
                model.Field(c => c.ParentDropDown).DefaultValue(ViewData["defaultDropDown"]);
                model.Field(c => c.ParentDropDown).Editable(true);
            })
            .PageSize(50)
            .Create(create => create.Action("MultiBillToChildrenCreate", "MultiBillTo"))
            .Read(read => read.Action("MultiBillToChildrenRead", "MultiBillTo"))
            .Update(update => update.Action("MultiBillToChildrenUpdate", "MultiBillTo"))
            .Destroy(destroy => destroy.Action("MultiBillToChildrenDelete", "MultiBillTo"))
            .Sort(sort =>
            {
                //sort.Add(c => c.ParentDropDown.ParentName);
                sort.Add(c => c.ParentDropDown.ParentName);
            }
            )
        )
        .Editable(editable => editable.Mode(GridEditMode.InCell))
        .Excel(excel => excel
            .FileName("MultiBillToChildren.xlsx")
            .ProxyURL(Url.Action("ExcelExportSave", "MultiBillTo"))
        )
        .Filterable()
        .HtmlAttributes(new { style = "height:600px;" })
        .Pageable()
        .Scrollable()
        .Sortable(s => s.AllowUnsort(false))
        .ToolBar(toolbar =>
        {
            toolbar.Create();
            toolbar.Save();
            toolbar.Excel();
        }
        )
)

 

I commented out my attempt to use _modelChange after I could not get it to work and switched to the manual append method.

Could you please provide additional detail on the _modelChange option?

Thank you,

Matt Pugsley

 

0
Konstantin Dikov
Telerik team
answered on 06 Feb 2018, 10:18 AM
Hello Matt,

With the latest version you could use the "set" method and it will add the dirty indicator internally:
As for the currently edited dataItem, this is the line that get reference to the item:
var currentItem = $("#childGrid").data("kendoGrid").dataItem(this.element.closest("tr"));

Nevertheless, since the _modelChange is a private method I would not recommend using it, because it could change over time and it is not part of the public API where we are trying to avoid breaking changes. 

Hope this helps.


Regards,
Konstantin Dikov
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.
0
Matt
Top achievements
Rank 1
answered on 07 Feb 2018, 03:34 PM

Konstantin,

I think I understand. Can you please confirm the below?

1. Because the dirty indicator is set internally, the first block below can be replaced with the second:

// first block
$("#childGrid").data("kendoGrid").dataItem(this.element.closest("tr")).set("ParentDropDown", this.dataItem().ToJson());
        if (e.action == "itemChange") {
            e.items[0].dirtyFields = e.items[0].dirtyFields || {};
            e.items[0].dirtyFields[e.field] = true;
        }
 
// second block
$("#childGrid").data("kendoGrid").dataItem(this.element.closest("tr")).set("ParentDropDown", this.dataItem().ToJson());

 

2. But I still need to include a check for the dirty flag and append the dirty flag class in the UI:

.ClientTemplate("#=dirtyField(data, 'ParentDropDown')# #=ParentDropDown.ParentName#")
 
 
// where dirtyField is a javascript function:
function dirtyField(data, fieldName) {
        if (data.dirty && data.dirtyFields[fieldName]) {
            return "<span class='k-dirty'></span>";
        }
        else {
            return "";
        }
 
}

 

My testing accorded with the above results, as I was able to remove the setting of the dirty flag, but I still needed the javascript function and the addition to the client template to show the dirty flag. (Since I am binding directly to ParentDropDown.ParentName, I also tried removing any reference to a client template, thinking that perhaps ".ClientTemplate("#=ParentDropDown.ParentName#")" was overriding a dirty flag class that was being included. But no such luck. The drop down did display and function properly without a call to .ClientTemplate() (at least, it appeared so), but the dirty flag indicator did not appear. It was only by including the extra "#=dirtyField(data, 'ParentDropDown')#" that I could see the dirty flag indicator.

Is the above correct?

Thanks,

Matt

0
Stefan
Telerik team
answered on 09 Feb 2018, 07:48 AM
Hello, Matt,

I will take over the ticket as my colleague Konstantin is away.

I went over the communication and can confirm that the suggested approach by my colleagues could replace the original logic. Also, the ClientTemplate is needed as well in order to call the function.

If the flag has to be added via CSS(and HTML) based on the code I can assume that the model modification and setting the flag visually can be done together in the same function without the need of a separate one. Instead of returning only the span I can suggest returning the span and the value of the DropDown and only the value if the condition is not met.

If this is not possible, please provide an example demonstrating the issue and we will gladly provide a suggestion best suited for it.

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.
Tags
Grid
Asked by
Russell
Top achievements
Rank 1
Answers by
Konstantin Dikov
Telerik team
Russell
Top achievements
Rank 1
Matt
Top achievements
Rank 1
Stefan
Telerik team
Share this question
or