Setting cell as edited (red marker)

8 posts, 0 answers
  1. Russell
    Russell avatar
    3 posts
    Member since:
    Jul 2016

    Posted 18 Nov 2016 Link to this post

    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);
        }
    }
  2. Konstantin Dikov
    Admin
    Konstantin Dikov avatar
    2466 posts

    Posted 22 Nov 2016 Link to this post

    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.
  3. Russell
    Russell avatar
    3 posts
    Member since:
    Jul 2016

    Posted 24 Nov 2016 Link to this post

    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);
        }
     
    }
  4. Konstantin Dikov
    Admin
    Konstantin Dikov avatar
    2466 posts

    Posted 28 Nov 2016 Link to this post

    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.
  5. Matt
    Matt avatar
    3 posts
    Member since:
    Oct 2016

    Posted 04 Feb 2018 Link to this post

    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

     

  6. Konstantin Dikov
    Admin
    Konstantin Dikov avatar
    2466 posts

    Posted 06 Feb 2018 Link to this post

    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.
  7. Matt
    Matt avatar
    3 posts
    Member since:
    Oct 2016

    Posted 07 Feb 2018 in reply to Konstantin Dikov Link to this post

    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

  8. Stefan
    Admin
    Stefan avatar
    2821 posts

    Posted 09 Feb 2018 Link to this post

    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.
Back to Top