There is a lot of code... too much to include all of it here. So, I've included the key pieces (stripped of non-relevant code) below. It works *most* of the time, but every once in a while the JSON value order does not match the repeat control order. I guess I thought they always should. Thanks for offering your time to help. :)
<xp:repeat var="rowData" indexVar="rowIndex" repeatControls="false"
id="docsRepeatPortfolio_OpenShops" rows="17">
<xp:this.value><![CDATA[#{javascript:
TemplateSearch.search('viewScope', 'searchQueryString', session.getServerName(), applicationScope.leasesDBPath,
[{
fieldName: 'OS_UNID',
formula: '@Text(@DocumentUniqueID)',
dataType: 'string'
},{
fieldName: 'OS_DBA',
formula: 'LeaseName',
dataType: 'string'
},{
fieldName: 'OS_DBA',
formula: 'LeaseName',
dataType: 'string'
},{
fieldName: 'OS_VVFlag',
formula: 'VV_Flag',
dataType: 'string'
}], 'jsonValuesPortfolio');
}]]></xp:this.value>
<xp:tr id="trowPortfolio_OpenShops">
<xp:td>
<xp:text escape="true"
id="dtaPortOSDBA"
value="#{rowData.OS_DBA}">
</xp:td>
<xp:td>
<xp:text escape="true"
id="dtaPortOSVVFlag"
value="#{rowData.OS_VVFlag}">
</xp:td>
</xp:tr>
</xp:repeat>
SSJS Library Template Search function:
var TemplateSearch = {
// Templates to build the value-parts from
"template-js-date-only": "@If( $formula='' ; 'null' ; '/Date(\"' + " + "$formula + '\")/' )",
"template-string": "'\"' + $formula + '\"'",
"template-multi-string": "'[\"' + @Implode( $formula ; '\",\"' ) + '\"]'",
"template-number": "@Text( $formula )",
"template-multi-number": "'[' + @Implode( @Text( $formula ) ; ',' ) + ']'",
"template-date": "@If( $formula='' ; 'null' ; '/Date(\"' + "
+ "@Implode(@Text(@Year($formula):@Month($formula):@Day($formula)) ; '/' ) + ' ' + "
+ "@Implode(@Text(@Hour($formula):@Minute($formula):@Second($formula)) ; ':' ) + '\")/' )",
"template-date-only": "@If( $formula='' ; 'null' ; '/Date(\"' + "
+ "@Implode(@Text(@Year($formula):@Month($formula):@Day($formula)) ; '/' ) + ' ' + "
+ "@Implode(@Text(0:0:0) ; ':' ) + '\")/' )",
"template-multi-date":"@If( $formula='' ; 'null' ; '[/Date(\"' + @Implode( @Transform( $formula ; 'date' ;"
+ "@Implode( @Text(@Year(date):@Month(date):@Day(date)) ; '/' ) + ' ' + "
+ " @Implode( @Text(@Hour(date):@Minute(date):@Second(date)) ; ':' ) ); '\")/,/Date(\"' ) + '\")/]' )",
// Helper-method to build a string that can be evaluated in formula-language against a document
buildJSONFormulaTemplate: function( fieldDefinitions ){
var formulaTemplateItems = [];
for( var i=0; i < fieldDefinitions.length; i++ ){
var field = fieldDefinitions[i];
var valuePart = this['template-' + field.dataType].replace( /\$formula/g, field.formula );
formulaTemplateItems.push( "'\"" + field.fieldName + "\":' + " + valuePart );
}
return "'{' + " + formulaTemplateItems.join( " + ',' + " ) + " + '}'";
},
/*
query: The FTSearch-query
fields: an array of objects describing the template fields with fieldName, formulaString, dataType
dataType: string, multi-string, number, multi-number, date, multi-date
*/
search: function( queryScopeType:String, dbServerName:String, dbFilePath:String, fieldDefinitions, jsonVarName:String){
var functionName:String = "search";
var queryString = viewScope.get( queryScopeName );
var jsonValues = viewScope.get(jsonVarName);
try {
if( !jsonValues || scopedVariableChanged( queryScopeType, queryScopeName ) ){
var dbToSearch:NotesDatabase = session.getDatabase(dbServerName,dbFilePath)
var resultCol:NotesDocumentCollection = dbToSearch.FTSearch( queryString );
//viewScope.aaResultCount = resultCol.getCount();
var resultDoc:NotesDocument = resultCol.getFirstDocument();
//viewScope.aaResultDocId = resultDoc.getUniversalID();
var jsonFormulaTemplate = this.buildJSONFormulaTemplate( fieldDefinitions );
//viewScope.aaJSONFormulaTemplate = jsonFormulaTemplate;
var jsonItems = [];
var sumFields = getSummedFieldsArray(fieldDefinitions);
viewScope.sumFields = sumFields;
var averagedFields = getAveragedFieldsArray(fieldDefinitions);
viewScope.averagedFields = averagedFields;
while( resultDoc !== null ){
var jsonFormulaTemplateJS = evaluateJSFunctions(resultDoc, jsonFormulaTemplate);
jsonItems.push( session.evaluate( jsonFormulaTemplateJS, resultDoc )[0] );
// both of these operations require the field values to be summed. Averages will be calced after looping through all docs
resultDoc = resultCol.getNextDocument();
}
jsonValues = Lookup.parseJSONArray( jsonItems );
viewScope.put( 'numValues' + jsonVarName, jsonValues.length );
}
} catch (e) {
handleDashboardError(functionName, e);
}
var jsonValuesSorted = Lookup.sortJSONArray( jsonValues, viewScope.get(sortScopeName), viewScope.get(sortScopeName2), viewScope.get(sortScopeDirection));
viewScope.put(jsonVarName, jsonValuesSorted);
return jsonValuesSorted;
}
}
Here is the db Search string that is set before the repeat control is loaded:
searchQueryString = "(FIELD Form = LeaseRecord) AND (FIELD LeaseStatus = Active) AND (FIELD E1_ABS_Flag = True)";