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

Update a read-only column with value while editing

14 Answers 789 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Shafi
Top achievements
Rank 1
Shafi asked on 07 Jun 2016, 06:53 PM

Hi!

I've setup a pure client side grid that does non-batch CRUD on a local array. There is a dropdown cascading involved. After selecting Terminal, the list of Services is filtered. The data that is received for this list by ajax contains the fee of that service. I want that fee value to be taken an update the current new/edit row's fee cell in grid after the selection. Here is what I have so far:

The Grid and supporting functionality:

var terminals = [];
var services = [];
 
var kendoDataSource = new kendo.data.DataSource({
    data: createRandomData(),
    pageSize: 5,
    schema: {
        model: {
            id: "ParkingServiceId",
            fields: {
                ParkingServiceId: { type: 'number', editable: false },
                TerminalId: { type: 'number', validation: { required: true } },
                ServiceId: { type: 'number', validation: { required: true } },
                ParkingCardNumber: { type: 'string' },
                ParkingCardIssueDate: { type: 'date', validation: { required: true } },
                ParkingCardExpiryDate: { type: 'date', validation: { required: true } },
                ParkingCardGroup: { type: 'string' },
                ServiceFee: { type: 'number', validation: { min: 0, required: true } }
            }
        }
    }
});
 
var gridMain = $("#serviceDetailsGrid").kendoGrid({
    dataSource: kendoDataSource,
    pageable: false,
    sortable: false,
    toolbar: ["create"],
    columns:
    [
        { field: "ParkingServiceId", width: 90, title: "Id", hidden: true },
        { field: "TerminalId", width: 130, title: "Terminal", template: getTerminalTitle, editor: terminalDropDownEditor },
        { field: "ServiceId", title: "Service", template: getServiceTitle, editor: serviceDropDownEditor },
        { field: "ParkingCardNumber", width: 100, title: "Card #" },
        { field: "ParkingCardIssueDate", width: 112, title: "Issued On", format: "{0:dd-MMM-yyyy}", template: "#= kendo.toString(kendo.parseDate(ParkingCardIssueDate, 'dd-MMM-yyyy'), 'MM/dd/yyyy') #" },
        { field: "ParkingCardExpiryDate", width: 112, title: "Expiry", format: "{0:dd-MMM-yyyy}", template: "#= kendo.toString(kendo.parseDate(ParkingCardExpiryDate, 'dd-MMM-yyyy'), 'MM/dd/yyyy') #" },
        { field: "ServiceFee", editable: false, width: 100, title: "Fee" },
        { command: ["edit", "destroy"], title: " ", width: "200px" }
    ],
    editable: "inline",
    cancel: function (e) { $('#serviceDetailsGrid').data('kendoGrid').dataSource.cancelChanges(); }
}).data("kendoGrid");
 
function createRandomData() {
    var data = [];
 
    data.push({
        ParkingServiceId: 1,
        TerminalId: 0,
        ServiceId: 54,
        ParkingCardNumber: 'CARD113',
        ParkingCardIssueDate: parseDateMonthStyle('01-May-16'),
        ParkingCardExpiryDate: parseDateMonthStyle('01-May-17'),
        ParkingCardGroup: 'SomeText1',
        ServiceFee: 940
    });
    data.push({
        ParkingServiceId: 2,
        TerminalId: 1,
        ServiceId: 164,
        ParkingCardNumber: 'CARD114',
        ParkingCardIssueDate: parseDateMonthStyle('01-May-16'),
        ParkingCardExpiryDate: parseDateMonthStyle('01-Nov-16'),
        ParkingCardGroup: 'SomeText2',
        ServiceFee: 470
    });
    data.push({
        ParkingServiceId: 3,
        TerminalId: 2,
        ServiceId: 1554,
        ParkingCardNumber: 'CARD115',
        ParkingCardIssueDate: parseDateMonthStyle('01-May-16'),
        ParkingCardExpiryDate: parseDateMonthStyle('01-Aug-16'),
        ParkingCardGroup: 'SomeText3',
        ServiceFee: 235
    });
 
    return data;
}
 
function getTerminalOffline() {
    return terminals;
}
 
function setTerminalOffline(setter) {
    console.log("Terminals from cache: " + setter.length);
    terminals = setter;
}
 
function getServiceOffline() {
    return services;
}
 
function setServiceOffline(setter) {
    console.log("Services from cache: " + setter.length);
    services = setter;
}
 
function filterServices(filter) {
    var temp = [];
 
    $.each(getServiceOffline(), function () {
        if ($(this).text.indexOf(filter) > 0) { temp.push($(this)); }
    });
 
    return temp;
}

function getTerminalTitle(container, options) {
    var terminalId = container.TerminalId;
 
    for (var i = 0; i < getTerminalOffline().length; i++) {
        if (getTerminalOffline()[i].TerminalId === terminalId) {
            return getTerminalOffline()[i].TerminalName;
        }
    }
 
    return 'N/A (' + getTerminalOffline().length + ")";
}
 
function getServiceTitle(container, options) {
    var serviceId = container.ServiceId;
 
    for (var i = 0; i < getServiceOffline().length; i++) {
        if (getServiceOffline()[i].Code === serviceId) {
            return getServiceOffline()[i].NameEnglish;
        }
    }
 
    return 'N/A (' + getServiceOffline().length + ")";
}
 
function refreshGrid() {
    gridMain.dataSource.read();
    gridMain.refresh();
}
 
$(function () {
    $.post("/Ajax/GetTerminalsCache")
      .done(function (response) {
          if (response.length > 0) {
              setTerminalOffline(response);
 
              $.post("/Ajax/GetAllServicesCache")
                .done(function (response) {
                    if (response.length > 0) {
                        setServiceOffline(response);
                        refreshGrid();
                    }
                })
                .fail(function (err) {
                    console.log(err);
                });
          }
      })
      .fail(function (err) {
          console.log(err);
      });
});

The OnChange events:

function terminalDropDown_OnChange() {
    var companyId = $("#CompanyId").val();
    var terminalId = $("input[id^='terminalsDropDownList']").data("kendoDropDownList").value();
    var serviceDdl = $("input[id^='servicesDropDownList']").data("kendoDropDownList");
 
    serviceDdl.value("");
 
    $.post("/Ajax/GetTerminalServices", { companyId: companyId, terminalId: terminalId })
        .done(function (response) {
            if (response.length > 0) {
                serviceDdl.setDataSource(response);
            }
        })
        .fail(function (err) {
            console.log(err);
        });
}

function serviceDropDown_OnChange(a) {
    var serviceDropDown = $("input[id^='servicesDropDownList']").data("kendoDropDownList");
    var extract = serviceDropDown.dataItem(serviceDropDown.select());
    // I have the fee at extract.Fee
}

The above code for terminals updates the services and I'm able to extract Fee from the dataItem of service. Now I want to update the grid current row which can be the first row in case of new record or current edit row. Once I have the the row, I need to access it's dataItem and update the ServiceFee column.

Issues/questions:

  1. (How to) Even after setting the ServiceFee column of the grid to be not editable, it still is editable
  2. (How to) After going through a lot of questions, all ways to access the current/selected/editing row of grid have failed for me. I'm not able to get the row I want and calling dataItem on what I get results in undefined
  3. Once #2 is solved, is it simple enough to set the grid's current row's dataItem's ServiceFee to Fee?

 

14 Answers, 1 is accepted

Sort by
0
Kostadin
Telerik team
answered on 09 Jun 2016, 02:10 PM
Hello,

In order to prevent editing of some filed you can set editable to false in the kendo datasource mode.
model: {
    id: "ParkingServiceId",
    fields: {
        ParkingServiceId: { type: 'number', editable: false },
        TerminalId: { type: 'number', validation: { required: true } },
        ServiceId: { type: 'number', validation: { required: true } },
        ParkingCardNumber: { type: 'string' },
        ParkingCardIssueDate: { type: 'date', validation: { required: true } },
        ParkingCardExpiryDate: { type: 'date', validation: { required: true } },
        ParkingCardGroup: { type: 'string' },
        ServiceFee: { type: 'number', validation: { min: 0, required: true }, editable: false }
    }
}

Regards your second question I was unable to understand on which event you are trying to access the data item values. Generally you can hook Edit command which will be fired for both insert and edit, so you can use it to access the dataitem and its values. Please check out the following code snippet.
edit:function(e){ var productName = e.model.ProductName)},

If your requirement differs I would appreciate if you can share more information.

Regards,
Kostadin
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Shafi
Top achievements
Rank 1
answered on 10 Jun 2016, 11:42 AM

I'll test the editable: false in datasource schema as well.

The second question is that if you look at my full code above, this is what I'm trying to achieve:

User selects a terminal and the services dropdown gets populated. The JSON that populates the services dropdown contains a field Fee that I want to pick and use it's value for the ServiceFee of the grid/datasource column for a row currently being edited/inserted.

0
Shafi
Top achievements
Rank 1
answered on 14 Jun 2016, 06:11 AM

The editable: false in datasource schema has worked nicely.

The second part of the question is still an open issue for me. Any prompt reply will be greatly appreciated.

0
Kostadin
Telerik team
answered on 14 Jun 2016, 10:39 AM
Hi Shafi,

As far as I understand you want to access a Fee fields when editing or inserting a new rows. In such case you can try using the Edit event as mentioned in my previous reply. Additionally you can examine the following sample which elaborates more on Access Editor Controls in Edit Events.

Regards,
Kostadin
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Shafi
Top achievements
Rank 1
answered on 15 Jun 2016, 05:35 AM

Following you link, I was able to hook into the edit event and was able to get a DropDownList and the grid's current model. I was able to manually set the grid model's ServiceFee to a value and it reflected.

Now, the issue: There are two dropdowns. And the mentioned code selects the first one:

var serviceDropDownList = container.find("[data-role=dropdownlist]").data("kendoDropDownList");

How do I select the second dropdown?

0
Shafi
Top achievements
Rank 1
answered on 15 Jun 2016, 08:36 AM

I'm attaching the scenario if there is still confusion.

Issues:

  • I have two DropDownLists
  • DropDownsLists are cascade-locked
  • I need to update the grid's ServiceFee cell EVERY time the selected item in the Service DropDownList is changed

Following the code you mentioned, I see that the edit event triggers once and as soon as row is added. This behavior is not desired as the Terminal DropDownList needs to be changed to trigger the post-back on Service DropDownList.

The process of getting the Fee out of Service DropDownList and updating the current row's model doesn't need to be immediate. If it can be done by hooking the Confirm/Update button, I'm OK with that.

Please help!

0
Kostadin
Telerik team
answered on 16 Jun 2016, 03:41 PM
Hello Shafi,

Keep in mind if the selector that you are using match multiple elements you need to loop through them and access the DropDownList widget by using the data method. Otherwise you will get only the first DropDown on the page.
container.find("[data-role=dropdownlist]").each(function(){
    console.log($(this).data("kendoDropDownList"))
})

In case you need to update a cell based on the DropDownList item you can hook up to the select event of the DropDownList editor and use dataItem (grid), closest (jQuery) and set (model) methods. For example:
select: function() {
    var grid = $("#grid").data("kendoGrid"),
        model = grid.dataItem(this.element.closest("tr"));
 
    model.ProductName = "changed";
}

You can check out the following sample which demonstrates that.

Keep in mind you can use model isNew method to check if the data item is new (created) or not (edited). This way you can execute different logic when inserting or updating an item.

Regards,
Kostadin
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Shafi
Top achievements
Rank 1
answered on 18 Jun 2016, 06:55 PM

Okay, we have almost cracked this one. one last bug: The select event is keeping the last selected value not the current one. So if I make the first selection from "Select service" to a valid value, I get null due to "Select service" being null.

Second case: Make first selection and then make second selection and leave the dropdownlist. The first selection's Fee will reflect and not the current selection.

0
Kostadin
Telerik team
answered on 21 Jun 2016, 01:20 PM
Hi,

In such case you can use a setTimeout function to get the current selected value. Here is a simple code which demonstrates that.
categoryDropDownList.bind("select", function(e){
  var that= this;
  setTimeout(function(){alert(that.selectedIndex)});
})

I hope this information helps.

Regards,
Kostadin
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Shafi
Top achievements
Rank 1
answered on 29 Jun 2016, 12:42 PM

Binding the select event this way didn't trigger at all. Here is what I did:

function serviceDropDownEditor(container, options) {
    var serviceDropDown =
        $('<input id="servicesDropDownList" required data-text-field="NameEnglish" data-value-field="Code" data-bind="value:' + options.field + '"/>')
            .appendTo(container)
            .kendoDropDownList({
                optionLabel: "Select service...",
                autobind: false,
                dataTextField: "NameEnglish",
                dataValueField: "Code"
            });
 
    serviceDropDown.bind("select",
        function() {
            var that = this;
            setTimeout(function() {
                var extract = that.dataItem(serviceDropDown.select());
                var model = gridMain.dataItem(that.element.closest("tr"));
 
                model.ServiceFee = extract.Fee;
            }, 100);
        });
}

And I also added a 100 ms timeout as well. Still need help.

0
Kostadin
Telerik team
answered on 01 Jul 2016, 07:52 AM
Hi,

In case you are hooking the event in the editor template you can directly attach the event to the dropdown. Please try using the following code.
function serviceDropDownEditor(container, options) {
    var serviceDropDown =
        $('<input id="servicesDropDownList" required data-text-field="NameEnglish" data-value-field="Code" data-bind="value:' + options.field + '"/>')
            .appendTo(container)
            .kendoDropDownList({
                optionLabel: "Select service...",
                autobind: false,
                dataTextField: "NameEnglish",
                dataValueField: "Code",
                select: function() {
                    var that = this;
                    setTimeout(function() {
                        var extract = that.dataItem(serviceDropDown.select());
                        var model = gridMain.dataItem(that.element.closest("tr"));
          
                        model.ServiceFee = extract.Fee;
                    }, 100);
                });
            });
}

Here is a sample which demonstrates this approach.

Regards,
Kostadin
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Shafi
Top achievements
Rank 1
answered on 11 Jul 2016, 12:17 PM

Hello again!

var extract = that.dataItem(serviceDropDown.select())

Is not returning the correct data model. In fact, it always selects an invalid entry. I have attached an image showing this.

0
Accepted
Kostadin
Telerik team
answered on 13 Jul 2016, 07:55 AM
Hi Shafi,

You can use the following approach to access the selected item.
var extract = that.dataItem(that.selectedIndex);

I hope this information helps.

Regards,
Kostadin
Telerik by Progress
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Shafi
Top achievements
Rank 1
answered on 13 Jul 2016, 04:30 PM
That did it! Thanks!
Tags
Grid
Asked by
Shafi
Top achievements
Rank 1
Answers by
Kostadin
Telerik team
Shafi
Top achievements
Rank 1
Share this question
or