Access non-local data from templates

70 views
Skip to first unread message

Behrad Zari

unread,
Jan 14, 2013, 4:21:40 PM1/14/13
to zotoni...@googlegroups.com
We have an external data (not stored in local db as resources, ...) that should be presented to user in our zotonic site, I was dreaming to find a way not to explicitly postback to a server, which results to do presentation stuff in your server side code, but instead use simple expressive tpl like: m.search, m.rsc, ... to retrieve my data.
I knew a robust method would be creating a new zotonic model module with some functions and use them like rsc, ... 
Today I firstly got happy when I saw m_notifier

{% for item in m.notifier.map[{footer_navigation current_location=id}] %}
    {% include "footer_item.tpl" item=item %}
{% endfor %}

but when I wrote a sample I got that return values from observers are behaved as strings, not pure erlang tupples! I was expecting e.g. each item 
in the example above be exactly what data that was returned from the observer! 
Am I misunderstanding? can I clone m_notifier to get desired behaviour? or any available solutions ready in Zotonic now?

Arjan Scherpenisse

unread,
Jan 14, 2013, 4:32:41 PM1/14/13
to zotoni...@googlegroups.com
Hey Behrad,

I don't see your problem..? The m_notifier is very straightforward, it
just passes the value from the :map or :first straight into your
template. I tested this and it indeed works like that.

To see the value returned from the notifier, just use the print tag:

{% for item in m.notifier.map[{footer_navigation current_location=id}] %}
{% print item %}
{% endfor %}


In mycase I saw [{complex_value,123}] when I did


{% for item in m.notifier.map[{foo}] %}
{% print item %}
{% endfor %}

and the observing module had

observe_foo({foo, []}, _C) ->
[{complex_value, 123}].


Hope this helps!
Arjan

Andreas Stenius

unread,
Jan 14, 2013, 4:43:32 PM1/14/13
to Zotonic users
Not exactly sure what you want, or how m_notifier works, but perhaps
mod_signal would work for you here.. ?
http://zotonic.com/docs/0.9/ref/modules/mod_signal.html

with that you can connect actions in your template to signal emitted
either from code on the server, or from other templates.
And, as I'm sure you are aware, those actions could update the page
the visitor is viewing..


2013/1/14 Behrad Zari <beh...@gmail.com>:

Andreas Stenius

unread,
Jan 14, 2013, 4:46:47 PM1/14/13
to Zotonic users
Aw! How cool!

This opens up yet another dimension to templates!
Can't believe I've overlooked this model for so long.

Thank you Behrad for bringing it to my attention :D

2013/1/14 Arjan Scherpenisse <ar...@scherpenisse.net>:

Behrad Zari

unread,
Jan 15, 2013, 12:25:07 PM1/15/13
to zotoni...@googlegroups.com
@Arjan, You are right! May be this was my misunderstanding on accessing erlang data in template language!
Then how can I access item.complex_value !?
{%print item.complex_value %} didn't work!
and what If my item was: { my_inner_tupple, { name, "Behrad" } } !!?

You know!? I want to find the best way to move data in erlang (proplists maybe?) to templates to easily access them!

Behrad Zari

unread,
Jan 15, 2013, 12:31:36 PM1/15/13
to zotoni...@googlegroups.com
@Andreas, Yeaaaaah Andreas! I really felt RICH when I found it. 
And I'm already heavily using mod_signal, thank you for your suggestion, since our
application is an event-based, rich, comet-like desktop!
But I didn't prefer signals for this kind of problem in my hands, where I would like
to trigger a server side data aggregator from templates and expressively represent
then in simple html! (I may either like to write our custom scomps for this to happen)
But whit mod_notifier I easily can populate my combos, ... with external data in my templates!

huh, am I right?

Arjan Scherpenisse

unread,
Jan 16, 2013, 6:37:31 AM1/16/13
to zotoni...@googlegroups.com
Indeed, tuples are not easily accessed in the template language.

Although you use the 'element' filter to get specific elements out of
tuples:

http://zotonic.com/docs/0.9/ref/filters/filter_element.html

But returning just (nested) proplists from notifier observers is indeed
a lot easier:

observe_foo({foo, []}, _C) ->
[{value, [{name, "Behrad"}]}].

Would allow you to access your value with

{% for item in m.notifier.map[{foo}] %}
{% print item.value.name %}
{% endfor %}

Should print just "Behrad".

Arjan

Behrad Zari

unread,
Jan 20, 2013, 3:07:21 PM1/20/13
to zotoni...@googlegroups.com
Thank you Arjan for your quick & helpful answers!
And what if the key is an atom like:
observe_foo({foo, []}, _C) -> 
     [{value, [{ 'my-key' , "Behrad"}]}]. 

I tested this and didn't work for me:

{% for item in m.notifier.map[{foo}] %} 
                {% print item.value['my-key'] %} 
{% endfor %} 

Since I knew item.value[ "my-key" ] works for list keys like:  [{value, [{ "my-key" , "Behrad"}]}]. 

Amiramix

unread,
Jan 22, 2013, 8:49:14 AM1/22/13
to zotoni...@googlegroups.com
I am not sure if those will be useful for you but some time ago I made some notes to document how the model functions works:


{% with m.nodes.test1 as result %}

Calls m_find_value with SearchProps:test1 and M:{m,m_nodes,undefined}


{% with m.nodes[1].test2 as result %}

Calls m_find_value with SearchProps:1 and M:{m,m_nodes,undefined}, and then m_find_value with SearchProps:test2 and M:{m,m_nodes,{1,2,3}} where {1,2,3} is the result from the first call to m_find_value


{% with m.nodes[{test5 param=test6|default:"def_value"}] as result %}

Calls m_find_value with SearchProps:{test5,[{param,”def_value”}]} and M:{m,m_nodes,undefined}


{% with m.nodes.test7|test8 as result %}

Calls m_find_value with SearchProps:test7 and M:{m,m_nodes,undefined}, and then passes the result to method test8/2 in module filters/filter_test8.erl This is followed by a call to m_to_list with M:{m,m_nodes,{1,2,3}} where {1,2,3} is a result previously returned from m_find_value


Also, don't forget that you can pass Erlang terms to the actual template while it is generated, e.g.:

    Template = z_context:get(template, Context2),
    [_|Tokens] = binary:split(list_to_binary(wrq:path(ReqData)), <<"/">>, [global]),
    Vars = [{tokens, Tokens}|z_context:get_all(Context)],
    Html = z_template:render(Template, Vars, Context2),

This passes the tuple {tokens, [Token1, Token2, ...]} to the actual template. Then in the template you can access it like this:

<div id="grid" class="claro data-table no-scroll {{tokens[2]}}-{{tokens[3]}}-{{tokens[5]}}"></div>

Behrad Zari

unread,
Jan 22, 2013, 1:25:59 PM1/22/13
to zotoni...@googlegroups.com
Thank you for your valuable information Amiramix,
But what I actually needed was to access an atom key whose name is not a valid atom identifier, of a proplists in templates.
consider you have a item = [ { 'my-key', 123 } ],
which you can't access it like {{  item.my-key }}

and I solved it this way (using filters): {{ item[ "my-key"|as_atom ] }}

Andreas Stenius

unread,
Jan 22, 2013, 2:28:42 PM1/22/13
to Zotonic users
2013/1/22 Behrad Zari <beh...@gmail.com>:
> Thank you for your valuable information Amiramix,
> But what I actually needed was to access an atom key whose name is not a
> valid atom identifier, of a proplists in templates.
> consider you have a item = [ { 'my-key', 123 } ],
> which you can't access it like {{ item.my-key }}
>
> and I solved it this way (using filters): {{ item[ "my-key"|as_atom ] }}

uh oh. So this didn't work?

>>> {% print item.value['my-key'] %}

Just to make sure, did you try with backquote `, or single quote ' ?
(hint: it should be backquotes)
Not sure if this is in the docs at a proper location, but I found this
ref to it: http://zotonic.com/docs/0.9/dev/releasenotes/rel_0.7.0.html?highlight=atoms#other-minor-features

(Sorry that I didn't spot this when you originally posted it, as it
just occured to me to check if you used single quote or back quote in
the message)

JRad

unread,
Jan 22, 2013, 2:44:09 PM1/22/13
to zotoni...@googlegroups.com
oh! I did check it with single-quote and it complains about syntax error. I didn't know that it should work with backquotes!
I will test it tomorrow! ;)

Behrad Zari

unread,
May 17, 2013, 5:51:10 AM5/17/13
to zotoni...@googlegroups.com
Are you using m.notifier.map ? If yes, the returned result from your observe_foo would be wrapped in a list.
If you are using m.notifier.first make sure your binary is properly unicode formatted. You can see what is returned to your template with {{ value | pprint }} 
you may also test if {{ value | stringify }} works.

On Thursday, May 16, 2013 10:57:03 PM UTC+4:30, Kirill Sysoev wrote:
Hi All

Found this thread very informative. 
m_notifier is really very straightforward and powerful but got a little problem while using it with utf8 strings (Russian in my case).
If I am just passing utf8 binary string as a result of an observe_foo function (for example <<208,158,208,158,208,158>>) it is still presented as binary at html web page.

At the same time, if I am passing such variable through controller -> z_template:render, I am having readable content at my web page.

Could anyone advise a work around?

Best,
Kirill 

вторник, 15 января 2013 г., 1:32:41 UTC+4 пользователь Arjan Scherpenisse написал:
Reply all
Reply to author
Forward
0 new messages