You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by Stephen Clout <st...@al.com.au> on 2004/08/23 02:52:02 UTC

Tapestry Comment

Hello

I would like to be able to dynamically choose which components to load 
at render time without resorting to a

@contrib:Choose <http://jakarta.apache.org/tapestry/doc/ComponentReference/contrib.Choose.html> statement listing every possibility.

To do this, I Dynamically load Pages at runtime, and use them as Components within other pages.

To achieve this, I have overridden BasePage to move the call to cycle.commitPageChanges() until after the call to render(writer, cycle)

/**
 * @see org.apache.tapestry.AbstractPage#renderPage(
 * 			org.apache.tapestry.IMarkupWriter, 
 * 			org.apache.tapestry.IRequestCycle)
 */
public void renderPage(IMarkupWriter writer, IRequestCycle cycle) {

	try
        {
         	// Move call to render() before commitPageChanges()
          	firePageBeginRender();
            	render(writer, cycle);
            	if (!cycle.isRewinding()) cycle.commitPageChanges();
        }
        finally
        {
            firePageEndRender();
        }
}

I have also created a custom component which can be used as follows:

<span jwcid="@PageImporter" pageName="ognl:content">

and whose implementation is as follows:

public abstract class PageImporter extends BaseComponent {

/**
 * 
 * @return The Name of the DynamicPage instance to render
 */
public abstract String getPageName();
		
	
/**
 * @see org.apache.tapestry.BaseComponent#renderComponent(
 *                         org.apache.tapestry.IMarkupWriter,
 *                         org.apache.tapestry.IRequestCycle)
 */
protected final void renderComponent(IMarkupWriter writer, IRequestCycle cycle) {
       
	String pageName = getPageName();
	if (pageName != null) 
	{
		DynamicPage page = (DynamicPage) cycle.getPage(pageName);
      	   	page.setContainer(this.getContainer());
      	   	try
		{
      	   		page.render(writer, cycle);
		}
      	   	finally
		{
      	   		// If we loaded a page, release it back to the page pool
      	   		page.setContainer(null);
    	   		IPageSource ps = cycle.getEngine().getPageSource();
		        ps.releasePage(page);
		}
	}
}
}

This hack seems to work pretty well, but I was wondering if there was a less hackish way of achieving this effect ?

I was also wondering if anybody else has come across the need to dynamically load components at runtime, and whether or not this could become a standard feature of Tapestry in a later release ?

An example usage of this feature would be a TappedPane that sourced its list of Tabs at runtime from a file system directory. 

Any comments or feedback would be greatly appreciated.

Kind Regards
Stephen Clout


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org


Re: Tapestry Comment

Posted by Mikaƫl Cluseau <nw...@nwrk.dyndns.org>.
Hello,

You can use the Block and RenderBlock components, they are done for 
this. An example near of yours (for more, see RenderBlock specification):

*** DynamicPage.java ***

public abstract class DynamicPage extends BasePage {
	public abstract Block getBlock();
}

*** DynamicPageOne.html ***

[WYSIWYG editor header]
<span jwcid="block@Block">
[Real page contents]
</span>
[WYSIWYG editor footer]

*** DynamicPageOnePage.java ***

public class DynamicPageOne extends DynamicPage {
	// DynamicPageOne.page uses this class
	public Block getBlock() {
		return getComponent("block");
	}
}

*** HomePage.java ***

public class HomePage extends BasePage {
	// Home.page uses this class

	// Do some implementation of getContentPageName()

	public Block getContent() {
		DynamicPage page = (DynamicPage)
			cycle.getPage(getContentPageName());
		return page.getBlock();
	}
}

*** Home.html ***
[...]
<span jwcid="@RenderBlock" block="ognl:content">
[replaced by dynamic content]
</span>
[...]

Stephen Clout wrote:
> Hello
> 
> I would like to be able to dynamically choose which components to load 
> at render time without resorting to a
> 
> @contrib:Choose 
> <http://jakarta.apache.org/tapestry/doc/ComponentReference/contrib.Choose.html> 
> statement listing every possibility.
> 
> To do this, I Dynamically load Pages at runtime, and use them as 
> Components within other pages.
> 
> To achieve this, I have overridden BasePage to move the call to 
> cycle.commitPageChanges() until after the call to render(writer, cycle)
> 
> /**
> * @see org.apache.tapestry.AbstractPage#renderPage(
> *             org.apache.tapestry.IMarkupWriter, *             
> org.apache.tapestry.IRequestCycle)
> */
> public void renderPage(IMarkupWriter writer, IRequestCycle cycle) {
> 
>     try
>        {
>             // Move call to render() before commitPageChanges()
>              firePageBeginRender();
>                render(writer, cycle);
>                if (!cycle.isRewinding()) cycle.commitPageChanges();
>        }
>        finally
>        {
>            firePageEndRender();
>        }
> }
> 
> I have also created a custom component which can be used as follows:
> 
> <span jwcid="@PageImporter" pageName="ognl:content">
> 
> and whose implementation is as follows:
> 
> public abstract class PageImporter extends BaseComponent {
> 
> /**
> * * @return The Name of the DynamicPage instance to render
> */
> public abstract String getPageName();
>        
>     
> /**
> * @see org.apache.tapestry.BaseComponent#renderComponent(
> *                         org.apache.tapestry.IMarkupWriter,
> *                         org.apache.tapestry.IRequestCycle)
> */
> protected final void renderComponent(IMarkupWriter writer, IRequestCycle 
> cycle) {
>           String pageName = getPageName();
>     if (pageName != null)     {
>         DynamicPage page = (DynamicPage) cycle.getPage(pageName);
>                 page.setContainer(this.getContainer());
>                 try
>         {
>                     page.render(writer, cycle);
>         }
>                 finally
>         {
>                     // If we loaded a page, release it back to the page 
> pool
>                     page.setContainer(null);
>                   IPageSource ps = cycle.getEngine().getPageSource();
>                 ps.releasePage(page);
>         }
>     }
> }
> }
> 
> This hack seems to work pretty well, but I was wondering if there was a 
> less hackish way of achieving this effect ?
> 
> I was also wondering if anybody else has come across the need to 
> dynamically load components at runtime, and whether or not this could 
> become a standard feature of Tapestry in a later release ?
> 
> An example usage of this feature would be a TappedPane that sourced its 
> list of Tabs at runtime from a file system directory.
> Any comments or feedback would be greatly appreciated.
> 
> Kind Regards
> Stephen Clout
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org