1

I am having trouble getting my dynamic VF Component to space out the buttons for navigation on my page.

As you can see in the image below, it correctly outputs spaces between the Previous and Next buttons in the middle, but never any of the others...

enter image description here

here is a bigger view of the buttons:

enter image description here

Here is the controller code that generates those buttons...

Component.Apex.outputPanel opPanel = new Component.Apex.outputPanel();
opPanel.id = 'myButtons';

// ************
// SPACES
// ************
Component.Apex.outputPanel spacePanel = new Component.Apex.outputPanel();
spacePanel.id='opSpacePanel';
spacePanel.rendered= true; 

Component.Apex.OutputText htmlSpace=new Component.Apex.OutputText();
htmlSpace.value='   ';
htmlSpace.escape=false; 

spacePanel.childComponents.add(htmlSpace);

// ****************
// FIRST BUTTON
// ****************    
Component.Apex.outputPanel firstPanel = new Component.Apex.outputPanel();
firstPanel.id='opFirstPanel';
firstPanel.rendered=showPrev();
firstPanel.expressions.rendered='{!showPrev}'; 

Component.Apex.OutputText htmlBegTxtStart = new Component.Apex.OutputText(); 
htmlBegTxtStart.value = '<div class="block-link" id="BegButton" onmouseover="ButtonMouseOver(\'BegButton\');" onmouseout="ButtonMouseOut(\'BegButton\');" >';               
htmlBegTxtStart.escape = false;  

// Output a commandLink to run the code in the Previous() function
Component.Apex.CommandLink pbLinkFirst = new Component.Apex.CommandLink ();     
pbLinkFirst.style='color: rgb(255,255,255)';
pbLinkFirst.expressions.action = '{!Beginning}';
pbLinkFirst.value='|<';
pbLinkFirst.id = 'mynewButtonsFirst';

Component.Apex.OutputText htmlBegTxtEnd = new Component.Apex.OutputText(); 
htmlBegTxtEnd.value = '</div>';     
htmlBegTxtEnd.escape = false;         

firstPanel.childComponents.add(htmlBegTxtStart);
firstPanel.childComponents.add(pbLinkFirst);
firstPanel.childComponents.add(htmlBegTxtEnd);      

opPanel.childComponents.add(firstPanel);
opPanel.childComponents.add(spacePanel);

// ****************
// PREVIOUS BUTTON
// ****************
Component.Apex.outputPanel prevPanel = new Component.Apex.outputPanel();
prevPanel.id='opPrevPanel';
prevPanel.rendered=showPrev();
prevPanel.expressions.rendered='{!showPrev}'; 

Component.Apex.OutputText htmlPrevTxtStart = new Component.Apex.OutputText(); 
htmlPrevTxtStart.value = '<div class="block-link" id="PrevButton" onmouseover="ButtonMouseOver(\'PrevButton\');" onmouseout="ButtonMouseOut(\'PrevButton\');" >';               
htmlPrevTxtStart.escape = false;  

// Output a commandLink to run the code in the Previous() function
Component.Apex.CommandLink pbLinkPrev = new Component.Apex.CommandLink ();     
pbLinkPrev.style='color: rgb(255,255,255)';
pbLinkPrev.expressions.action = '{!Previous}';
pbLinkPrev.value='<';
pbLinkPrev.id = 'mynewButtonsPrev';

Component.Apex.OutputText htmlPrevTxtEnd = new Component.Apex.OutputText(); 
htmlPrevTxtEnd.value = '</div>';        
htmlPrevTxtEnd.escape = false;         

prevPanel.childComponents.add(htmlPrevTxtStart);
prevPanel.childComponents.add(pbLinkPrev);
prevPanel.childComponents.add(htmlPrevTxtEnd);      

opPanel.childComponents.add(spacePanel);
opPanel.childComponents.add(prevPanel);
opPanel.childComponents.add(spacePanel);

// ************
// NEXT BUTTON
// ************
Component.Apex.outputPanel nextPanel = new Component.Apex.outputPanel();
nextPanel.id='opNextPanel';
nextPanel.expressions.rendered='{!showNext}';
nextPanel.rendered= showNext(); 

Component.Apex.OutputText htmlNextTxtStart = new Component.Apex.OutputText(); 
htmlNextTxtStart.value = '<div class="block-link" disabled="{!disablePrevious}" rendered="{!showNext}" id="nextButton" onmouseover="ButtonMouseOver(\'nextButton\');" onmouseout="ButtonMouseOut(\'nextButton\');" >';      
htmlNextTxtStart.escape = false; 

// Output a commandLink to run the code in the Next() function
Component.Apex.CommandLink pbLinkNext = new Component.Apex.CommandLink ();     
pbLinkNext.style='color: rgb(255,255,255)';
pbLinkNext.expressions.action = '{!Next}';
pbLinkNext.value='>';
pbLinkNext.id = 'mynewButtonsNext';

Component.Apex.OutputText htmlNextTxtEnd = new Component.Apex.OutputText(); 
htmlNextTxtEnd.value = '</div>';        
htmlNextTxtEnd.escape = false;  

nextPanel.childComponents.add(htmlSpace);       
nextPanel.childComponents.add(htmlNextTxtStart);
nextPanel.childComponents.add(pbLinkNext);
nextPanel.childComponents.add(htmlNextTxtEnd);

opPanel.childComponents.add(nextPanel);
opPanel.childComponents.add(spacePanel);

//****************
//  LAST Button
//****************
Component.Apex.outputPanel lastPanel = new Component.Apex.outputPanel();
lastPanel.id='opLastPanel';
lastPanel.expressions.rendered='{!showNext}';
lastPanel.rendered= showNext(); 

Component.Apex.OutputText htmlLastTxtStart = new Component.Apex.OutputText(); 
htmlLastTxtStart.value = '<div class="block-link" id="lastButton" onmouseover="ButtonMouseOver(\'lastButton\');" onmouseout="ButtonMouseOut(\'lastButton\');" >';       
htmlLastTxtStart.escape = false; 

// Output a commandLink to run the code in the End() function
Component.Apex.CommandLink pbLinkLast = new Component.Apex.CommandLink ();     
pbLinkLast.style='color: rgb(255,255,255)';
pbLinkLast.expressions.action = '{!End}';
pbLinkLast.value='>|';
pbLinkLast.id = 'mynewButtonsLast';

Component.Apex.OutputText htmlLastTxtEnd = new Component.Apex.OutputText(); 
htmlLastTxtEnd.value = '</div>';        
htmlLastTxtEnd.escape = false;  

lastPanel.childComponents.add(htmlLastTxtStart);
lastPanel.childComponents.add(pbLinkLast);
lastPanel.childComponents.add(htmlLastTxtEnd);

opPanel.childComponents.add(spacePanel);
opPanel.childComponents.add(lastPanel);         
return opPanel;

so each time another button panel is output, it should also output the spaces panel:

opPanel.childComponents.add(spacePanel);

so what am I missing here, and how can I space out my buttons nicely?

  • 3
    Any reason why you're not using CSS to put margins in between your buttons? If you designate one class that you assign to each of your pagination buttons, you can probably use a single line of CSS to accomplish this, paginationButton + paginationButton { margin: 0 1em;} – Derek F Feb 8 '16 at 19:38
  • @DerekF: Thanks Derek, please would you add that as an answer with some explanation and an example, then I can accept it. – Our Man in Bananas Feb 8 '16 at 20:03
1

Not entirely sure why your current method isn't working.

It might have something to do with your spacePanel having a common id, and then being reused several times. The Id attribute of html tags needs to be unique throughout the page to be valid/standards-compliant, but I have no idea if an Id conflict can cause the issue that you're seeing.

That said, Cascading Style Sheets (CSS) is the right tool for the job here.

If you make use of a more specific version of the lobotomized owl selector (which has my vote for the best programming construct nickname), you can accomplish the spacing that you're looking for with a single line of CSS.

Taking a closer look at your provided code, the easiest way to do this is probably to put the following into your visualforce page:

<style>
    #myButtons * + * { margin-left: 1em;}
</style>
  • #myButtons selects the output panel that you assigned the Id myButtons to
  • * + * further selects any element that is immediately adjacent to another element. In other words, this will select everything except the first button
  • margin-left: 1em; puts 1 'em' of whitespace on the left side of the button. The em is a relative (to the font-size of the element in question) unit of measure, and is a particularly good idea to use if you expect a page to be viewed across many different devices (desktops, smartphones, tablets). If the current font-size is 16px, then 1 em = 16px.

With that, you can take out all of the opPanel.childComponents.add(spacePanel); lines in your controller code

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.