Search code examples
javascriptsapui5

Binding non-boolean values to CheckBox in Table


I am having trouble to bind a String value of 00 and 98 to false and true. I have found quite a few possible solutions but none of them works for me and I don't quite understand why.

Suppose I receive data from a server and create a JSON Model and set that to the table model.

function createTableColumns(columns) {
        var oTable = sap.ui.getCore().byId("mainTable");

        var statusTemplate = new sap.ui.commons.CheckBox({
            editable: false,
            // THIS WAS MY FIRST ATTEMPT TO GET IT WORKING
            //checked: {
            //    path: "{TableModel>status}",
            //    formatter: function(val) {
            //        console.log(val);
            //        return val === "98";
            //    }
            //}
        });

        // SECOND ATTEMPTS, DOESN'T WORK EITHER
        statusTemplate.bindProperty("checked", "{TableModel>status}", function(val) { return val === "98"; });

        for(var i = 0; i < columns.length; i++) {
             oTable.addColumn(new sap.ui.table.Column({
                 label: new sap.ui.commons.Label({text: columns[i]}),
                 name: columns[i],
                 flexible: false,
                 autoResizable: true,
                 template: columns[i] === 'status' ? statusTemplate : new sap.ui.commons.TextView({text: "{TableModel>" + columns[i] + "}"}),
                 sortProperty: columns[i],
                 filterProperty: columns[i],
             }));
        }
    }

Both ways in the code above do not work. I don't know whether it is the logic or whether I am using the model wrong. Every other (TextView) Column displays data to which it is bound... so I believe that the binding is correct!?

I also have tried this way but that doesn't work at all for me: OpenUI5 binding property with a function, instead of direct access I keep on getting the error that "00" is not a valid value for the checkbox.

Am I doing something obviously wrong?

EDIT: Current state

This function is basically called everytime the user switches the table in the application. The old data (rows and columns) will be deleted and filled new. The parameter columns contains an array of strings of the column names! No data is in the data model yet!!!

function createTableColumns(columns) {
    var oTable = sap.ui.getCore().byId("mainTable");

    oTable.destroyColumns();
    sap.ui.getCore().setModel(null, "TableModel");

    var statusCheckBoxTemplate = new sap.ui.commons.CheckBox({
        text: "{TableModel>status}",
        editable: false,
        checked: {
            path: "{TableModel>status}",
            formatter: function(v) {
                console.debug(v);
                if(v === "98") return true;
                else return false;
            }
        }
    });

    for(var i = 0; i < columns.length; i++) {
        if(columns[i] !== 'rowid') {
            oTable.addColumn(new sap.ui.table.Column({
                label: new sap.ui.commons.Label({text: columns[i]}),
                name: columns[i],
                flexible: false,
                autoResizable: true,
                template: columns[i] === 'status' ? statusCheckBoxTemplate : new sap.ui.commons.TextView({text: "{TableModel>" + columns[i] + "}"}),
                sortProperty: columns[i],
                filterProperty: columns[i],
            }));
        }
    }
}

After a user selected a table to display it sits there only displaying the columns. Data is fetched from the server (ajax call) as an JSON object and a data model is created. It all works fine. Data is bound without problems and displayed correctly.

function tableBtnReloadPressed() {
    // ajax call
    var tabledata = readTableData(ACTIVE_TABLE);
    var oModel = new sap.ui.model.json.JSONModel();
    oModel.setData(tabledata);
    sap.ui.getCore().setModel(oModel, "TableModel");
    var oTable = sap.ui.getCore().byId("mainTable");
    oTable.setModel(oModel);
    oTable.bindRows("TableModel>/");
}

EDIT: Third try with factory

function createTableColumns(columns) {
    var oTable = sap.ui.getCore().byId("mainTable");

    oTable.destroyColumns();
    sap.ui.getCore().setModel(null, "TableModel");

    sap.ui.model.SimpleType.extend("BooleanStringType", {
        formatValue: function(s) {
            console.debug(typeof s, s);
            return s === "98";
        },
        parseValue: function(s) {
            console.debug(typeof s, s)
            return s ? "98" : "00";
        },
        validateValue: function(s) {
            console.debug(typeof s, s)
        }
    });

    var statusCheckBoxTemplate = new sap.ui.commons.CheckBox({
        text: "{TableModel>status}",
        editable: false,
        //checked: {
        //    path: "{TableModel>status}",
        //    formatter: function(v) {
        //        console.debug(v);
        //        if(v === "98") return true;
        //        else return false;
        //    }
        //}
    });

    statusCheckBoxTemplate.bindProperty("checked", {
        path: "{TableModel>status}",
        type: new BooleanStringType()
    });

    for(var i = 0; i < columns.length; i++) {
        if(columns[i] !== 'rowid') {
            oTable.addColumn(new sap.ui.table.Column({
                label: new sap.ui.commons.Label({text: columns[i]}),
                name: columns[i],
                flexible: false,
                autoResizable: true,
                template: columns[i] === 'status' ? statusCheckBoxTemplate : new sap.ui.commons.TextView({text: "{TableModel>" + columns[i] + "}"}),
                sortProperty: columns[i],
                filterProperty: columns[i],
            }));
        }
    }
}

Solution

  • You should simplify to get it working. First thing is to use a textview / label to check if the binding is working. Only then change to the checkbox and use a formatter / custom datatype for the conversion. For instance, this is not valid (from the code above):

    checked: {
      path: "{TableModel>status}",
    

    because when you pass an explicit path property, you should not use the {} in the string.