Question

This has reference to my question I posted earlier Need to know the way to stamp a field within a document collection which is in a repeat control

I am trying to access a panel which is within a repeat control using the xPages API, but I have failed in doing so because when I try to get the handle of the repeat control and try to loop through its children I only get tables row and cells which are put within the panel but I do not get the panel as the child of the repeat. Here is the code I am using to do so. Kindly suggest if there is any other way to access the panel within the repeat. I need to so so to access the datasources within the panel to save them individually.

function getComponentValueInRepeat(strRepeatID, strCompID, tmpRowIndex) {
var repeatComp:com.ibm.xsp.component.UIRepeat = getComponent(strRepeatID);
var rowIndex = 1;
if (null != repeatComp) {
    var repeatList:java.util.Iterator = repeatComp.getFacetsAndChildren();
    var repeatContainer:com.ibm.xsp.component.UIRepeatContainer = null;
    var entityComponent:javax.faces.component.UIComponent = null;

    while (repeatList.hasNext()){
        repeatContainer = repeatList.next();
        var componentList = repeatContainer.getChildren();

        while (componentList.length == 1 && 
                (componentList[0].getClass().getName().equals("com.ibm.xsp.component.xp.XspTable") |
                componentList[0].getClass().getName().equals("com.ibm.xsp.component.xp.XspTableRow"))) {
            componentList = componentList[0].getChildren();
        }

        for (compArrLoopCont = 0 ; compArrLoopCont < componentList.length; compArrLoopCont++) {
            entityComponent = componentList[compArrLoopCont];

            if (entityComponent.getChildCount() == 1 && 
                    entityComponent.getClass().getName().equals("com.ibm.xsp.component.xp.XspTableCell")) {
                entityComponent = entityComponent.getChildren();
                entityComponent = entityComponent[0];
            }

            if (entityComponent.getId().equals(strCompID) && tmpRowIndex == rowIndex) {
                if (null == entityComponent.getValue()) {
                    return "";
                } else {
                    return entityComponent.getValue();
                }

            }
        }
        //print ("hello +++ " + entityComponent[0].getId());
        rowIndex++;
    }
} else {
    print ("exception...");
}
Was it helpful?

Solution

When dealing with data you always should try to go after the data, not the UI. You change your UI, your logic breaks. There are a number of options for your task:

  • Place the individual save button inside your panel. Then a document1.save() will nicely do the trick
  • Keep the IDs of your documents in a viewScope variable and when some action requires that a document needs to be saved use that value to determine the document (probably messy)
  • Don't bind to documents, bind your values to a collection of custom objects. These objects get populated by your repeat control logic and stored in the viewScope. When you hit your save button all changed values get submitted and in your setters you can define the flag "do I need to save that" and save it.

The class could look something like that:

  public class Approval() {
      private boolean isDirty = false;
      private final String unid;
      private String approver;
      // more fields here;

      public Approval(String unid, String approver /* more values or pass the NotesViewEntry */) {
          this.unid = unid;
          this.approver = approver;
      }

      public String getUnid() {
          return this.unid;
      }

      public String getApprover() {
          return this.Approver;
      }

      public void setApprover(String newApprover) {
             if (!this.approver.equals(newApprover)) {
                this.isDirty = true;
             }
             this.approver = newApprover;
      }

      public void save(Database db) {
           if (!this.isDirty) {
              return; // No action needed
           }
           Document doc = db.getDocumentByUnid(this.unid);
           doc.replaceItemValue("Approver",this.approver);
           doc.save();
      }
  }

So your repeat code would look something like this:

// If we looked them up before we don't need to do anything
if (viewScope.approvals) {
    return viewScope.approvals;
}
// Look up the employee details view to get the employee appraisal details from the current database
var curDB:NotesDatabase = session.getCurrentDatabase();
var vwlkApprView:NotesView = curDB.getView("vwlkAllApprApper");
var collDocAppr:NotesViewEntryCollection = vwlkApprView.getAllEntriesByKey(sessionScope.EmployeeID);
// Don't do a count, slow!
var result = new java.util.Vector();
// Add all approvals
var ve:NotesViewEntry = collDocAppr.getFirstEntry();
while (ve != null) {
   var nextVe = ve.getNextEntry(ve);
   // make this next line nicer!
   result.add(new demo.Approval(ve.getUniversalid(),ve.getColumnValues().get(0))); // eventually check to avoid categories?
   ve.recyle();
   ve = nextVe;
}
viewScope.approvals = result.isEmpty() ? null : result;
collDocAppr.recyle();
vwlkApprView.recycle();
return viewScope.approvals;

Your save button then would loop through the collection

 for (var a in viewScope.approvals) {
    a.save(database);
 }

Of course another approach is to have ONE bean as the object datasource for the page that has a getApprovals(database) function to initialize it

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top