webmcp

view framework/env/ui/form.lua @ 12:f3d3203cd2e4

Documentation for partial loading added

NOTE: Previous changeset d76a8857ba62 also modified behaviour of ui.script: Scripts containing "]]>" are now rejected to avoid ambiguities
author jbe
date Fri Feb 19 16:43:29 2010 +0100 (2010-02-19)
parents d76a8857ba62
children 36ebcae1cde3
line source
1 --[[--
2 ui.form{
3 record = record, -- optional record to be used
4 read_only = read_only, -- set to true, if form should be read-only (no submit button)
5 external = external, -- external URL to be used as HTML form action
6 module = module, -- module name to be used for HTML form action
7 view = view, -- view name to be used for HTML form action
8 action = action, -- action name to be used for HTML form action
9 routing = {
10 default = { -- default routing for called action
11 mode = mode, -- "forward" or "redirect"
12 module = module, -- optional module name, defaults to current module
13 view = view, -- view name
14 id = id, -- optional id to be passed to the view
15 params = params -- optional params to be passed to the view
16 },
17 ok = { ... }, -- routing when "ok" is returned by the called action
18 error = { ... }, -- routing when "error" is returned by the called action
19 ... = { ... } -- routing when "..." is returned by the called action
20 },
21 partial = { -- parameters for partial loading, see below
22 module = module,
23 view = view,
24 id = id,
25 params = params,
26 target = target
27 },
28 content = function()
29 ... -- code creating the contents of the form
30 end
31 }
33 This functions creates a web form, which encloses the content created by the given 'content' function. When a 'record' is given, ui.field.* helper functions will be able to automatically determine field values by using the given record. If 'read_only' is set to true, then a call of ui.submit{...} will be ignored, and ui.field.* helper functions will behave differently.
35 When passing a table as "partial" argument, AND if partial loading has been enabled by calling ui.enable_partial_loading(), then ui._partial_load_js is
36 used to create an onsubmit event. The "partial" setting table is passed to ui._partial_load_js as first argument. See ui._partial_load_js(...) for
37 further documentation.
39 --]]--
41 local function prepare_routing_params(params, routing, default_module)
42 local routing_default_given = false
43 if routing then
44 for status, settings in pairs(routing) do
45 if status == "default" then
46 routing_default_given = true
47 end
48 local module = settings.module or default_module or request.get_module()
49 assert(settings.mode, "No mode specified in routing entry.")
50 assert(settings.view, "No view specified in routing entry.")
51 params["_webmcp_routing." .. status .. ".mode"] = settings.mode
52 params["_webmcp_routing." .. status .. ".module"] = module
53 params["_webmcp_routing." .. status .. ".view"] = settings.view
54 params["_webmcp_routing." .. status .. ".id"] = settings.id
55 if settings.params then
56 for key, value in pairs(settings.params) do
57 params["_webmcp_routing." .. status .. ".params." .. key] = value
58 end
59 end
60 end
61 end
62 if not routing_default_given then
63 params["_webmcp_routing.default.mode"] = "forward"
64 params["_webmcp_routing.default.module"] = request.get_module()
65 params["_webmcp_routing.default.view"] = request.get_view()
66 end
67 return params
68 end
70 function ui.form(args)
71 local args = args or {}
72 local slot_state = slot.get_state_table()
73 local old_record = slot_state.form_record
74 local old_readonly = slot_state.form_readonly
75 slot_state.form_record = args.record
76 if args.readonly then
77 slot_state.form_readonly = true
78 ui.container{ attr = args.attr, content = args.content }
79 else
80 slot_state.form_readonly = false
81 local params = table.new(args.params)
82 prepare_routing_params(params, args.routing, args.module)
83 params._webmcp_csrf_secret = request.get_csrf_secret()
84 local attr = table.new(args.attr)
85 attr.action = encode.url{
86 external = args.external,
87 module = args.module or request.get_module(),
88 view = args.view,
89 action = args.action,
90 }
91 attr.method = args.method and string.upper(args.method) or "POST"
92 if ui.is_partial_loading_enabled() and args.partial then
93 attr.onsubmit = slot.use_temporary(function()
94 local partial_mode = "form_normal"
95 if args.action then
96 partial_mode = "form_action"
97 slot.put(
98 'var element; ',
99 'var formElements = []; ',
100 'for (var i=0; i<this.elements.length; i++) { ',
101 'formElements[formElements.length] = this.elements[i]; ',
102 '} ',
103 'for (i=0; i<formElements.length; i++) { ',
104 'element = formElements[i]; ',
105 'if (element.name.search(/^_webmcp_routing\\./) >= 0) { ',
106 'element.parentNode.removeChild(element); ',
107 '} ',
108 '}'
109 )
110 local routing_params = {}
111 prepare_routing_params(
112 routing_params,
113 args.partial.routing,
114 args.partial.module
115 )
116 for key, value in pairs(routing_params) do
117 slot.put(
118 ' ',
119 'element = document.createElement("input"); ',
120 'element.setAttribute("type", "hidden"); ',
121 'element.setAttribute("name", ', encode.json(key), '); ',
122 'element.setAttribute("value", ', encode.json(value), '); ',
123 'this.appendChild(element);'
124 )
125 end
126 slot.put(' ')
127 end
128 slot.put(ui._partial_load_js(args.partial, partial_mode))
129 end)
130 end
131 if slot_state.form_opened then
132 error("Cannot open a non-readonly form inside a non-readonly form.")
133 end
134 slot_state.form_opened = true
135 ui.tag {
136 tag = "form",
137 attr = attr,
138 content = function()
139 if args.id then
140 ui.hidden_field{ name = "_webmcp_id", value = args.id }
141 end
142 for key, value in pairs(params) do
143 ui.hidden_field{ name = key, value = value }
144 end
145 if args.content then
146 args.content()
147 end
148 end
149 }
150 slot_state.form_opened = false
151 end
152 slot_state.form_readonly = old_readonly
153 slot_state.form_record = old_record
154 end

Impressum / About Us