From: Chris W. <ch...@cw...> - 2003-05-29 20:48:24
|
Teemu wrote: > I spent quite some time today to figure out how to process a template for a > return value while calling an OI component. Sorry it took you so long. From what you describe it seems to be a scoping issue. > Basically, I try to create a OI component that returns the browser specific > CSS for every site. I have the following in base_main: > > [% OI.comp('ua_select_css') %] > > With this I will call an action called ua_select_css (in class > OpenInteract::Handler::UserAgent), which detects the client browser and feeds > the ua_select_css template with params {browser => $browser}. Okay, with you so far. > ... > link_rel is just an action that returns the generated CSS2 stylesheet with > correct content-type etc. If my browser is IE, the above TT code will produce > the following output: > > <link rel="stylesheet" type="text/css" href="/link_rel/?link=ie.css" /> > > Now my problem is how to retrieve ua_select_css (while in > OpenInteract::Handler::UserAgent->ua_select_css), process it and return the > processed output to base_main. Still with you. > I tried the following: > > sub ua_select_css { > .... > return $R->template->handler( {}, $params, > { name => 'my_base::ua_select_css' } ); > } > > But it didn't work. Some strange error ended up in error_log and OI ceased to > function: > > --EXITED WITH ERROR from main handler eval block > Error: Cannot process template!file error - Template with name [javascript] > not found. > > [javascript] should be a [% BLOCK javascript %] in my base_main, which makes > me wonder why it was not found... Well, this makes sense. The OI.comp() call is treated like a normal subroutine -- it has no idea of the Template scope from which it was called. (Technically it does, but not that you can use.) Your [% BLOCK javascript %] needs to be in scope of the template you're processing, in this case 'my_base::ua_select_css'. I'm not sure why you need it -- if the block is generating Javascript that your component will use, that's okay. Once OI is done calling components and rendering all your javascript will be in the generated page's scope and therefore callable. > Ok. I browsed the OpenInteract::Template::Process code for help and tried the > following (in place of template->handler): > > my $output; > my $template = $R->template->initialize; > $template->process( 'my_base::ua_select_css', $params, \$output ); > return $output; > > It worked! Now I ask, why didn't template->handler work through a component > call? Is the above method I used correct or is there a better way to do this? No, the above method is definitely not correct. When you call $R->template->handler() OI does a number of things for you to setup the template environment, and it also uses the same template object over and over. Using the same template object again and again ensures that we don't have to parse templates multiple times since they'll be in the cache. And $R->template->initialize() is only called at server/apache-child startup to initialize that single template object -- it also does work to ask each package if it has any TT plugins to initialize and some other tasks I can't remember right now. > Also, I noticed a problem in Pod documentation of > OpenInteract::Template::Process: > > initialize( \%config ) > ... I'll change this to emphasize that web developers should never call it for the reasons stated above. > ... %config could actually be > very nice for initialize if I could pass some parameters to Template->new() > through it. Something like: > > my $template = $R->template->initialize(TRIM => 1); > > Would enable TT to trim generated output. Is there currently a way to do this? Yes. You can define in your server config an initialization class/method that gets called at server/apache-child startup and passed the \%config which it can manipulate. So you can do something like this: [template_info] ... custom_init_class = MyTemplateStuff custom_init_method = initialize and put a class like this in @INC: package MyTemplateStuff; use strict; sub initialize { my ( $class, $tt_config ) = @_; $tt_config->{TRIM} = 1; } Hope that makes sense, and good luck! Chris |