2
votes

I have built a custom control which renders an arraylist of java objects via a repeat control. Via the property definition I can provide which fields from the underlying java object I want to display. In the back-end I read this value e.g. via

obj[compositeData.columnField1]

This works well with static data, but sometimes I want to format the before rendering e.g. when the field contains a notesname and I only want to display the commonname.

I am wondering how I could set up something like that.

Now I am only passing the field name, which will be picked up by the cc to read the value.

E.g. for the jQuery DataTables plugin you can define a render function for a column and use the data variable of that column within that render function (e.g. build an anchor link or button in that column).

Can I provide something similar for SSJS e.g. I pass the render function as text (or object?) and in the back-end it will be transformed to ssjs.

3

3 Answers

0
votes

Functions in JavaScript are first class citizens on objects. Presume you created a JS object with all the rendering functions and stored it in one of the scopes. E.g. viewScope.renderFunctions. Then hand over the name of the render function and inside use something like:

    var renderfunc = viewScope.renderFunctions[funcname];
     var result = renderfunc(rawdata);
      return result;

That should do the trick

0
votes

I found an answer here on stackoverflow. The eventhandler for my button looks as followed:

<xp:eventHandler event="onclick" submit="true"
            refreshMode="partial" refreshId="pnlContainer"
            action="#{javascript:if (compositeData.actionButton.action) if (!compositeData.actionButton.action.call()) return;}">
        </xp:eventHandler>

For my custom control I have set up a property:

<property>
        <property-name>action</property-name>
        <property-class>javax.faces.el.MethodBinding</property-class>
        <property-extension>
          <designer-extension>
            <editor>com.ibm.workplace.designer.ide.xfaces.internal.editors.MethodBindingEditor</editor>
          </designer-extension>
        </property-extension>
        <description>ssjs that action button must perform</description>
      </property>

Make sure the class and editor are as above.

Then the property on the xpage containing the custom control contains the ssjs:

action="#{javascript:removeSelected}"

This is a function that resides in a SSJS script library. The key here is not to provide ANY parameters of parantheses (!!!)

The SSJS function is as followed:

function removeSelected(){
    var accessList = sessionScope.get("removalList");   
    var nsf_committee = datasources["COM1_DB_FILEPATH"];        
    var db:NotesDatabase =  session.getDatabase(session.getServerName(), nsf_committee);
    for (var i = 0; i < accessList.length; i++) {
        var doc:NotesDocument = db.getDocumentByUNID(accessList[i]);
        if (null != doc){
            doc.remove(true);
            accessList.remove(accessList[i]);
        }
    }   
}

(here I remove documents from the database. the unid id's reside in a an arraylist. the array list is set via a checkbox group for each row in my repeat control.)

0
votes

Considering you would likely want to re-use the component in many contexts of your app I would approach the problem with an helper class and interface

public class FieldManager {

  public static interface FieldDetail {
     String getName();
     void getAction();
  }

  private List<FieldDetail> fieldDetails = new List<FieldDetail>();

  public FieldManager() {

  }

  public FieldManager(List<FieldDetail> fieldDetails) {
    this.fieldDetails.addAll(fieldDetails);
  }

  public void addFieldDetail(FieldDetail fieldDetail) {
    this.fieldDetails.add(fieldDetail);
  }

  public List<FieldDetail> getFieldDetails() {
    return fieldDetails;
  }

}

With this succinct definition you could now be able to implement the FieldDetail interface with a generic class or alternative specialized classes.

Then in the custom control you set a property as value or whatever, the <property-class> tag will be FieldManager and in the custom control you would know how everything plays out because the class FieldManager and the FieldDetail are the contract for you.

<xp:repeat disableOutputTag="true"
        value="#{compositeData.value.fieldDetails}" var="fieldDetail">
    <xp:link text="#{fieldDetail.name}">
        <xp:eventHandler event="onclick" submit="true"
                refreshMode="partial" refreshId="pnlContainer"
                action="#{fieldDetail.action}">
        </xp:eventHandler>
    </xp:link>
</xp:repeat>

Or whatever your code might be. Anyway, that's the gist of it.