Josh,

Yeah that looks like it would do it, working much like what proposed
with pagelinks. Given a choice I would use the pagelink based way
because architecturally it works the same (news page collects the id via
context), but using pagelinks reduces the round-trips and the need to
deal with events.
Janos if you're still listening ;-), I think we've found the best ways
possible to do what you want. The missing piece is that you said your
News component was a component and not a page, so in that case use a
page property (like Josh said) and in your page's template, testing for
a valid newsId, provide the News component with it. These are the best
methods we've seen, I just can't figure out why my mind keeps saying
there's a better way :-|.

chris

Josh Canfield wrote:
> Here's an app that does what I believe is trying to be done:
>
> // Page
> public class News {
>       @Property
>       private Integer _newsId;
>       public void onActivate(Integer newsId) {
>               _newsId = newsId;
>       }
>       
>       public Integer onPassivate() {
>               return _newsId;
>       }
> }
>
> // Page Template
> <?xml version="1.0" encoding="UTF-8" ?>
> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
>   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";>
>
> <html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";>
> <body>
> <t:newsQuote newsId="newsId" />
> </body>
> </html>
>
> // Component
> public class NewsQuote {
>
>       @Parameter
>       private Integer _newsId;
>
>       @Inject
>       private ComponentResources _resources;
>
>       void beginRender(MarkupWriter writer) {
>               writer.element("ul");
>               for (int i = 0; i < 5; ++i) {
>                       writer.element("li");
>                       Link link = _resources.createActionLink("show", false, 
> i);
>                       writer.element("a", "href", link.toURI());
>                       writer.write("News number " + i);
>                       writer.end();
>                       if (_newsId != null && _newsId.equals(i)) {
>                               writer.write(" You picked " + _newsId);
>                       }
>                       writer.end();
>               }
>               writer.end();
>       }
>       
>       // The Action handler
>       void onShow(Integer id) {
>               // stored into the bound parameter, feeding it back into the 
> page
>               _newsId = id;
>       }
> }
>
> The url http://localhost:8080/news/4
>
> Renders
>
> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";>
> <html xmlns="http://www.w3.org/1999/xhtml";>
> <head>
>   <link href="/assets/tapestry/default.css" rel="stylesheet" type="text/css">
> </head>
> <body>
> <ul>
> <li><a href="/news.newsquote:show/0?t:ac=4">News number 0</a></li>
> <li><a href="/news.newsquote:show/1?t:ac=4">News number 1</a></li>
> <li><a href="/news.newsquote:show/2?t:ac=4">News number 2</a></li>
> <li><a href="/news.newsquote:show/3?t:ac=4">News number 3</a></li>
> <li><a href="/news.newsquote:show/4?t:ac=4">News number 4</a> You picked 
> 4</li>
> </ul>
> </body>
> </html>
>
> Josh
>
> On Wed, Apr 30, 2008 at 2:49 PM, Chris Lewis <[EMAIL PROTECTED]> wrote:
>   
>> I do hope we've missed a simpler way, but I don't think it's surfaced
>> yet. Regarding parameters, how would that address the issue? NewsQuote
>> displays a collection of items as links that represent selectable items
>> (expressed as links). The action must be taken based on the user's
>> selection, so a component parameter doesn't apply here.
>> The event-based approach seems a theoretical perfect fit, but I can't
>> see how to do it without using @Persist (which Janos wants to avoid).
>> The only other thing I thought of is to have the NewsQuote component
>> generate pagelinks based on the containing page instead of action links.
>> This circumvents entirely the need for the events as the value will be
>> in the page context, does not not make 2 requests, and ultimately gets
>> the job done. It doesn't seem as elegant to me, but does the job and is
>> completely decoupled from the page.
>>
>> Still not sure if we've had our epiphany yet :-)
>>
>> chris
>>
>>
>> Josh Canfield wrote:
>>     
>>>> I mean really, how is that any simpler than
>>>> dealing directly with query parameters?
>>>>
>>>>         
>>> Hehe... I have to admit that I was solving a much more complicated
>>> problem than the original question, probably brought on by an earlier
>>> request about dynamic component rendering... I was shooting for
>>> completely decoupled context handling for an unknown assortment of
>>> components. Say you have 50 potential portlet components on a page
>>> that may get included multiple times and may or may not add to the
>>> context of the page, you probably don't want to manage that through
>>> individual page properties.
>>>
>>> Anyway,
>>> Isn't the straight forward solution to this problem to use component
>>> parameters as Joel pointed out? If your NewsQuote component accepts a
>>> newsId parameter, that binding is bi-directional. When the event
>>> occurs in the component it calls the setter of the bound parameter,
>>> which updates the value in the page and gets put back into the url via
>>> context returned by onPassivate. When the value is set during render
>>> time the component grabs the news item and renders it, if not it grabs
>>> the top five and displays them...
>>>
>>> Perhaps as Joel pointed out we're just making this too complicated and
>>> we should be the ones kicked out!
>>>
>>> Josh
>>>
>>> On Wed, Apr 30, 2008 at 1:27 PM, Chris Lewis <[EMAIL PROTECTED]> wrote:
>>>
>>>       
>>>> I see how this whole push on/pull off environment will solve the issue,
>>>> but it just seems so nasty. I mean really, how is that any simpler than
>>>> dealing directly with query parameters? I point at this only to
>>>> highlight that perhaps Janos has brought to light a legitimately rough
>>>> edge in T5, or else there's a cleaner way to do it and we're all just
>>>> missing it. I'm convinced that the event system is the way to go as it
>>>> seems a natural fit, but the redirect-after-action part is rendering it
>>>> useless without using @Persist! Let me share what I've put together, and
>>>> maybe someone will find the missing piece. I have a working test and
>>>> I'll abbreviate the code here and assume a few things:
>>>>
>>>> (coming in another message - i tripped the spam filter :-| )
>>>>
>>>>
>>>> Josh Canfield wrote:
>>>>
>>>>         
>>>>> Are you trying to keep the news id out of the url? Doesn't sound like
>>>>> it from your response to not doing the redirect. Since that's the
>>>>> case, why not add it to the page context?
>>>>>
>>>>> I suppose if you were building a portal with several components then
>>>>> keeping track of component parameters could get unwieldy. If you were
>>>>> showing a news article from the news portlet, and a stock highlight
>>>>> from the stock portlet... At that point you're sort of building a
>>>>> framework on a framework.
>>>>>
>>>>> You could build your page such that it accumulated context from it's
>>>>> components. Push a ComponentContext object into the Environment
>>>>> onActivate, and setupRender in your page (env gets cleared before
>>>>> render phase, not sure if there is a better way than doing it in
>>>>> both.) Then collect component parameter mappings. onPassivate for your
>>>>> page would organize and return these as it's context (you might want
>>>>> to sort them to get consistent results)
>>>>>
>>>>> Your url might look like this:
>>>>>
>>>>> http://localhost/context/mypage/cc/news/4527/stock/MCD
>>>>>
>>>>> Then onactivate you init the ComponentContext from the url keying off
>>>>> the "cc" to grab the remaining parameters and use them as key/value
>>>>> for the components. The your components do something like:
>>>>>
>>>>> @Environmental
>>>>> private ComponentContext _compContext;
>>>>>
>>>>> void setupRender() {
>>>>>   Long newsId = _compContext.getLong(_resources.getId());
>>>>> }
>>>>>
>>>>> void onPickNewsItem(Long id) {
>>>>>   _compContext.put(_resources.getId(), id);
>>>>> }
>>>>>
>>>>>
>>>>> Josh
>>>>>
>>>>> On Wed, Apr 30, 2008 at 5:23 AM, János Jarecsni
>>>>> <[EMAIL PROTECTED]> wrote:
>>>>>
>>>>>
>>>>>           
>>>>>> Hi Chris,
>>>>>>
>>>>>> I try to explain :)
>>>>>> Say, you have a "NewsQuote" component, which shows a few lines from the 5
>>>>>> latest news. At the and of each quotations, there a "More" link. Now, 
>>>>>> when
>>>>>> the user clicks on this link (an action link, for that matter), the
>>>>>> NewsQuote component will set a request scope info saying that the news 
>>>>>> with
>>>>>> ID=4527 is requested. And when it comes to the "News" component (it is 
>>>>>> able
>>>>>> to show the text of a given news in full), it simply looks at this piece 
>>>>>> of
>>>>>> info, and loads the news with id 4527 (or gets it from an app level cache
>>>>>> :)) and renders it.
>>>>>>
>>>>>> Hope it tells something about what I am up to :)
>>>>>>
>>>>>> thx
>>>>>> Janos
>>>>>>
>>>>>> 2008/4/30 Chris Lewis <[EMAIL PROTECTED]>:
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>             
>>>>>>> Honestly it's difficult for me to imagine a situation where I'd do that
>>>>>>> because it seems to violate a degree of encapsulation that tapestry
>>>>>>> imposes as a "freeing law" of the framework. The epicenter of that being
>>>>>>> that one should not think in terms of low-level idioms such as request
>>>>>>> parameters, and instead replace those with a higher level of application
>>>>>>> logic that eclipses them entirely (when possible). That's not to say
>>>>>>> that your perspective is flawed, but from the small bit of understanding
>>>>>>> I've taken from your posts I can't see why one would do what you want.
>>>>>>> The thing that I've been saying is missing here is, what are you trying
>>>>>>> to do? I don't mean technically, I mean what is the end result for the
>>>>>>> user? Understanding this is critical, but even if I don't your problem
>>>>>>> can still be solved by using a session to serve as an arbitrary holder.
>>>>>>> If you've settled on this architecture, why not write such a generic
>>>>>>> service and move on?
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>               
>> --
>> http://thegodcode.net
>>
>>
>>     
>
>
>
>   

-- 
http://thegodcode.net

Reply via email to