Posts Tagged: ‘ViewPanel’

Notes: Views in Standard-Notes Web-Applikationen

27. Februar 2012 Posted by airwolf89

Heute hatte ich eine (eigentlich) recht einfache Aufgabe: In einer View, welche in einer Standard-Notes Webanwendung (also ausnahmsweise mal keine XPages) sollte ein Paging eingebaut werden, weil nicht alle Einträge angezeigt wurden.

Damit hatte ich mich bisher noch nicht beschäftigt und merkte, dass das (vermeintlich) gar nicht so einfach ist. Die View wird über einen Button innerhalb eines Frames in einem Frameset aufgerufen. Somit hatte ich erstmal keine Möglichkeit etwas an der View einzustellen, wie z.B. den “linecount” bei embeddedViews.

Ich stieß auf eine Option im Server Dokument namens “Default lines per view page”, zu finden im Admin Client unter Configuration -> Web -> Internet Sites -> Domino Web Engine

Diesen zu modifizieren brachte aber kein Ergebnis in der Anwendung.

Schließlich fand ich heraus wie es funktioniert. Die Views, welche in Framesets eingebunden werden, werden über eine Form namens “$$ViewTemplateDefault” aufgerufen. Diese kann man sich natürlich auch selbst erstellen.

Dazu einfach eine Form definieren, eine embeddedView reinpacken und dann kann man auch munter herumkonfigurieren, wie z.B. den lineCount.

Allerdings löste das das Problem des Pagings noch immer nicht. Da half mir aber eine Dokumentation von IBM weiter, zu finden hier.

Dort steht weiter unten wie es geht. Einfach in die Form irgendwo hin einen Button oder eine Action, welche den folgenden Code enthält:

@DbCommand("Domino"; "ViewNextPage")

Damit kann man dann wunderbar durch die View durchblättern.


Einsortiert unter:Notes & XPages Tagged: embedded view, Formel, frameset, line count, Pagination, Paging, Refresh, standard notes, ViewPanel, web

Notes: Ein- und Ausblenden von View-Actions

9. November 2011 Posted by airwolf89

Heute mal ein kleiner Tipp für Standard-Notesclient Anwendungen.

Ich hatte die Anforderung bekommen dass in einer kategorisierten View die Actions ein- und ausgeblendet werden sollen, je nachdem ob ich eine Kategorie oder ein Dokument ausgewählt habe. Langes Suchen brachte nichts und auch ein Kollege war der Meinung es geht nicht. Ein anderer Kollege brachte dann aber doch die Lösung:

In den View-Einstellungen gibt es eine Option namens „Evaluate actions for every document change“. Das funktioniert deshalb weil auch ein Wechsel der Selektion als Change aufgefasst wird.
Schlussendlich muss man in der Hide-When Formel nur noch auf die Form abfragen. Wenn sie leer ist verstecke den Button, wenn nicht dann zeige ihn an, denn Kategorien haben keine Form.

Darüber hinaus kann man so natürlich noch sehr flexibel entsprechende Actions anzeigen, beispielsweise wenn man in der View mehrere Forms hat.


XPages: Tippsammlung

18. Oktober 2011 Posted by airwolf89

Hallo,

hier mal eine kleine Ansammlung von Tipps welche meine Kollegen und ich uns im Laufe der Zeit notiert haben.

Attributbenennung im IE

Dojo scheint bei Attributselektoren (z.B. dojo.query()) im Internet Explorer Probleme zu haben, die richtigen Elemente zu finden, wenn ein Teilstring des Attributs ein reserviertes Wort (z.B. name oder id) enthält. Da Dojo wie jQuery als Selektor-Engine Sizzle einsetzt, kann dieses Phänomen auch bei jQuery auftreten!

Beispiel hierfür ist ein Input-Feld mit dem Namen „username“. Selektiert man dojo.query(‘input[id$="WFApprovalVFL"]‘) wird das username-Feld mitselektiert, obwohl es nicht auf WFApprovalVFL endet.

Selbiges gilt für Keynamen in JSON-Objekten.

Nich gerenderte Datasources werden dennoch computed

Wenn man in einem Custom Control eine Datasource verwendet, dann wird dessen Code IMMER ausgeführt, egal ob rendered=“false“ oder loaded=“false“. Der Code dazu wird immer ausgeführt. Dies kann zu schwer nachvollziehbaren Fehlern führen.

Des weiteren, wenn man mehrere Datasources in unterschiedlichen Custom Controls hat, welche auf das selbe Dokument zeigen, so werden alle diese Datasources gespeichert und ggf. mehrere Dokumente desselben Typs angelegt.
Um dieses Problem zu umgehen kann man in den Custom Controls entweder die Datasource auf der XPage direkt über den namen referenzieren, oder man übergibt die Datasource per Parameter an das Custom Control (compositeData). Da muss man allerdings manuell einen Typ auswählen, da Datasources nicht in der Liste auftauchen. Der Typ heißt: com.ibm.xsp.model.ModelDataSource

Prüfen ob ein Viewpanel kategorisiert ist

Gesetzt den Fall, das zu prüfende View Control auf der XPage heißt viewPanel1, liefert:

var model:com.ibm.xsp.model.domino.DominoViewDataModel = getComponent("viewPanel1").getDataModel();
return model.getCategoryIndentLevel();

den Wert 0, wenn die View kategorisiert ist, -1 wenn nicht.

Use case: Bei kategorisierten Views gehen die Inhalte der Kategoriespalte verloren, wenn die View umsortiert wird. Hiermit kann man prüfen, ob die View umsortiert ist und entsprechend die Anzeige wiederherstellen.

Umgehen des OnChange-Bugs im IE beim Klick auf eine CheckBoxGroup

Werden auf einer XPage oder Custom Control Radiobutton Groups oder Checkbox Groups verwendet, tritt im IE das Phänomen auf, dass beim Partial refresh die übergebenen Werte der Gruppe immer die Werte des vorangegangenen Requests sind. Dies tritt nur auf, wenn man auf das Label klickt, statt direkt auf die Box zu klicken. Grund hierfür ist, dass der IE den Partial refresh-Request abschickt, bevor auf der UI der neue Wert gesetzt wird.

rendered="#{javascript:context.getUserAgent().isIE()}"


Beispiel
:

Es gibt eine Checkbox-Gruppe mit den Optionen A, B, C, D. Beim onchange-Event wird ein Partial refresh auf ein anderes Panel ausgelöst, das abhängig von den gewählten Optionen Elemente ein- oder ausblendet. Klickt man auf das Label für die Option A, kommt kein gewählter Wert an. Klickt man anschließend auf das Label für die Option B, kommt der Wert A an. Klickt man anschließend auf das Label der Option C, kommen A und B an, usw.


Workaround
:

Im onclick-Eventhandler wird der Partial refresh beim oncomplete ein zweites Mal ausgeführt.

 <xp:this.onComplete>
<![CDATA[XSP.partialRefreshPost("#{id:refreshPanelID}");]]>
</xp:this.onComplete>

Obiger Workaround 1 wirkt nicht, wenn auf dem Eventhandler zusätzlich noch Aktionen bzw. Server Side Javascript ausgeführt werden soll. Dieser Code wird dann nur beim ersten partial refresh ausgeführt. Um diesen Eventhandler wieder gängig zu machen, muss man den Click-Event des Labels von seiner Standard-Aktion abhängen und selbst durchführen. Dies macht man in einem clientseitigen Scriptblock. Da aber die Checkbox selbst auch innerhalb des Labels liegt, muss man diese wiederum aus der eigenen Verarbeitung rausnehmen:

 <xp:scriptBlock id="scriptBlock1"
        rendered="#{javascript:context.getUserAgent().isIE()}">
        <xp:this.value><![CDATA[dojo.addOnLoad(function(){
    dojo.query("label",dojo.byId("#{id:checkBoxGroupID}")).forEach(function(el){        
        dojo.connect(el,"onclick",el,function(e){
            if (e.target.type != "checkbox") {
                e.preventDefault();
                dojo.query("input",this).forEach(function(el){
                    dojo.attr(el,"checked",!(dojo.attr(el,"checked")));
                });
            }    
        });
    });        
});]]></xp:this.value>
</xp:scriptBlock>

Ein weiterer Vorteil dieser Methode gegenüber Workaround 1 ist, dass kein zweiter Request nötig ist.

Validierung von zwei abhängigen Eingabefeldern

Bei der Validierung von zwei voneinander abhängigen Eingabefeldern muss der SubmittedValue des Feldes abgefragt werden, das validiert wird. Vergleicht man den Value des Feldes mit dem Value des zweiten Feldes, wird die Validierung nach dem ersten Fehlschlag nicht mehr ausgelöst und der Validierungsfehler bleibt bestehen.

Beispiel:

 <xp:inputText id="recipientNotesID"
   value="#{test.recipientNotesID}"
   disableClientSideValidation="true" required="true">
   <xp:this.validators>
      <xp:validateRequired message="Required value."></xp:validateRequired>
   </xp:this.validators>
</xp:inputText>
<xp:inputText id="recipientNotesPW"
   value="#{test.recipientNotesPW}"
   disableClientSideValidation="true" required="true">
   <xp:this.validators>
      <xp:validateExpression>
         <xp:this.expression><![CDATA[#{javascript:((getComponent("recipientNotesPW").getSubmittedValue()||"")!=(getComponent("recipientNotesID").getValue()||""))}]]>
         </xp:this.expression>
         <xp:this.message><![CDATA[#{javascript:"Values must not be equal."}]]></xp:this.message>
      </xp:validateExpression>
      <xp:validateRequired message="Required value."></xp:validateRequired>
   </xp:this.validators>
</xp:inputText>