Search code examples
javascriptknockout.jsoracle-jet

populate dynamic columns based on the user column selection using oracle jet + knockout JS + elasticsearch


In my site development I have provided combobox where the user can select the columns to be displayed and the data will fetched and presented based on the users requests. So I have provided the combo box selection as below,

<div id="filterColumns" style="width: 1px; min-width: 100%;">
  <oj-label for="multiSelect">Select Columns</oj-label>
  <div id="columnsList">
    <oj-select-many help.instruction="Select the columns to populate the data" id="multiSelect" value={{selectedColumns}} style="max-width:50em">
      <oj-option value="Name">Name</oj-option>
      <oj-option value="Age">Age</oj-option>
      <oj-option value="Gender">Gender</oj-option>
      <oj-option value="Mainden Name">Mainden Name</oj-option>
      <oj-option value="Mothers Name">Mothers Name</oj-option>
      <oj-option value="Designation">Designation</oj-option>
      <oj-option value="Experience">Experience</oj-option>
      <oj-option value="Company">Company</oj-option>
      <oj-option value="Location">Location</oj-option>
    </oj-select-many>
  </div>
  <oj-button id='filterColumnsGo' on-oj-action='[[generateData]]'>Generate Data</oj-button>
</div>

And in the ViewModel, am getting the column names which are selected the user,

self.selectedColumns = ko.observableArray(document.getElementById('columnsList'));

and call the Elasticsearch API with the data based on the selection.

Below is the response of one data,

{
  "_index": "person_data",
  "_type": "_doc",
  "_id": "moahn",
  "_score": 1,
  "_source": {
    "person_details": {
      "age": 23,
      "gender": "male",
      "mothers_name": "Jabito",
      "mainden_name": "Rosoku",
      "designation_info": {
        "designation_name": "Architect",
        "company": {
            "company_location": "Delhi",
            "experience": 4,
        }
      }
    }
  }
}

Am looking for the way to parse the data in the same order of user selected the column names in the combobox. I was trying to loop through as below, and for each loop was trying to loop the fetched data but not working as expected,

self.selectedColumns().forEach(function(col){
  tempCols.push({headerText: col, field: col});
  ...
  ...
});

Since the Elasticsearch doesn't provide the item name details where I can simply get it and the data returned by ES is nested JSON formatted result where it will not have the same name as what displayed for the user selection in combo box. Any help would be appreciated


Solution

  • The simplest way to do this is to have a "schema" like mapping file where you specify how the columns map one to one with the fields. So you can do something like this:

    ColumnDataMapping: {
       "age": { field: "age", label: "Age" }
       "mothersName": { field: "mothers_name", label: "Mothers Name" },
       "designation": { field: "designation_info.designation_name", label: "Designation" }
       "location": { field: "designation_info.company.company_location", label: "Location" }
       ...
    }
    

    Then in your view model using that mapping you can get the columns and the fields they are mapped to. Note that in your combo-box you would not have the same values as labels. You values would be the keys in the ColumnDataMapping and your labels would be the label fields.

    This way you can be flexible with your code since all you care about is the correct configuration of the "schema". So you decouple from the code the knowledge of how fields are mapped etc.

    This also allows you now to store that "schema" and make it customizable. You can also add any fields you want to extend it ... like enabled for a field etc.