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

Kendo Grid - Display Cell Text, but transport Cell Value

2 Answers 597 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Adrian
Top achievements
Rank 1
Adrian asked on 27 Aug 2012, 10:57 PM
I have a grid with inline editing enabled. The editor template for one column is a ComboBox which is linked to a dataSource containing currency values and descriptions.
/*
    Cost Grid DataSource
*/
var dataCost = new kendo.data.DataSource({
    pageSize: 10,
    transport: commonTransport({
        read: "/ProjectInfo/GetProjectCost",
        rData: { projectId: projectId },
        update: "/ProjectInfo/UpdateProjectCost",
        destroy: "/ProjectInfo/DestroyProjectCost",
        create: "/ProjectInfo/CreateProjectCost",
        cData: { projectId: projectId }
    }),
    schema: {
        type: "json",
        model: {
            id: "projCostId",
            fields: {
                "projCostId": { editable: true, type: "number" },
                "costType": { editable: true, type: "string" },
                "cost": { editable: true, type: "number" },
                "currency": { editable: true, type: "string" }
            }
        }
    }
});
 
var costGridColumns = [
    { "field": "costType", "title": "Description", "filterable": true, "sortable": true, "width": "40%" },
    { "field": "cost", "title": "Cost", "filterable": true, "sortable": true, "width": "30%" },
    { "field": "currency", "title": "Currency", "filterable": true, "sortable": true, "width": "30%", "editor": costGridCurrencyEditor }
],
costGridObject;
 
/*
    Currency ComboBox DataSource
*/
var dataCurrency = new kendo.data.DataSource({
    transport: commonTransport({
        read: "/ProjectInfo/GetCurrency"
    }),
    schema: {
        type: "json",
        model: {
            fields: {
                "currencyCode": { editable: false, type: "string" },
                "currencyDesc": { editable: false, type: "string" }
            }
        }
    }
});
 
var costGridCurrencyComboBox;
function costGridCurrencyEditor(container, options) {
    costGridCurrencyComboBox = $('<input id="costGridCurrency" data-bind="value:' + options.field + '" name="' + options.field + '" style="width:auto" />')
        .appendTo(container)
        .kendoComboBox({
            dataTextField: "currencyDesc",
            dataValueField: "currencyCode",
            filter: "contains",
            dataSource: dataCurrency
        }).data("kendoComboBox");
}
I want to configure this grid so it displays the currency description in the currency column of the table, but the value sent back and forth when editing or adding new rows is the shortened currencyCode (or in another similar instance, a numeric value).  It's easy enough to set up a ComboBox to behave this way, displaying text in the dropdown list, but submitting the value; I just want to get the grid cell functioning the same way.

I have tried to figure out how to use the schema "data" or "parse" options, or the transport "parameterMap" option, but between the documentation, the forums, posted examples, the code library, and Google, I still cannot figure out how to get it to work.

if I use parameterMap(data, operation) {} and try to output the "data" to the console with console.log(data) I receive "undefined", whereas upon returning the data, the grid receives it and operates on it perfectly fine. Because of this, I am unable to ascertain the data structure and figure out how to navigate it and modify it.

With the "data" and "parse" options under schema, there are no functional examples I can use. I found an example of using "parse" to convert a value to a date, but that's all. (here)

Does anyone have any useful examples I may have missed that will help me? Or can anyone explain how to use the "parameterMap" "data" and "parse" functions? It should be simple, but without documentation, it is not.

Thank you.

2 Answers, 1 is accepted

Sort by
0
Adrian
Top achievements
Rank 1
answered on 28 Aug 2012, 08:11 PM
So here's where I'm at right now (I finally figured out how to use the parameterMap, data, and parse methods, no thanks to the documentation or examples):

/*
    Currency ComboBox DataSource
*/
var dataCurrency = new kendo.data.DataSource({
    transport: commonTransport({
        read: "/ProjectInfo/GetCurrency"
    }),
    schema: {
        type: "json",
        model: {
            id: "currencyCode",
            fields: {
                "currencyCode": { editable: false, type: "string" },
                "currencyDesc": { editable: false, type: "string" }
            }
        }
    }
});
 
var costGridCurrencyComboBox;
function costGridCurrencyEditor(container, options) {
    costGridCurrencyComboBox = $('<input id="costGridCurrency" data-bind="value:' + options.field + '" name="' + options.field + '" style="width:auto" />')
        .appendTo(container)
        .kendoComboBox({
            dataTextField: "currencyDesc",
            dataValueField: "currencyDesc",
            filter: "contains",
            dataSource: dataCurrency
        }).data("kendoComboBox");
}
 
/*
    Cost Grid DataSource
*/
var dataCost = new kendo.data.DataSource({
    pageSize: 10,
    transport: commonTransport({
        read: "/ProjectInfo/GetProjectCost",
        rData: { projectId: projectId },
        update: "/ProjectInfo/UpdateProjectCost",
        destroy: "/ProjectInfo/DestroyProjectCost",
        create: "/ProjectInfo/CreateProjectCost",
        cData: { projectId: projectId },
        pMap: function(options, type) { // Handles outgoing grid data
            if (type === "read") return options;
            if (type !== "read") {
                var temp = options;
                // Step 1 - Read currency description from cell:
                var cellContents = temp.currency;
                // Step 2 - Find corresponding currency code:
                dataCurrency.filter({
                    field: "currencyDesc",
                    operator: "eq",
                    value: cellContents
                });
                var outgoing = dataCurrency.view()[0].currencyCode;
                dataCurrency.filter({});
                // Step 3 - Send currency code to server:
                temp.currency = outgoing;
                return temp;
            }
        }
    }),
    schema: {
        type: "json",
        model: {
            id: "projCostId",
            fields: {
                "projCostId": { editable: true, type: "number" },
                "costType": { editable: true, type: "string" },
                "cost": { editable: true, type: "number" },
                "currency": { editable: true, type: "string" }
            }
        },
        parse: function(data) { // Handles incoming grid data
            var temp = data;
            for (var i = 0; i < temp.length; i++) {
                // Step 1 - Receive currency code from server:
                var incoming = temp[i].currency;
                console.log(incoming);
                // Step 2 - Find corresponding currency description:
                dataCurrency.filter({
                    field: "currencyCode",
                    operator: "eq",
                    value: incoming
                });
                console.log(dataCurrency.view());
                 
                    //var cellContents = (typeof(dataCurrency.view()[0]) !== "undefined") ? dataCurrency.view()[0].currencyDesc : "";
                    //dataCurrency.filter({});
                    // Step 3 - Output currency description to cell:
                    //temp[i].currency = cellContents;
                //}
            }
            return temp;
        }
    }
});
 
var costGridColumns = [
    { "field": "costType", "title": "Description", "filterable": true, "sortable": true, "width": "40%" },
    { "field": "cost", "title": "Cost", "filterable": true, "sortable": true, "width": "30%" },
    { "field": "currency", "title": "Currency", "filterable": true, "sortable": true, "width": "30%", "editor": costGridCurrencyEditor }
],
costGridObject;

The problem I'm having this time is that the dataCurrency.filter({}) within dataCost's parse method is returning an empty array when I call dataCurrency.view(). If, from the browser's JavaScript console, I apply the very same filter (manually inputting "USD" in the value of the filter) and call dataCurrency.view(), I receive the expected output:

// Input into console:
dataCurrency.filter({field:"currencyCode",operator:"eq",value:"USD"});
dataCurrency.view()
 
// Output from console:
[{_events:{change:[(function (a){c.trigger(w,{field:a.field,node:a.node,index:a.index,items:a.items||[this],action:a.action||"itemchange"})})]}, currencyCode:"USD", currencyDesc:"US Dollar", uid:"6656ecbe-b915-4335-a042-63c841ee77d1", dirty:false, id:"USD", parent:(function (){return c})}]

I suspect there's some kind of timing issue involved here -- that the dataCurrency dataSource simply hadn't finished loading its data set by the time it's being called upon within the parse method of the dataCost dataSource -- but I have no solid answers, nor any ideas for a workaround. I've tried using the setTimeout zero trick and I've tried chaining them using the dataSource change event to ensure they load in the appropriate order, but neither achieved the desired result, which is to translate the currencyCode ("USD", "GBP", etc.) to its corresponding currencyDesc ("US Dollars", "British Pounds", etc.) for display in the grid (which it would translate back to currencyCode when submitting a create, update, or destroy via the parameterMap method). This is perhaps the least-important usage for this technique, but I have several places where a string value is linked to an int key in the database (and stored as such to ensure consistency), and as a result, is displayed as a numeric value in the Grid. I need to be able to convert it to its corresponding string for display in the Grid, and back to an int in the case of any create or update events.

Can anyone help me out here? I think I can safely say I've gone beyond the boundaries of the documentation and examples, and require professional (or knowledgeable) assistance.
0
Adrian
Top achievements
Rank 1
answered on 28 Aug 2012, 09:19 PM
I changed my parse function to the following:

parse: function(data) { // Handles incoming grid data
    var temp = data;
    dataCurrency.read();
    for (var i = 0; i < temp.length; i++) {
        // Step 1 - Receive currency code from server:
        var incoming = temp[i].currency;
        console.log(incoming);
        // Step 2 - Find corresponding currency description:
        dataCurrency.filter({
            field: "currencyCode",
            operator: "eq",
            value: incoming
        });
        console.log(dataCurrency.view());
        var cellContents = (dataCurrency.view().length > 0) ? dataCurrency.view()[0].currencyDesc : "";
        dataCurrency.filter({});
        // Step 3 - Output currency description to cell:
        temp[i].currency = cellContents;
 
    }
    return temp;
}

The grid loads with blank fields in the Currency column. If I specifically invoke dataCost.read() after the grid loads, then the dataCurrency dataSource is available, and the fields in the Currency column of the dataCost grid finally populate with the corresponding values. This is all well and good, but I should not have to manually invoke another read operation. Is there some other, more elegant way to achieve this that I'm missing?
Tags
Grid
Asked by
Adrian
Top achievements
Rank 1
Answers by
Adrian
Top achievements
Rank 1
Share this question
or