qooxdoo qx.ui.form.VirtualComboBox key value pairs

384 views Asked by At

I would like to know if it is there a prefered way to use key,value pairs in a qooxdoo qx.ui.form.VirtualComboBox. I would like the name to be set in the textbox but when requested the id should be returned. All the examples for this widget I have seen use just the value. I am posting the code how I am approaching the problem but I would like to know if there is a better/prefered way using data binding. So far every time I need the value or the key I loop through the model to find a match. Here is the playground example: http://tinyurl.com/neyfwva

//John is set for testing purposes
var myJSONObject = {"personal": [
        {"name": "Martin", "id": "1", "age": "32"},
        {"name": "Horst", "id": "2", "age": "55"},
        {"name": "Peter", "id": "3", "age": "23"},
        {"name": "John", "id": "2", "age": "40"}  ]
};

var jsonmodel = qx.data.marshal.Json.createModel(myJSONObject);

var comboBox = new qx.ui.form.VirtualComboBox(jsonmodel.getPersonal());
comboBox.setLabelPath("name");

comboBox.setDelegate({bindItem : function(controller, item, id) {
  controller.bindProperty("name", "label", null, item, id);
  controller.bindProperty("id", "model", null, item, id);
}});


this.getRoot().add(comboBox);

//#################################################################
//-->> get "ID" from selected value
var button1 = new qx.ui.form.Button("get ID from selectbox");
this.getRoot().add(button1,
{
  left : 20,
  top  : 50
});
button1.addListener("execute", function(e) {
  var model = comboBox.getModel();
  var selection= null;

  for(var i = 0, l = model.getLength(); i < l; i++){
    if(model.getItem(i).getName() === comboBox.getValue()){
      selection = model.getItem(i);
      break;
    }
  }

  if(selection){
  alert(selection.getId());
  }
});
//#################################################################

//#################################################################
//-->> set value "Horst" by giving id
var button2 = new qx.ui.form.Button("set ID -2- (also Horst)");
this.getRoot().add(button2,
{
  left : 200,
  top  : 50
});
button2.addListener("execute", function(e) {
  var model = comboBox.getModel();
  var selection = null;

  for(var i =0, l = model.getLength(); i < l; i++){
    if(model.getItem(i).getId() === "2"){
      selection = model.getItem(i);
      break;
    }
  }

  if(selection){
  comboBox.setValue(selection.getName());
  }
});
1

There are 1 answers

4
saaj On BEST ANSWER

qx.ui.form.VirtualComboBox's child control dropdown has normal selection data array. Even though Qooxdoo's API reference and docs are very good and thorough, the advice for such cases is source code is your documentation (you can go straight to the method's source code from the API reference by following View Source links). Qooxdoo's code is as good and comprehensible.

Here's modified snippet:

var data = {"personal": [
  {"name": "Martin", "id": "1", "age": "32"},
  {"name": "Horst", "id": "2", "age": "55"},
  {"name": "Peter", "id": "3", "age": "23"},
  {"name": "John", "id": "2", "age": "40"}  
]};

var model = qx.data.marshal.Json.createModel(data);

var comboBox = new qx.ui.form.VirtualComboBox(model.getPersonal());
comboBox.setLabelPath("name");

this.getRoot().add(comboBox);

var getButton = new qx.ui.form.Button("Get id");
this.getRoot().add(getButton, {'left': 20, 'top': 50});

getButton.addListener("execute", function() 
{
  var selection = comboBox.getChildControl('dropdown').getSelection();
  if(selection.getLength())
  {
    this.debug('Here is your id', selection.getItem(0).getId());  
  }
}, this);

var setButton = new qx.ui.form.Button("Set id:2");
this.getRoot().add(setButton, {'left': 200, 'top': 50});

setButton.addListener("execute", function() 
{
  // don't replace selection object as it's used internally
  var selection = comboBox.getChildControl('dropdown').getSelection();
  selection.push(model.getPersonal().getItem(1));
}, this);

Update

If you need to select an item by id or another item's attribute, qx.data.Array won't help you directly because it's an array, not a dictionary. You have to options:

Pre-calculate id -> index mapping and use it later:

var mapping = data['personal'].reduce(function(result, item, index)
{
  result[item['id']] = index;
  return result;
}, {});
var selection = model.getPersonal().getItem(mapping['2']);

Or filter the data array on demand:

var selection = model.getPersonal().filter(function(item)
{
  return item.getId() == '2';
});

If you have big list and frequent selection then the former is preferable.