PageRenderTime 42ms CodeModel.GetById 34ms app.highlight 3ms RepoModel.GetById 2ms app.codeStats 0ms

/doc/Templates-and-scomps.txt

http://github.com/zotonic/zotonic
Plain Text | 134 lines | 95 code | 39 blank | 0 comment | 0 complexity | 64d96372caf5aa764610b98778b1afed MD5 | raw file
  1= Templates and Scomps =
  2
  3The templates in Zotonic are based on django templates, using the excellent erlydtl library.
  4See http://code.google.com/p/erlydtl/ for the implemented tags and release notes.
  5
  6== Template Locations ==
  7
  8The templates are searched for in two different locations:
  9
 10/zotonic/default/templates/
 11/zotonic/priv/templates/
 12
 13Templates don't need to have an extension, they are just text files.  Templates can also be found in subdirectories, as long as you give the subdirectory name with the template.
 14
 15
 16== Scomps ==
 17
 18Scomp is shorthand for screen component. A scomp is a module implementing logic and templates.
 19Scomps can be included in the template using, for example:
 20
 21	{% @button text="Hello" action={growl text="Hello World" stay="1"} %}
 22	{% @button text=somevar action={growl text="Hello World" stay="1"} %}
 23
 24This button scomp has two parameters, text and action. The action parameter is a tuple with two additional parameters. 
 25
 26
 27== Implementing Scomps ==
 28
 29Scomps come in two different variations, caching and non-caching.
 30
 31You can implement scomps by using the behaviours scomp and caching_scomp.
 32
 33A scomp has the following four functions:
 34
 35	init(Args) -> {ok, State} | {error, Error}
 36	render(Params, Context, State) -> {ok, NewContext} | {error, Error}
 37	code_change(OldVsn, State, Extra) -> {ok}
 38	terminate(Reason, State) -> ok
 39	
 40		State = term()
 41		Params = proplist()
 42		Context = context()
 43
 44	depends(Params, Context) -> {NewParams, MaxAge, Depend} | false
 45
 46		Params = proplist()
 47		MaxAge = integer()
 48		Depend = TermList()
 49
 50
 51== Templates, Scomps and Request Context State ==
 52
 53During the evaluation of scomps we are able to:
 54
 55- wire action
 56- add script
 57- add validator
 58- add variable (accessible only by other scomps)
 59
 60After rendering a template it is inspected to find all scripts, actions and validators.  They are placed as #context records in the resulting iolist, the #contexts should be replaced by the 'render' record-attribute.  There will be a special 'script' atom to signify the place where all collected scripts will be inserted.  When the script atom is not found, then the result of the template
 61is a context, unless there are no collected scripts.
 62
 63Process state diagram, how all processes work together to render a scomp:
 64
 65Resource			Template						ScompServer			Scomp		Page/Session/User
 66	|
 67	|------------>	render(Template,ReqContext)
 68						|
 69						| ------------------------------- lookup missing var ---------->|
 70																						|
 71						|<------------------------------------- value ------------------|
 72						|
 73						|------------------> render(Scomp,ReqContext)
 74														|
 75														|---------> render(ReqContext)
 76														:				|
 77													(if cached)			|
 78														:				|
 79														|<--ReqContext--|
 80														|
 81														|
 82														|
 83														|
 84														|
 85						|<------------ Output ----------|
 86						|
 87					Filter scripts
 88					    |
 89	|<---- Output ------|
 90	|
 91 reply user agent
 92
 93
 94The scripts/actions/validators are similar to the ones defined with Nitrogen, though the record structure is redefined to accomodate easy construction by the Template compiler.
 95
 96
 97== Things to do ==
 98
 991. Change the variable lookup in erlydtl_runtime.erl - Done.
1002. Add extra parsing rules to erlydtl_parser.yrl - Done.
1013. Build the new LALR parser - Done.
1024. Add handling of scomp AST (abstract syntax tree) to erlydtl_compiler.erl - Done.
1035. Create the scomp server (no caching for the moment) - Done.
1046. Add script filter to z_template - Done.
1057. Make test scomps - Done.
106
107== Code generated for the scomp calls ==
108
109{% @button text="Hello" action={growl text="Hello World" stay=1} %}
110
111gives an AST of:
112
113	[{scomp,
114	     {identifier,{5,5},"button"},
115	     [{{identifier,{5,12},"text"},
116	       {string_literal,{5,17},"\"Hello\""}},
117	      {{identifier,{5,25},"action"},
118	       {{identifier,{5,33},"growl"},
119	        [{{identifier,{5,39},"text"},
120	          {string_literal,{5,44},"\"Hello World\""}},
121	         {{identifier,{5,58},"stay"},
122	          {number_literal,{5,63},"1"}}]}}]},
123
124Which should be translated to:
125
126	case z_scomp:render(button, [{text,"Hello"},
127								  {action, {growl, [{text,"HelloWorld"}, {stay,1}]} }
128							     ], Variables) 
129	of
130		{ok, Rendered} -> Rendered;
131		{error, Reason} -> io_lib:format("error: ~p", Reason)
132	end
133
134