Change custom control in facet at runtime?

My app homepage will have four panels containing separate custom controls, mostly just displaying data from different views.

What I want to do is allow people to specify which panels should be displayed (sort of portal like). I’ll have more than 4 potential view custom controls they can select from, and they can choose which ones they want shown.

So my layout has four editable areas/facets where I can drop custom controls. Looks fine and is all good up to now.

But, is there any way of controlling which custom control is displayed, using profiles/applicationscope variables (or any other way).

One way I guess would be to create the (maybe 10) different view custom controls, then create 4 new custom controls for the display of these, with all the different available view custom controls imported into all 4 panel controls, and then calculate the visible property of each one (if that’s possible).

Would be easier to be able to programme the main page to display the individual view controls as needed though.

Any ideas?

Thanks, hope this is understandable

Subject: Use one facet and loaded= on each control…

  • I simulate computed subforms this way and it works a treat. Don’t know why your interactive app can’t set a scoped variable and do the same.

Hope this helps…

Subject: Details

Hi David

Thanks for the response - can you give me any more details, not quite sure what you mean (this is my first xPage app so not familiar with all the new features)

Cheers

Dan

Subject: That’s okay, this is my first XPage app as well…

  • I just don’t believe in starting small. (fool’s grin)

  • Let’s see if I can one-off this. I work almost exclusively in the Source tab, so I don’t know how to get the Design tab to do this, nor if it even will. The Design tab is a nightmare of poorly laid-out dialogs and insane numbers of mouse clicks, imho, so I refuse to use it unless there is no other choice. Fortunately I don’t have to! (happy smile)

  • So, you have a parent and a child; the child must be a custom control and the parent could be a custom control or a XPage. The child contains the facets, the parent contains the code to use the facets. I call them parent and child for reference only, since I have to call them something. You also need one custom control for each “changed” facet.

  • The child is first. I’ll call it “ChildControl”:

…[XPage code before facets]…

<xp:callback facetName=“one” id=“one” />

<xp:callback facetName=“two” id=“two” />

<xp:callback:facetName=“three” id=“three” />

…[XPage code after facets]…

When you look at this in the Design tab you’ll see three boxes in a row containing “one”, “two”, “three”, with little pencil and paper icons.

  • Now the parent:

…[XPage code before ChildControl]…

xc:ChildControl

xp:this.facets

  <xc:ControlForOne xp:key="one" loaded="${javascript:code returns true to use one}" />

</xp:this.facets>

xp:this.facets

  <xc:ControlForTwo xp:key="two" loaded="${javascript:code returns true to use two}" />

</xp:this.facets>

xp:this.facets

  <xc:ControlForThree xp:key="three" loaded="${javascript:code returns true to use three}" />

</xp:this.facets>

</xc:ChildControl

  • The above will load either one, two, or three with the XPage depending on the loaded=. Naturally one may use any number of facets, I show three because my application has three. Because this uses loaded= and not rendered=, there should be little performance penalty for large numbers of unused facets. The XSP processor should utterly ignore the unused ones.

  • I use this as a hack-around for computed subforms; my loaded controls are XPage code for the three different types of computed subforms, and the XPage is the Form that needs computed subforms. The XPage sets scoped variables with the data necessary to drive the javascript loaded= selectors to apply the correct subform for the document being loaded.

Hope this helps…

Subject: Thanks

Aplogies for taking so long to get back, didn’t have time to look at this until today

I like what you’ve done, although not sure it’ll work for me. Well, it might work but would be very complex.

What I’m trying to do is always display 4 different custom controls in 4 different panels, but each panel (facet) could display one of 10(ish) different controls. And they’re potentially ‘movable’ as well, so one person could have the four panels showing controls A,C,F,B in that order (they’re just horizontal across the screen) another would display F,G,A,B

So from what I can tell with your solution the parent would have to have 40 facets on it, with each block of 10 displaying a single facet that contained a control.

Could work (and probably would I guess), might have to try and think of a slightly more trimmed down version though…

Subject: I would try adding another layer…

  • Make one custom control with 10 facets that takes a parameter (via compositeData) to tell it which of the ten items to display. Include that control on the parent four times with arbitrary selection attributes.

  • It’s possible this will fail because of a namespace collision on the facets, but it’s worth a try.

  • Alternatively you may be able to make ten custom controls and put them on one custom control in place of the facets, with loaded= on those ten, and use that four times on the parent. I don’t recall that working for me, I think because I couldn’t get loaded= to work on a control, only on a facet inclusion, but that may be due to some misunderstanding on my part.

  • But if all else fails 40 facets it is. As mentioned, only the four that are actually loaded should consume noticeable server resources. The other 36 should be quickly run through without much impact. So it’s ungainly to code but the result should be good. Often times that’s how XPages seem to turn out … ungainly to code but work well enough.

  • I’ve also noticed the more complex I layer custom controls, the more unstable the system becomes, so I wouldn’t go any more layers of custom controls than is necessary to reach the goal. I originally built a nice framework of custom controls where it was trivial to swap controls around to re-arrange the entire web site, but that’s all gone now. I’m down to three layers from eight and it’s been stable ever since, but now each XPage is an ungainly mess of markup that is significantly more difficult to work with.

Hope this helps…

Subject: Many thanks

I think to be honest I’ll just go the 40 facets routes, name them all something different and use the loaded property from a sessionScope variable (which is how I’m managing most of the personal preference type stuff).

Haven’t got my head around the compositeData thing so not sure what you mean by that to be honest (I’m biting off far more than I can chew with this app, hopefully I won’t make a fool of myself:-))

Subject: Using rendered instead of loaded

Got it working, although have to use rendered property as the loaded property doesn’t update even with a full page refresh and this needs to be changed in real-time.

Subject: Ahh…

  • You’re doing refreshes and not full page loads. You would need rendered for that. Since you’re using rendered a partial refresh should work just as well. I do full page loads, as in a fresh URL, not refresh using the same URL, so loaded works for me…