My xe:applicationLayout is in my demoLayout.xsp CC. The left column width is set in the .lotusColLeft class to 220px by default. I can manually override this setting by adding the following CC to any XPage that needs a 300px wide Left column:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<style>
.lotusColLeft { width:300px }
.hugeWidth { width:2000px }
.lotusContent { overflow-x: scroll; }
</style>
</xp:view>
This works nicely, but I actually need a 400 and 500 pixel wide Left column for some xpages. Yes, could do this with 3 CCs like the one above, but was hoping for a better approach where I can simply set the desired width in a custom property at the time I add my demoLayout.xsp CC control to my xpage.
Any ideas?
Rather than putting the style tag directly on the Custom Control, how about using a Computed Field control with escape="false" (i.e. output as HTML). Then, in the value property, you can computed the width of the left column. Something like this works for me:
<xp:text escape="false"><xp:this.value><![CDATA[
<style>
.lotusColLeft {width:#{compositeData.passedWidth};}
</style>]]>
</xp:this.value></xp:text>
You can then add a passedWidth property on the Custom Control and pass the relevant width in. You could get more sophisticated and set the loaded property of the Computed Field so it only shows if the passedWidth property has been set.
I like Paul's suggestion, but another approach would be to define two conditionally rendered stylesheet resources on your layout custom control (or just one, with a computed href). The control could have a property of leftColumnWidth that accepts values of "small", "medium", or "large". If small, no additional stylesheets are rendered. Otherwise it renders one of the two. This way if you ever need to change the exact width associated with either (as well as other elements that might make sense to tweak to suit the adjusted layout), you can just change it in the stylesheet without having to touch each page.
Related
I have a number of custom controls layed out on an xpage. I want these controls to be displayed in the order of a setting in a notes document
So my xpage might look like this in DDE
CustomControl1
CustomControl2
CustomControl3
CustomControl4
but when the custom control is displyed on the webpage the custom controls should be displayed in the following order (based on the setting document)
CustomControl4
CustomControl1
CustomControl2
CustomControl3
anyone have any ideas how to accomplish this (server side)
You can use the xp:switchFacet in combination with a xp:repeat to calculate the order at runtime like this:
<xp:repeat
id="repeat1"
rows="30"
var="rowEntry">
<xp:this.value><![CDATA[#{javascript:var arr = ["Control1","Control3","Control2"];return arr;}]]></xp:this.value>
<xe:switchFacet
id="switchFacet1"
selectedFacet="#{javascript:rowEntry}">
<xp:this.facets>
<xp:panel xp:key="Control1">Control1</xp:panel>
<xp:panel xp:key="Control2">Control2</xp:panel>
<xp:panel xp:key="Control3">Control3</xp:panel>
</xp:this.facets>
</xe:switchFacet>
</xp:repeat>
Instead of the Array arr you can use data based on a document or xsp.propertie. The Output of this code is Control1 Control3 Control2 and in your Designer you have your controls inside switchFacet in following order: Control1 Control2 Control3.
Without knowing the real pain of your project I can only assume that the individual position needs to be defined at runtime, or something like that.
In general: controlling a page's layout is a pure CSS job. On the resulting page almost anything can be positioned almost anywhere within the page's range, and it doesn't matter where it was placed at design time. So, if you enclose your custom controls within their own containers (panels / divs) then you should be all set. You might define positioning classes in CSS and then have some SSJS code decide which class is assigned to what div.
If for example you have a custom control for each day of the week, and you always want to have the current day at the top-most position, then you could define 7 css classes as in ".today", ".todayPlus1", ".todayPlus2" ... ".todayPlus6". Write your positioning rules for each class. And finally compute each panel's styleClass property based on the current week day.
I am working on a large, worldwide application, which includes access from areas of low bandwidth. As such, I want to use a minimum of SSJS or partial refreshes for all the complex hide/when calculations. Here is what I have so far for a simple "hide/when":
A Yes/No radio button, with CSJS to show a panel ("Yes") or hide the
panel ("No").
The panel has a formTable inside it, and the values are shown or hidden, as per #1.
In the XPage's onClientLoad, the following code is run:
// "getRadioValue" is a simple script to return the value of a radio button
var v_value = getRadioValue("#{id:radioButton}");
v_div = '#{javascript:getClientId("radioButtonPanel")}';
// show or hide div simply use dojo to change the display of the panel
if (v_value == 'Yes') {
showDiv(v_div);
} else {
hideDiv(v_div);
};
For a new document, the onClientLoad script will hide the "radioButtonPanel" successfully. Changing the radio button to "Yes" will show the radioButtonPanel, just as clicking "No" will hide it. It works great! :-)
Once the document is saved and reopened in read mode, though, the onClientLoad CSJS event should read the saved value in the document, and decide to show the panel or not. When the document is opened in edit mode, the onClientLoad fires, reads the radioButton value and successfully shows or hides the panel.
This is what I've tried so far, to get it to work in read mode:
In CSJS, using "#{javascript:currentDocument.getItemValueString('radioButton'}" to get the value,
Doing some calculations in the "rendered" or "visible" properties, but that's SSJS and, if hidden, prevents any of the "show/hideDiv" CSJS visibility style changes.
Adding an old fashioned "div" to compute the style (which is what I used to do before XPages), but since I can't do pass-thru html any more, I can't seem to get a CSJS calculation for the style. Ideally, I can do something like this:
<div id="radioButtonPanel" style="<ComputedValue>">
Where the ComputedValue would read the back end value of the document, and decide to add nothing or "display:none".
Note that I don't want to use viewScopes, since this long form would need many of them for all the other hide/when's.
Is there any way to make this 100% CSJS? I feel like I'm very close, but I wonder if there's something I'm just missing in this whole process.
First, rather than computing style, I'd recommend computing the CSS class instead -- just define a class called hidden that applies the display:none; rule. Then toggling visibility becomes as simple as a call to dojo.addClass or dojo.removeClass.
Second, I see that you're using the #{id:component} syntax to get the client ID of the radio button but using SSJS to get the client ID of the panel. Use the id: syntax for both; this is still just a server-side optimization, but if there are many instances of these calculations, it adds up. Similarly, replace #{javascript:currentDocument.getItemValueString('radioButton'} with #{currentDocument.radioButton}. Both will return the same value, but the latter will be faster.
Finally, any attribute of a pass-thru tag (any component with no namespace, like xp: or xc:) can still be computed, but you'll need to populate the expression by hand, since the editor doesn't know which attributes for valid for these tags, and therefore doesn't provide a graphical expression editor. So if the ideal way to evaluate the initial display is by wrapping the content in a div, the result might look something like this:
<div class="#{javascript:return (currentDocument.getValue('radioButton') == 'Yes' ? 'visible' : 'hidden');}">
<xp:panel>
...
</xp:panel>
</div>
Has anyone experienced an issue with disableOutputTag property where if you disable output tag for a computed field control inside a repeat control and have ssjs computed content inside that tag, it won't compute the content? Is disableOutputtag property only meant to work with static content inside a repeat control or is it a bug?
I don't know whether its a bug or not, but you can emulate the behavior of disableOutputTag by removing the ID attribute from and setting the disableTheme attribute to true. Maybe this helps you in short term.
EDIT: You can refer here for more information.
Not only does this happen when placing the xp:Text control inside a repeat but in also when you create a new XPage, add a xp:text onto it and define its value like:
<xp:text value="This is a test" disableOutputTag="true"/>
In the above example the xp:text will disappear. This is not what you would have expected. I would expect that only the value would be visible on the rendered page. But I think I can explain why this happens. Since there are no tags defined (disableoutputtag) somewhere in the rendered of this component it states that it should not generate anything. Because it can not bind its id to 'nothing' and so on.
Anyway, I could not think of a scenario where I would like to render plain text without any surrounding tags. It should at least be surrounded by a span or paragraph (<p>) tag so you can style it. And an ID would be nice so I can change the contents with a partial refresh.
I have a custom control that has a property I have defined. I use the composite data a label which is on the custom control. The label displays just fine but I wanted to use the value of the label on a control that is outside the control with the label and composite data.
But it is returning null for the value of the label. It seems like that composite data is being calculated every time the label value is accessed and the reference point for the calculation seems to be the control accessing the label value rather than the control where it is contained.
I plan to use scope variables instead but is there any way I can make composite data work?
Composite data only exists inside the custom control that defines it. As such, it is far easier to reach outward than to reach inward.
In addition to scope variables, an alternative is to define a dataContext. This is technically still a use of scope variables, as it pushes a variable temporarily into the requestScope, but is slightly easier to work with because you don't have to explicitly tell it to do so... it just does it. For example:
<xp:view
xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xp:this.dataContexts>
<xp:dataContext
var="labelValue"
value="#{someExpression}" />
</xp:this.dataContexts>
<xp:text
value="#{labelValue}" />
<xc:labelContainer
labelValue="#{labelValue}" />
</xp:view>
In the above example, everywhere within the container to which I've attached this labelValue dataContext, I can just refer to #{labelValue}, and it will return whatever value the expression for that dataContext returned. This provides you, then, a single variable that can be used within the XPage itself, but also passed into custom controls.
I like Tim's suggestion with the data context. However if you have to, you could access the value on the propertyMap of the control. This wouldn't be the label but the composite data. This is how components could 'talk back'
I have a Flex 4 TabBar component with a custom skin. In this skin, the item renderer is defined with an ButtonBarButton with a custom skin.
All the tabs in the itemrenderer have now the same width.
The client however wants me to make the tabs width dynamically, so a smaller tab for a smaller label, a bigger one for a long label.
Does anybody know how to adjust the width of Tab (ButtonBarButton)?
Thanks a million!
I found something that works.
Create a custom component that inherits from ButtonBarButton, call it CustomTabButton.
Add a bindable property tabWidth.
Then when we update tabWidth, the width of the tab is adjusted with it.
THis is how you update the skin:
set the host component to the custom class CustomTabButton.
In the SparkSkin definition, bind the width value to the hostComponents property tabWidth.
width="{hostComponent.tabWidth}"
The skin looks like this:
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
minHeight="54"
width="{hostComponent.tabWidth}"
xmlns:tabbar="be.boulevart.project.components.tabbar.*">
<!-- host component -->
<fx:Metadata>
<![CDATA[
[HostComponent("be.boulevart.project.components.tabbar.CustomTabButton")]
]]>
</fx:Metadata>