Grids are a powerful tool for encapsulating tables of data and displaying the entire table or a single row. Grids support multiple data types including Text, CheckBoxes, Picklists, and Images. In this article we will discuss how to add Images to a grid. For more information on general Grid usage, please refer to How do I add items to a grid?


Consider the following form which contains a grid of car information. When the "Add Car" button is pressed, a new entry is added to the grid containing values from the form.



The client script corresponding to this form is as follows. The grid is initialized in the form's EH_AfterOpen() handler, and the Add Car button is handled in EH_HotspotPressed(). When the button is pressed, values from the form fields are used to add a new row to the grid.


// Triggered when the form is opened
function EH_AfterOpen() {
     //set grid columns
    _form.gridColumnData("CarGrid", ["Make and Model", "Year", "Price"]);
    _form.gridDescriptiveColumn("CarGrid", "Make and Model");
    
    //set grid column properties
    _form.gridColumnProperties("CarGrid", 0, { Width: { Width: 150, Type: "Pixels", Automatic: false }, Type: "Text" });
    _form.gridColumnProperties("CarGrid", 1, { Width: { Width: 50, Type: "Pixels", Automatic: false }, Type: "Text" });
    _form.gridColumnProperties("CarGrid", 2, { Width: { Width: 70, Type: "Pixels", Automatic: false }, Type: "Text" });

    //initial data
    _form.gridRowData("CarGrid", [["Honda Civic", "1993", "$5,000"], ["Ford F150", "2019", "$35,000"], ["Chevy Camaro", "2010", "$15,000"]]);
}

// Triggered when a hotspot is pressed
function EH_HotspotPressed(fieldName) {
    if (fieldName == "AddCar") {
        //get new car values from form
        var makeAndModel = _form.getValue("MakeAndModel");
        var year = _form.getValue("Year");
        var price = _form.getValue("Price");

        //add new row to grid
        var rowId = _form.addGridRow("CarGrid");

        //set values in new row
        var carData = _form.gridRowData("CarGrid");
        _form.editGridCellValue("CarGrid", rowId, 0, makeAndModel);
        _form.editGridCellValue("CarGrid", rowId, 1, year);
        _form.editGridCellValue("CarGrid", rowId, 2, price);
    }
}



Adding an image column to the grid follows a similar pattern. The column properties for the new column must specify Image as its Type.


    _form.gridColumnProperties("CarGrid", 3, { Width: { Width: 70, Type: "Pixels", Automatic: false }, Type: "Image", ImageHeight: "30", ImageWidth: "30" });


The image itself can come from any source; for this example add an ImageAnnotation field to the form to allow the user to select an image from their client device.



Finally, in the event handler for the Add Car button add the necessary code to retrieve the image data from the ImageAnnotation field and add it to the appropriate grid column.


        if (_form.hasImage("CarImage")) {
            _form.imageGetContent("CarImage", { index: 0, includeInk: false })
            .then(function(img) {

                var MIME_TYPE_PNG = "data:image/png;base64,";
                if (img.startsWith(MIME_TYPE_PNG)) {
                    img = img.substring(MIME_TYPE_PNG.length);
                }

                _form.editGridCellValue("CarGrid", rowId, 3, img);
            });
        }


A few notes about this code snippet. First, make sure to check if the ImageAnnotation field has an image. If no image has been selected, the call to _form.imageGetContent() will return null and an exception will be thrown when attempting to call .then(). Also, the call to imageGetContent() is asynchronous and returns a promise, therefore a .then() clause must be used to process the result. When the image data is returned, an additional step of stripping off the png header must be performed, and then the raw image data can be added to the grid cell.


The final, full script code is as follows:


// Triggered when the form is opened
function EH_AfterOpen() {
     //set grid columns
    _form.gridColumnData("CarGrid", ["Make and Model", "Year", "Price", "Thumbnail"]);
    _form.gridDescriptiveColumn("CarGrid", "Make and Model");
    
    //set grid column properties
    _form.gridColumnProperties("CarGrid", 0, { Width: { Width: 150, Type: "Pixels", Automatic: false }, Type: "Text" });
    _form.gridColumnProperties("CarGrid", 1, { Width: { Width: 50, Type: "Pixels", Automatic: false }, Type: "Text" });
    _form.gridColumnProperties("CarGrid", 2, { Width: { Width: 70, Type: "Pixels", Automatic: false }, Type: "Text" });
    _form.gridColumnProperties("CarGrid", 3, { Width: { Width: 70, Type: "Pixels", Automatic: false }, Type: "Image", ImageHeight: "30", ImageWidth: "30" });

    //initial data
    _form.gridRowData("CarGrid", [["Honda Civic", "1993", "$5,000"], ["Ford F150", "2019", "$35,000"], ["Chevy Camaro", "2010", "$15,000"]]);
}

// Triggered when a hotspot is pressed
function EH_HotspotPressed(fieldName) {
    if (fieldName == "AddCar") {
        //get new car values from form
        var makeAndModel = _form.getValue("MakeAndModel");
        var year = _form.getValue("Year");
        var price = _form.getValue("Price");

        //add new row to grid
        var rowId = _form.addGridRow("CarGrid");

        //set values in new row
        var carData = _form.gridRowData("CarGrid");
        _form.editGridCellValue("CarGrid", rowId, 0, makeAndModel);
        _form.editGridCellValue("CarGrid", rowId, 1, year);
        _form.editGridCellValue("CarGrid", rowId, 2, price);

        if (_form.hasImage("CarImage")) {
            _form.imageGetContent("CarImage", { index: 0, includeInk: false })
            .then(function(img) {

                var MIME_TYPE_PNG = "data:image/png;base64,";
                if (img.startsWith(MIME_TYPE_PNG)) {
                    img = img.substring(MIME_TYPE_PNG.length);
                }

                _form.editGridCellValue("CarGrid", rowId, 3, img);
            });
        }
    }
}



After adding a new car with image to the grid, the form and its grid contents appear as follows: