javascripthtmlbootstrap-tableformatterouterhtml

Using bootstrap-table, how can I format a cell to include a select where the default selected value matches the table data?


I am using bootstrap-table to create a table dynamically from an ajax request that pulls data from our CRM, as well as having fields for input and form submission (per row) which then posts another API request to update our CRM. That all works fine.

My issue is that I need to turn the cells in one column, Result, into a select so that if the value needs to be changed a different option can be selected and submitted with the other updates. I can successfully get a select with the possible values into the cell, but I can't get it to show the actual correct value, meaning the value in the json response, as the currently selected value. Instead, it's just defaulting to the first option.

I made a rather complete copy of the table in a fiddle as I don't know which parts could be affecting this, but it's pulling random data from a mock API.

The relevant code that creates the select in the cell is as follows: Initializing the table, and the Result column with a formatter.

function initTable() {
    $table.bootstrapTable('destroy').bootstrapTable({
            height: 760,
            locale: "en-US",
            classes: "table table-bordered table-hover table-striped",
            sortable: true,
            ...
            filterControl: true,
            columns: [
                ...
                {
                    title: 'Result',
                    field: 'UF_CRM_1678511065',
                    formatter: callResultFormatter
                }
                ...
            }
        ]
    })

And the formatter is

function callResultFormatter(value, row, index) {
      callResults = {
        "79": "Sale Made",
        "335": "Rep will call back",
        "81": "Upsold Device",
        "83": "Outbound Call Needed",
        "337": "Not Interested/Bad Call",
        "739": "Support Call",
        "773": "Dropped Call",
        "775": "RMA",
        "777": "Other"
      }

      const select = document.createElement("select");
      select.className = "form-control";

      for (const [key, value] of Object.entries(callResults)) {
        const option = document.createElement("option");
        option.value = key;
        option.text = value;
        select.appendChild(option);
      }

      // Set the selected option to the input number
      const selectedOption = select.querySelector(`option[value="${row[index]}"]`);
      if (selectedOption) {
        selectedOption.selected = true;
      }

      return select.outerHTML;
    }

I have tried multiple ways of setting the selectedOption, but as none of them worked I don't see much point in posting them all.

Am I missing something obvious? Is there a limitation with bootstrap-table that would prevent this from being possible? I was thinking maybe the formatter is run in such a way that the option can't be selected, but I don't think that's true. My other thought is that I'm not returning the right thing. I know it needs to be HTML, but does outerHTML not keep the selected option?

Thank you in advance for any guidance.


Solution

  • Fixed. I'm not sure what I was thinking. Updated fiddle in case someone finds it useful in the future, and here is the fixed function.

        function callResultFormatter(value, row, index) {
            const callResults = {
                "79": "Sale Made",
                "335": "Rep will call back",
                "81": "Upsold Device",
                "83": "Outbound Call Needed",
                "337": "Not Interested/Bad Call",
                "739": "Support Call",
                "773": "Dropped Call",
                "775": "RMA",
                "777": "Other"
            }
        
            const select = document.createElement("select");
            select.className = "form-control"
        
            // loop through the possible call results to add them as options and find a match
            for (const [key, text] of Object.entries(callResults)) {
                const option = document.createElement("option")
                option.value = key
                option.text = text
                // If the value from the JSON matches an option, set the attribute "selected" to true
                if (value == key) {
                    option.setAttribute("selected", "true")
                }
        
                select.appendChild(option)
            }
            return select.outerHTML
        }
    

    Here are some additional pitfalls if anyone runs into these in the future: