You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Andrea Chiumenti <ki...@gmail.com> on 2007/05/31 12:03:08 UTC

dynamic component injection

Hello I'd like to konw if in Tap 4.1.2 there is a way do dynamically
render components inside a page.

If yes, how ?

regards,
kiuma

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


Re: dynamic component injection

Posted by Martino Piccinato <ma...@gmail.com>.
tnx a lot Alejandro!

this is exactly what I was looking for, block/renderblock components
combined with EventListener  can be really powerful stuff but I didn't
realize it until I read your example.

It's also very interesting the way you use that Editors page as a "block
component repository" and the ComponentAddress beans.

Re: dynamic component injection

Posted by Alejandro Scandroli <al...@gmail.com>.
Hi Guys,

I don't know if this is what are you looking for but here is how we
handle our "dynamic" components at Trails.

First we have a page which contains what we call "editors" (our
"dynamic" components):
http://svn.codehaus.org/trails/trunk/trails/modules/trails-core/src/main/resources/org/trails/page/Editors.html
http://svn.codehaus.org/trails/trunk/trails/modules/trails-core/src/main/resources/org/trails/page/Editors.page
They are all wrapped by @Blocks.

Then we have a map where the key is an ongl expression we use to
evaluate if that is right component for render a property, and  the
value is a ComponentAddress. The map definition is in our sping
configuration file.
Here is an example of one entry:
<entry>
	<key>
		<value>string and !large and !identifier</value>
	</key>
	<bean class="org.apache.tapestry.util.ComponentAddress">
		<constructor-arg index="0">
			<value>trails:Editors</value> <!-- it refers to Editors page -->
		</constructor-arg>
		<constructor-arg index="1">
			<value>stringEditor</value>
		</constructor-arg>
	</bean>
</entry>

So "stringEditor" is the name of the block we are going to look for in
our Editors page.

Then wherever we need to render one of those blocks we do:

<span jwcid="$content$">	
    <span jwcid="renderBlock@Block" block="ognl:block"/>
</span>

and

public Block getBlock()
{
	ComponentAddress componentAddress = get the ComponentAddress from the map.
componentAddress.findComponent(getPage().getRequestCycle()); //activate it.
// set all the properties you need to set

	return (Block) componentAddress;
}

That's all!
This is safe to use inside a For or Table or wherever you need to use it.

Of course an ognl expressions map is not a good fit for everyone, so
you can use whatever service you need to implement your logic as long
as it returns a ComponentAddress from the Editors page.

I hope this helps you.
Saluti.
Alejandro.


On 6/20/07, Martino Piccinato <ma...@gmail.com> wrote:
> did you find any cleaner way to do this?
>
> I think this problem is not just related to "one page applications" but
> apply also to any page/component that depending un user actions must show
> different enough content (unless one wants to go with EventListener and a
> long  ugly list of IF components...)
>

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


Re: dynamic component injection

Posted by Martino Piccinato <ma...@gmail.com>.
did you find any cleaner way to do this?

I think this problem is not just related to "one page applications" but
apply also to any page/component that depending un user actions must show
different enough content (unless one wants to go with EventListener and a
long  ugly list of IF components...)

Re: dynamic component injection

Posted by Andrea Chiumenti <ki...@gmail.com>.
Well I want to make a single page application, so componentns (the
body part of a page)
will be injected as reference by hivemind into different jars.

Playng a bit with Tapestry src I've found a better way to do this, but
I need some more testing (assets, listeners, etc).

I'm investigating on this kind of solution becase this will optimize
dojo loading with incremental load.

What do you thik about this ?

kiuma

Here it is the code
--------------------------------------------------------------------------
package org.jfly.sample.pages;


import org.jfly.sample.components.widgets.DynaRenderer;
import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.HiveMind;
import org.apache.hivemind.Location;
import org.apache.tapestry.AbstractPage;
import org.apache.tapestry.BaseComponent;
import org.apache.tapestry.IComponent;
import org.apache.tapestry.IMarkupWriter;
import org.apache.tapestry.INamespace;
import org.apache.tapestry.IPage;
import org.apache.tapestry.IRender;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.TapestryConstants;
import org.apache.tapestry.annotations.InjectObject;
import org.apache.tapestry.engine.IPageLoader;
import org.apache.tapestry.html.BasePage;
import org.apache.tapestry.pageload.ComponentClassProvider;
import org.apache.tapestry.pageload.ComponentClassProviderContext;
import org.apache.tapestry.pageload.PageLoader;
import org.apache.tapestry.resolver.ComponentSpecificationResolver;
import org.apache.tapestry.services.ComponentConstructor;
import org.apache.tapestry.services.ComponentConstructorFactory;
import org.apache.tapestry.services.ResponseBuilder;
import org.apache.tapestry.spec.ContainedComponent;
import org.apache.tapestry.spec.IComponentSpecification;
import org.apache.tapestry.spec.IContainedComponent;
import org.apache.tapestry.web.WebRequest;
import org.apache.hivemind.Messages;
import org.apache.tapestry.annotations.InjectObject;
import java.util.Date ;

/**
 * Start page of application pageInjection.
 */
abstract public class Home    extends BasePage {
    private IRender renderer;

    public IRender getRenderer() {
        return renderer;
    }
    public Date getCurrentTime() {
        return new Date();
    }

    @InjectObject("service:tapestry.page.ComponentClassProvider")
    public abstract ComponentClassProvider getComponentClassProvider();

    @InjectObject("service:tapestry.page.ComponentSpecificationResolver")
    public abstract ComponentSpecificationResolver getComponentResolver();

    @InjectObject("service:tapestry.enhance.ComponentConstructorFactory")
    public abstract ComponentConstructorFactory
getComponentConstructorFactory();

     @InjectObject("service:tapestry.page.PageLoader")
    public abstract IPageLoader getPageLoader();

    public IRender getDynaComp() {
        IRequestCycle cycle = getEngine().getInfrastructure().getRequestCycle();
        ComponentSpecificationResolver componentResolver =
getComponentResolver();
        IPageLoader pageLoader = getPageLoader();
        String componentType = DynaRenderer.class.getName();
        Location location = getLocation();
        componentResolver.resolve(cycle, getNamespace(),
componentType, location);

        INamespace componentNamespace = componentResolver.getNamespace();
        IComponentSpecification spec = componentResolver.getSpecification();

        IContainedComponent contained = new ContainedComponent();
        contained.setLocation(location);
        contained.setType(componentType);
        IComponent result = instantiateComponent(this, this, "message",
                spec, componentResolver.getType(), componentNamespace,
                contained);


        //IRender result =
getPageLoader().createImplicitComponent(cycle, this, "message",
DynaRenderer.class.getName(), getLocation());
        return result;
    }

    private IComponent instantiateComponent(IPage page, IComponent container,
            String id, IComponentSpecification spec, String type,
            INamespace namespace, IContainedComponent containedComponent)
    {
        ComponentClassProviderContext context = new
ComponentClassProviderContext(
                type, spec, namespace);
        String className =
getComponentClassProvider().provideComponentClassName(context);

        if (HiveMind.isBlank(className))
            className = BaseComponent.class.getName();
        else
        {

            Class componentClass =
getEngine().getInfrastructure().getClassResolver().findClass(className);

            if (!IComponent.class.isAssignableFrom(componentClass))
                throw new ApplicationRuntimeException(componentClass +
" is not a component class", container, spec
                        .getLocation(), null);

            if (IPage.class.isAssignableFrom(componentClass))
                throw new ApplicationRuntimeException("Not assignable
" + id, container, spec.getLocation(),
                        null);
        }

        ComponentConstructor cc =
getComponentConstructorFactory().getComponentConstructor(spec,
className);

        IComponent result = (IComponent) cc.newInstance();

        result.setNamespace(namespace);
        result.setPage(page);
        result.setContainer(container);
        result.setId(id);
        result.setContainedComponent(containedComponent);
        result.setLocation(containedComponent.getLocation());


        return result;
    }



}



On 5/31/07, Jesse Kuhnert <jk...@gmail.com> wrote:
> Hmm I'm not sure.   It doesn't look right but it's possible.  Wouldn't
> @Block be the easiest way to do it?  Or different instances of IRender ?
>
> On 5/31/07, Andrea Chiumenti <ki...@gmail.com> wrote:
> >
> > Is it right to do this ?
> > public IRender getDynaComp() {
> >         IRequestCycle cycle =
> > getEngine().getInfrastructure().getRequestCycle();
> >         IWorkerRender result;
> >         if ((cycle.getParameter("body") != null) &&
> > (!(cycle.getParameter("body").equals(""))) ) {
> >             result = from a service via IOC <----
> >             result.setRenderWorker(getRenderWorker());
> >         } else {
> >             result = new DynaRenderer(); //Default
> >             result.setRenderWorker(getRenderWorker());
> >         }
> >         return result;
> >     }
> >
> > of course components must not be abstract.
> >
> >
> > On 5/31/07, Andrea Chiumenti <ki...@gmail.com> wrote:
> > > Hello I'd like to konw if in Tap 4.1.2 there is a way do dynamically
> > > render components inside a page.
> > >
> > > If yes, how ?
> > >
> > > regards,
> > > kiuma
> > >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> > For additional commands, e-mail: users-help@tapestry.apache.org
> >
> >
>
>
> --
> Jesse Kuhnert
> Tapestry/Dojo team member/developer
>
> Open source based consulting work centered around
> dojo/tapestry/tacos/hivemind. http://blog.opencomponentry.com
>

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


Re: dynamic component injection

Posted by Jesse Kuhnert <jk...@gmail.com>.
Hmm I'm not sure.   It doesn't look right but it's possible.  Wouldn't
@Block be the easiest way to do it?  Or different instances of IRender ?

On 5/31/07, Andrea Chiumenti <ki...@gmail.com> wrote:
>
> Is it right to do this ?
> public IRender getDynaComp() {
>         IRequestCycle cycle =
> getEngine().getInfrastructure().getRequestCycle();
>         IWorkerRender result;
>         if ((cycle.getParameter("body") != null) &&
> (!(cycle.getParameter("body").equals(""))) ) {
>             result = from a service via IOC <----
>             result.setRenderWorker(getRenderWorker());
>         } else {
>             result = new DynaRenderer(); //Default
>             result.setRenderWorker(getRenderWorker());
>         }
>         return result;
>     }
>
> of course components must not be abstract.
>
>
> On 5/31/07, Andrea Chiumenti <ki...@gmail.com> wrote:
> > Hello I'd like to konw if in Tap 4.1.2 there is a way do dynamically
> > render components inside a page.
> >
> > If yes, how ?
> >
> > regards,
> > kiuma
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>


-- 
Jesse Kuhnert
Tapestry/Dojo team member/developer

Open source based consulting work centered around
dojo/tapestry/tacos/hivemind. http://blog.opencomponentry.com

Re: dynamic component injection

Posted by Andrea Chiumenti <ki...@gmail.com>.
Is it right to do this ?
public IRender getDynaComp() {
        IRequestCycle cycle = getEngine().getInfrastructure().getRequestCycle();
        IWorkerRender result;
        if ((cycle.getParameter("body") != null) &&
(!(cycle.getParameter("body").equals(""))) ) {
            result = from a service via IOC <----
            result.setRenderWorker(getRenderWorker());
        } else {
            result = new DynaRenderer(); //Default
            result.setRenderWorker(getRenderWorker());
        }
        return result;
    }

of course components must not be abstract.


On 5/31/07, Andrea Chiumenti <ki...@gmail.com> wrote:
> Hello I'd like to konw if in Tap 4.1.2 there is a way do dynamically
> render components inside a page.
>
> If yes, how ?
>
> regards,
> kiuma
>

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