PDA

View Full Version : Combo Boxes



Zakaroonikov
28 Jun 2007, 2:17 PM
I made some modifications to the Ext.nd.UIView class so that I am able to create a Ext.data.Store object without creating the view. By doing this I was able to get some Ext combo box examples to work with Domino.

I am not sure how useful the code is but here is the wrapper class that I created for the combo boxes. One the to notice is how I make use of Ext.nd.UIView. I pass these parameters to the constructor:


viewName: dataSource, // Ext.data.store from results
callback: this.setCombo.createDelegate(this), // Function to call after data.store is created
createGrid: false // Modification to Ext.nd.UIView code to not create grid if this is set


I have also added a new function to the Ext.util.Format class so that I can strip the prefix of the Ext.nd.UIView data records (it adds a prefix data type to the values). You would need to put something like this in your code or else you would get values like 'tJohn Smith' as a data value instead of 'John Smith' in your combo box list.



Ext.util.Format.stripLeft = function(value, start) {
return String(value).substr(start);
};


Here is the entire code for the class:


/**
* @class JCW.Form.ComboBox
* Represents a combobox field in a form<br><br>
* Usage:<br>
<pre><code>
* Transform on-page combobox field 'light' to Ext combobox with type ahead features
var ucb = new JCW.Form.ComboBox('light');
* Create combo box on field 'comboAjax' using domino viewentries url as datasource and displaying
* first column from results in select list
var cf2 = new JCW.Form.ComboBox( 'comboAjax', '/__CA25687000822467.nsf/Corporate+Extension+List');
* Create combo box on field 'comboTpl' using domino viewentries url as datasource and custom template
* to display 2 values from result in select List (stripLeft(1) is used to remove prefix character from Ext.nd)
var cf = new JCW.Form.ComboBox(
'comboTpl',
'/__CA25687000822467.nsf/Corporate+Extension+List',
{ tpl: [ '<div class="search-item">',
'<h3><span>{Name:stripLeft(1)}<br /></span></h3>{PhExt:stripLeft(1)}',
'</div>']}
);
* Create combo box on field 'comboLocal' using array 'AusState' below as data source and
* ['abbr', 'state'] mapping elements to field names. Configuration parameter col set to 1 tells
* the combo box to display the second element (state) as the element in the list and also what
* is returned to the field
AusStates = [
['ACT', 'Australian Capital Territory'],
['NSW', 'New South Wales'],
['NT', 'Northern Territory'],
['QLD', 'Queensland'],
['SA', 'South Australia'],
['TAS', 'Tasmania'],
['VIC', 'Victoria'],
['WA', 'Western Australia']
];
var arrcb = new JCW.Form.ComboBox('comboLocal',
{ fields: ['abbr', 'state'],
data : AusStates},
{ col: 1}
);
</code></pre>
* @constructor Create Ext.Form.ComboBox on dom ID fieldID
* @param {String} fieldID Dom ID of field to place combo box onto
* @param {String/Object} dataSource (optional) If datasource is not present that source of data is field specified in first parameter
* otherwise it is a string URL or an object containing an array with values and another with
* element to name mappings
* @param {Object} config (optional) Ext.Form.ComboBox config options (see Ext documentation for list)
*/
JCW.Form.ComboBox = function(fieldID, dataSource, config) {
if (fieldID) { // Only proceed if there is a destination field to place ext combobox onto
this.fieldID = fieldID;
this.config = {}; // Combobox configuration object (keep separate from object so we can pass entire configuration across)
Ext.apply(this.config, config); // Update combobox config with pass params
this.setupCombo(dataSource); // Determine type of combobox data source and run the appropriate configuration
}
};

JCW.Form.ComboBox.prototype = {
dominoConfig: {
typeAhead: false,
emptyText: 'Search',
loadingText: 'Loadind Data...',
pageSize: 10,
queryParam: 'StartKey',
listClass: 'x-combo-list',
hideTrigger: true
},
arrayConfig: {
typeAhead: true,
mode: 'local',
triggerAction: 'all',
emptyText:'Search',
selectOnFocus:true,
listClass: 'x-combo-list'
},
htmlConfig: {
typeAhead: true,
mode: 'local',
triggerAction: 'all',
listClass: 'x-combo-list',
forceSelection:true
},
/**
* Using dataSource, determine if source data is from Domino View Entries, a javascript array or the field already has the content and needs
* reformatting
* @param {String/Object} dataSource (optional) If datasource is not present that source of data is field specified in first parameter
* otherwise it is a string URL or an object containing an array with values and another with
* element to name mappings
*/
setupCombo : function (dataSource) {
if (dataSource) { // Datasource is supplied
if(typeof dataSource == 'string') { // If datasource parameter is supplied and is a string then it is a URL so use AJAX to get the data
this.setupDominoCombo(dataSource);
} else if(dataSource.fields && dataSource.data){ // If datasource is an array with a field name mapping
this.setupArrayCombo(dataSource);
}
} else { // No datasource so this is a transformation of a regular combobox to an ext combo box
this.setupHTMLCombo();
}
},

/**
* Using a dom ID for an existing combobox field convert it to use Ext.Form.ComboBox type-ahead capabilities
*/
setupHTMLCombo : function() {
Ext.applyIf(this.config, this.htmlConfig); // Set defaults for field conversion
this.config.transform = this.fieldID; // Set field to transform to passed in field dom id
var comboField = new Ext.form.ComboBox(this.config); // Convert field to ext.form.combobox
},

/**
* Using an object containing an array with the data to add to the combo box and another array mapping element numbers to identifiers
* create an Ext.data.Store for the combobox to use for its type-ahead
* @param {Object} dataSource Object contains an array with data values and another array with element to name mappings
*/
setupArrayCombo : function(dataSource) {
Ext.applyIf(this.config, this.arrayConfig); // Set defaults for array datasource combobox
this.store = new Ext.data.SimpleStore(dataSource); // Create ext data store using supplied object
if(this.store) {
this.config.displayField = this.setDisplayField(); // Determine what element in data array to use when an item is selected and also
// what to display as default element in listing (if no template is supplied)
var comboField = new Ext.form.ComboBox(this.config);
comboField.store = this.store;
comboField.tpl = this.setTemplate(comboField,false); // Get template from supplied config or use the default displaying displayField
comboField.applyTo(this.fieldID); // apply it to the exsting input element
}
},

/**
* Using supplied url to view get the readviewentires and use it as datasource for this combobox
* @param {String} dataSource Url to view (not containing any ? parameters) to get readviewentires from
*/
setupDominoCombo : function(dataSource) {
Ext.applyIf(this.config, this.dominoConfig); // Set defaults for viewentriesd datasource combobox
var DataStore = new Ext.nd.UIView({ // Read-in readviewentires for the supplier url and call this.setCombo on success with
viewName: dataSource, // Ext.data.store from results
callback: this.setCombo.createDelegate(this),
createGrid: false
});
},
/**
* Callback function called by Ext.nd.UIView if data is successfully read from ReadViewEntries for supplied url
* @param {Ext.data.Store} ds Resultset from converted ReadViewEntries query
*/
setCombo : function (ds) {
this.store = ds;
if(this.store) {
this.config.displayField = this.setDisplayField(); // Determine what element in data store to use when an item is selected and also
// what to display as default element in listing (if no template is supplied)
var comboField = new Ext.form.ComboBox(this.config);
comboField.tpl = this.setTemplate(comboField, true); // Get template from supplied config or use the default displaying displayField
comboField.sv = comboField.setValue; // Store original function
comboField.setValue = function(v) {
// Override setValue function of combobox as Ext.nd.UIView stores ReadViewEntries values with 1 character prefix
// This prefix is stripped below before the field value is set (when an item is selected from the combo list)
if(v) return comboField.sv(Ext.util.Format.stripLeft(v, 1));
}
comboField.store = this.store;
comboField.applyTo(this.fieldID); // apply it to the exsting input element
}
},

/**
* If the configuration parameter hasn't been set for displayField then use the element number (either config.col or 0 if it doesn't exist)
* as in index to get the data element name
* @return {String} Element identifier to use for display (including default for combo list if no template is supplied)
*/
setDisplayField : function () {
// Use column number as key for data source if displayField is not set (col number defaults to 0 which is the first column in the view)
if (!this.config.displayField)
// Get element name using this.config.col if it exists otherwise get first element
return this.getIndex(String(this.config.col ? this.config.col : 0));
else
return this.config.displayField;
},

/**
* Setup the template to use for displaying the combo list. Use the config template if supplied otherwise use the default
* @param {Ext.Form.ComboBox} comboField Field to merge into the template being set
* @param {boolean} stripLeft (Optional) True if first character is to be stripped on default template
* @return {String/Ext.Template} Template to use for display of combo list
*/
setTemplate : function (comboField, stripLeft) {
var template;
if (this.config.tpl) { // Use config template if supplied
template = new Ext.Template(this.config.tpl);
// Replace any column numbers in template with their corresponding object index name
// ie {0} becomes {Name} if 'Name' is the first column name described in the lookup
template.html = String(template.html).replace(/\{([\d]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g, this.getIndex.createDelegate(comboField));
} else { // If no template was supplied use the default which is a 1-item div list using displayField as the column name/number for the data
template = '<div class="'+comboField.listClass+'-item">{' + comboField.displayField + (stripLeft ? ':stripLeft(1)' : '') + '}</div>';
}
return template;
},

/**
* Given a numeric key for the data grab the literal identifier for the element in the data list
* @param {String} key Index of element in item's data array
* @return {String} Literal identifier of the data element at this index
*/
getIndex : function(key) {
var keyNumber = key.match(/\d+/); // Remove anything in string that is not numeric
if (keyNumber) {
var idx = parseInt(keyNumber); // Convert numeric portion of string to integer for array lookup
if(this.store.fields.keys.length >= idx+1)
return this.store.fields.keys[idx]; // Use key to locate field name for this element
else
return key;
}
}

};

RWaters
29 Jun 2007, 6:44 AM
Nice work. My current comboboxes have been using a page or agent to spit out some json from a view, but this looks like a good way to reuse some code. Perhaps I'll look into breaking out the Reader and DataStore's some more so they are easier to use for other Ext components. As for the data type prefix, we're looking into another way to go about it and it may change in the near future.

dominodeviant
31 Jul 2007, 6:55 AM
Reusing the thread for a similiar subject.
I am trying to get Single Category views to work, without a combobox.

Like the below example:
http://www.openntf.org/extnd/demo.nsf/demo-singlecategory-views.html!OpenPage

Does anyone have experience or a working example to share for single category views?

My scenario is a viewtemplatedefault form with an single categorized embedded view.
Kind regards,
D.D.

sandymonroe
8 Oct 2007, 12:58 PM
Would really like to look at and work with the JCW.Form.Combobox code shown above... however I am new to Ext and Ext.nd. How would I load this file of information into domino for the code to be able to reference it? I have tried many of the normal places to no avail. Any help would be appreciated.

Sandy Monroe