Filtering content in Text::Xslate - perl

In Mason i could define a filter:
<%filter Div($class)>
<div class="<% $class %>">
<% $yield->() %>
</div>
</%filter>
And later i could use it
% $.Div("row") {{
1 The "$yield->()" method returns everything from here (free text)
% $.Div("col") {{
2 even could have another nested filter, etc...
% }}
% }}
with result
<div class="row">
1 The "$yield->()" method returns everything from here (free text)
<div class="col">
2 even could have another nested filter, etc...
</div>
</div>
E.g. the $yield->() method returns everything what is inside of the enclosed filter.
Want achieve same functionality using Text::Xslate, but don't know how.
The closest thing what I found ,are the macro blocks where i could write:
: macro div -> ($cls,$str) {
<div class="<: $cls :>">
<: $str :>
</div>
: }
and use it as
: div("row",
: div("col",
: "my string"
: )
: )
but the my string must be quoted and : marked, so it is impossible to use any free html text. E.g. the following dies.
: div("row",
some free text here
: div("col",
nested
here
: )
: )
After the long introduction, the question is simple:
Exists in the Text::Xslate something as the Mason's $yield->() call, which returns the content of the enclosed filter call? (or if not exists, how i could mimic it?)

Related

web.py markdown global name 'markdown' is not defined

Im trying to use markdown together with Templetor in web.py but I can't figure out what Im missing
Documentation is here http://webpy.org/docs/0.3/templetor#builtins
import markdown
t_globals = {
'datestr': web.datestr,
'markdown': markdown.markdown
}
render = web.template.render(globals=t_globals)
class Blog:
def GET(self, post_slug):
""" Render single post """
post = BlogPost.get(BlogPost.slug == post_slug)
render = web.template.render(base="layout")
return render.post({
"blogpost_title": post.title,
"blogpost_content": post.content,
"blogpost_teaser": post.teaser
})
here is how I try to use markdown inside the post.html template
$def with (values)
$var title: $values['blogpost_title']
<article class="post">
<div class="post-meta">
<h1 class="post-title">$values['blogpost_title']</h1>
</div>
<section class="post-content">
<a name="topofpage"></a>
$:markdown(values['blogpost_content'])
</section>
But Im getting this exception
type 'exceptions.NameError' at
/blog/he-ll-want-to-use-your-yacht-and-i-don-t-want-this-thing-smelling-like-fish/
global name 'markdown' is not defined
You're re-initializing render, once in global scope setting globals and once within Blog.GET setting base. Do it only once!

Accessing form from directive

I need to access the current form (which may be nested) from within an angularjs directive. I know I can use
require: 'form'
or
require: '^form'
to go up a level but what if the directive I'm designing can live 1 level deep on one form and three levels deep on another?
require: '^form' or require: '^^^form' etc
How can I design my directive to require the nearest form to it?
Thanks!
It doesn't matter how far down the directive is nested. It will search up until it finds an ancestor with that controller, or it will throw an error.
So if you have a directive like this:
app.directive("formSpice", function () {
return {
restrict: "A",
require: "^form",
scope: {},
link: function (scope, element, attrs, ctrl) {
scope.formName = ctrl.$name;
}
};
});
And a your markup looks like this:
<form name="myForm">
<div class="well" form-spice>
<h3>Level 1 - Form Name: {{formName}}</h3>
<div class="well" form-spice>
<h3>Level 2 - Form Name: {{formName}}</h3>
<div class="well" form-spice>
<h3>Level 3 - Form Name: {{formName}}</h3>
</div>
</div>
</div>
</form>
It will still find the form in all three instances.
Live Demo

Call play2 template with variable arguments of type Html

How can I call a template with a variable number of arguments that have Html type in play?
I created a template in play2 defined like the following:
#(tabs: Html*)
<div class="btn-group" style="margin-bottom:20px">
#for((tab,index) <- tabs.zipWithIndex){
<a class="btn btn-mini btn-info active" id="display-hierarchy-#index" href="javascript:void(0)"><i class="icon icon-random icon-white"></i></a>
}
</div>
#for((tab,index) <- tabs.zipWithIndex){
<div id="display-hierarchy-tab-#index" class="onetab">
#tab
</div>
}
I tried to call it like
#views.html.tabs({
<a>tab1</a>
},{
<a>tab2</a>
})
I tried other varios combinations but it fails with:
type mismatch; found : scala.xml.Elem required: play.api.templates.Html
You can use a workaround:
Example call in a template file:
#TabsBuilder{
<a>tab1</a>
}{
<a>tab2</a>
}.map(tabs.apply)
The TabsBuilder:
package views.html
import play.api.templates.Html
class TabsBuilder(templates: Vector[Html]) {
def apply(html: Html) = new TabsBuilder(templates :+ html)
def map(f: Seq[Html] => Html) = f(templates)
}
object TabsBuilder {
def apply(html: Html) = new TabsBuilder(Vector(html))
}
The TabsBuilder enables you to write the code like you would have a variable number of parameter lists.

Symfony2 Forms: is it possible to bind a form in an "unconventional way"?

Imagine this scenario: in our company there is an employee that "play" around graphic,css,html and so on.
Our new project will born under symfony2 so we're trying some silly - but "real" - stuff (like authentication from db, submit data from a form and persist it to db and so on..)
The problem
As far i know, learnt from symfony2 "book" that i found on the site (you can find it here), there is an "automated" way for creating and rendering forms:
1) Build the form up into a controller in this way
$form = $this->createFormBuilder($task)
->add('task','text'),
->add('dueDate','date'),
->getForm();
return $this->render('pathToBundle:Controller:templateTwig',
array('form'=>$form->createview());
2) Into templateTwig render the template
{{ form_widget(form) }} // or single rows method
3) Into a controller (the same that have a route where you can submit data), take back submitted information
if($rquest->getMethod()=='POST'){
$form->bindRequest($request);
/* and so on */
}
Return to scenario
Our graphic employee don't want to access controllers, write php and other stuff like those. So he'll write a twig template with a "unconventional" (from symfony2 point of view, but conventional from HTML point of view) method:
/* into twig template */
<form action="{{ path('SestanteUserBundle_homepage') }}" method="post" name="userForm">
<div>
USERNAME: <input type="text" name="user_name" value="{{ user.username}}"/>
</div>
<div>
EMAIL: <input type="text" name="user_mail" value="{{ user.email }}"/>
</div>
<input type="hidden" name="user_id" value="{{ id }}" />
<input type="submit" value="modifica i dati">
</form>
Now, if into the controller that handle the submission of data we do something like that
public function indexAction(Request $request)
{
if($request->getMethod() == 'POST'){ // sono arrivato per via di un submit, quindi devo modificare i dati prima di farli vedere a video
$defaultData = array('message'=>'ho visto questa cosa in esempio, ma non capisco se posso farne a meno');
$form = $this->createFormBuilder($defaultData)
->add('user_name','text')
->add('user_mail','email')
->add('user_id','integer')
->getForm();
$form->bindRequest($request); //bindo la form ad una request
$data = $form->getData(); //mi aspetto un'array chiave=>valore
/* .... */
We expected that $data will contain an array with key,value from the submitted form.
We found that it isn't true. After googling for a while and try with other "bad" ideas, we're frozen into that.
So, if you have a "graphic office" that can't handle directly php code, how can we interface from form(s) to controller(s) ?
UPDATE
It seems that Symfony2 use a different convention for form's field name and lookup once you've submitted that.
In particular, if my form's name is addUser and a field is named userName, the field's name will be AddUser[username] so maybe it have a "dynamic" lookup method that will extract form's name, field's name, concat them and lookup for values.
Is it possible?
You can force Symfony2 to set the name of a form field, though I don't suggest it: $formBuilder->add('dummyfield', 'text', array( 'attr' => array('name' => 'yournamehere') ) );
Alternatively (also a bad idea), you can do this, which won't even let you use the form API: $this->getRequest()->get('whatever_the_field_name_is');
OR you can hackily add elements to the request based on the Sf2 generated names before binding it (copying the values that exist).
OR you can make use of the bind method of the form component (instead of bindRequest) as documented here.
But seriously...just use the formbuilder api. Your life will be easier, and isn't that what a framework is for? :)
Symfony 2 is based on twig as templating language. Let him use it :
{{ form_label(form.field) }}
will generate something like this :
<label for="field">field</label>
You can use all the available functions in order to render the form :
{{ form_label() }}
{{ form_widget() }}
{{ form_errors() }}
If you want to customize what is rendered by those functions, you can override twig templates as defined in the Symfony2 documentation.
Otherwise if you really want to something ugly, you can go for this kind of syntax :
{{ myform.vars.value.myField }}

opa : strange behaviour of dom element update

I have a strange behaviour with the code below:
function update(txt, _)
{
#text = <>{txt}</>
#data = <>{txt}</>
}
command = <a onclick={update("test1", _)}> change text1 </a> <+>
<a onclick={update("test2", _)}> change text2 </a>
content = <textarea style="width:30%;" rows=1 id=#text > filename </textarea>
<textarea style="width:100%;" rows=30 id=#data > This is a text area </textarea>
Server.start(
Server.http,
[
{page: function() {command <+> content}, title: "test" }
]
)
When I clik on the links "change text1" or "change text2", the text is updated in the two textareas, but as soon as I edit the value of one of these textareas, the update failed when I clik on the links.
Why ?
i think this is because once you have edited a textarea, the browser considers the "value" attribute of the textarea, and not the HTML content inside the textarea.
So in order to work, you should :
function update(txt, _)
{
Dom.set_value(#text, txt)
Dom.set_value(#data, txt)
}