Typeahead i et names felt

I XPages er det nemt at lave typeahead. Her er vist et eksempel på et names felt der laver opslag til adressebogen på serveren:

<xp:inputText value="#{document1.manager}" id="manager">
	<xp:typeAhead mode="partial" minChars="1" ignoreCase="true">
	<xp:this.valueList><![CDATA[#{javascript:@Name("[Abbreviate]",
@DbLookup("names.nsf", "($VIMPeople)",getComponent("manager").getValue() ,1,"[PARTIALMATCH]")
)}]]></xp:this.valueList>
	</xp:typeAhead>
</xp:inputText>
Note: af en eller anden grund virker Partial refresh ikke på min server – men det virker på andre servere? Full refresh virker dog fint…
Bemærk
  • at der benyttes en @DbLookup (ok ikke en DbColumn) – dermed undgå vi at hente flere data end nødvendigt.
  • hvis koden skal virke i Notes klienten, så skal der angives et servernavn – ellers laves opslag til den lokale adressebog
  • Du kan få koden forklaret i denne video: A license to type ahead
Fejlsøgning
  • Koden er lavet som ServerSide JavaScript – og det kan ikke debugges 🙁
  • Da koden kører som et AJAX kald – så kan du ikke umiddelbart se evt. fejlbeskeder. Det virker bare ikke/der sker ikke noget når du indtaster i feltet.
  • Hvis du vil se fejlbeskeden, så tast F12 (vis debugger) i din Chrome browser og vælg ‘Network’ tab – så kan du se retur værdier fra AJAX kaldet.
I ovenstående eksempel vil typeahead funktionen blot vise en liste med matchende navne. Du har dog også mulighed for at lave det rigtigt lækkert – og også vise billede, afdeling, telefonnr m.v. i typeahead listen. Prøv at se nogle at disse eksempler:

Custom Controls med parameter

1. På din Custom Control kan du oprette nye Property Definitions (dvs. definere hvilke parameter der kan sendes til denne Custom Control)

2. På samme Custom Control kan du frit bruge værdierne. Her et eksempel på et Computet field der læser værdien fra vores ‘title’ parameter:

<xp:text escape="true" id="computedField1"
   value="${javascript:compositeData.title;}">
</xp:text></h2>

3. Tilsidst kan du på dem XPage hvor du indsætter din Control, angive værdierne. Her sætter ‘title’ feltet ved at hente værdien fra feltet ‘PersonName’ på CurrentDocument

I dette eksempel er der blot overført en String – men stort set alle data typer kan bruges som parameter – også Objects som f.eks. et NotesDocument

 

Hide/When i XPages

På alle XPages elementer er der en ‘rendered’ property. Hvis denne sættes til False, så bliver elementet skjult og ikke sendt med ud til browseren (fjernet fra HTML koden).

Hiden/When kan nemt baseres på roller som det kendes fra Notes klienten. I XPages benyttes denne kode:

context.getUser().getRoles().contains('[rolename]');

Tilsvarende kan nedenstående kode benyttes til at skjule et element når dokumentet er i edit mode:

rendered="#{javascript:document1.isEditable()}">

Eller en @IsNewDoc:

!document1.isNewNote()

Links

 

Dynamisk Custom Control

Det er muligt at lave en ‘Computet Custom Control’ (tilsvarende en Computet Subform).

Du skal blot indsætte en ‘Include Page’ control og så lave et lille javascript der beregner hvilken Custom Control der skal vises. I dette eksempel beregnes udfra en QueryString parameter:

<xp:include id="include1">
	<xp:this.pageName>
	<![CDATA[${javascript:"/"+param.page+".xsp"}]]>
	</xp:this.pageName>
</xp:include>

Dynamisk ændring af Themes

Hvis du har flere themes, så kan man nemt lave en dropdown på din XPage hvorfra brugeren selv kan vælge et andet theme. Koden er vist nedenfor. Det er også muligt, i themet, at beregne hvilke stylesheets der skal benyttes – det har bl.a. Paul Withers lavet et eksempel på.

Theme vælger – koden er lige til at kopiere. Du skal blot ændre valgmuligheder, så de svarer til de themes du har:

<xp:panel styleClass="lotusInfoBox">
	<h3>Theme selector</h3>
	<xp:comboBox id="comboBox1" value="#{requestScope.possibleAppThemes}">
		<xp:selectItem itemLabel="" />
		<xp:selectItem itemLabel="Theme1" />
		<xp:selectItem itemLabel="Theme2" />
		<xp:selectItem itemLabel="Theme3" />
		<xp:eventHandler event="onchange" submit="true"
			refreshMode="complete">
			<xp:this.action><![CDATA[#{javascript:var f = "/"+@RightBack(context.getUrl().getAddress(),"/");
context.setSessionProperty('xsp.theme', getComponent('themeSelector').getValue());
context.redirectToPage(f)}]]></xp:this.action>
		</xp:eventHandler>

	</xp:comboBox>
</xp:panel>

Login og Logout

På OpenNTF findes der en lækker Login/Login Custom Control som du kan genbruge på dine egne sider. Denne åbner en dialogboks og understøtter funktioner som ‘Husk password’ og ‘Glemt password’

Hvis du ønsker en mere simple ‘gør det selv’ løsning, så kan du blot indsætte følgende kode i dit OneUI ‘lotusBanner’ panel:

<xp:tabbedPanel id="lotusUtility" styleClass="lotusInlinelist lotusUtility"
		disableTheme="true">
		<xp:tabPanel id="tabserverName" startTabStyleClass="lotusFirst">
			<xp:this.label><![CDATA[${javascript:"On " + @Name("[CN]",database.getServer());}]]></xp:this.label>
			<xp:this.loaded><![CDATA[${javascript:@ClientType()=="Notes"}]]></xp:this.loaded>
		</xp:tabPanel>
		<xp:tabPanel id="userName" startTabStyleClass="lotusFirst"
			styleClass="lotusUser">
			<xp:this.label><![CDATA[#{javascript:@Name("[CN]",session.getEffectiveUserName());}]]></xp:this.label>
			<xp:this.loaded><![CDATA[${javascript:@ClientType()=="Web"}]]></xp:this.loaded>
		</xp:tabPanel>
		<xp:tabPanel label="Log in" id="login">
			<xp:this.rendered><![CDATA[${javascript:@ClientType()=="Web" && session.getEffectiveUserName()=="Anonymous"}]]></xp:this.rendered>
			<xp:this.href><![CDATA[?Open&login]]></xp:this.href>
		</xp:tabPanel>
		<xp:tabPanel label="Log out" id="logout">
			<xp:this.rendered><![CDATA[${javascript:@ClientType()=="Web" && session.getEffectiveUserName()!="Anonymous"}]]></xp:this.rendered>
			<xp:this.href><![CDATA[${javascript:"/names.nsf?logout&RedirectTo="+context.getUrl().toString()}]]></xp:this.href>
		</xp:tabPanel>
	</xp:tabbedPanel>

Debug af XPages

Når du udvikler XPages, så har du brug for følgende værktøjer til at debugge koden:

Mere om debug muligheder i denne Wiki

Tip
Sæt denne linie i dit CSS for at flytte Debug toolbaren til bunden:
div.debugToolbar {position:relative !important;}

Links

@DbLookup m.fl. returnerer en String eller et Array

Hvis du bruger eksempelvis en @DbLookup() funktion i almindelig Notes – så returnerer den altid et Array som du kan loope på. Men i XPages returnere funktionerne kun et Array hvis der er mere end én værdi – ellers returneres en String.

Dermed er du nødt til at teste på returværdien/datatypen hvergang du har brugt en af disse funktioner: @DbLookup, @DbColumn, @Trim, @Unique. For ikke at gøre koden unødig kompleks, så lav en lille general JavaScript funktion som denne

Se også dette indlæg: Work with DbColumn and DbLookup

 

XPage settings

Her er mine foretrukne settings til XPage udvikling

Application properties:

  • Brug ‘Display XPage runtime error page’ – det giver en bedre fejlbesked (indtil du laver din egen fejlside)
  • Brug ‘Use runtime optimized JavaScript and CSS’ – dette vil komprimere alle css+js filer og kun sende én fil til klienten. Dette øger performance, specielt på mobile devices.
  • Så længe din server ikke er presset, så vælg ‘Keep pages in memory’ 

 

Designer settings:

  • Vælg ‘XPages’ perspective fra ‘Window, Open Perspective’ i menuen

P.S. Denne side bliver løbende opdateret med nye settings 🙂

Links:

Tips for referencing elements in XPages JavaScript

I XPages bliver dine id’s ændret – dermed forbliver de unikke, også selvom du har brugt samme id i flere custom controls eller i en repeat control. Men det gør også at de ikke kan referere direkte til dit id. I stedet benyttes dette lille hack:

Client Side JavaScript

#{id:myElement}

Server Side JavaScript

getComponent( "myElement")

Eksempler:

  • dojo.byId(“#{id:myDiv}”)
  • #{javascript:getComponent(“my_id_here”).getClientId(facesContext)}

Flere eksempler på Matt Whites blog eller læs Work with documents and fields on the XPage på XPages Wiki