/
usage.gtw
341 lines (246 loc) · 13.1 KB
/
usage.gtw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
~~LANG:FR@frman:composants/jforms/utilisation~~
jForms stores all form data in a cache. In your controller, you'll access these
data through a //form object//, instantiation of a class inheriting from
@@C@jFormsBase@@. That class is automatically generated by jForms by parsing
your XML file. As for DAO, the class is stored in a cache to optimize performance.
In your controller, you'll create, modify and destroy a //form object// with
@@C@jForms@@ static methods.
===== Forms and actions =====
As described in [[/modules/classic-forms|Classic forms]], you are advised to create a
set of actions to manage a form completely (name of actions below are not
mandatory of course, you could use which ever you want):
* "prepare" action. its role is to create a //form object// with jForms,
pre-fill the form if needed and redirect to "show" action.
* "show" action. it will first get the //form object// and use it in a
template to display its form and maybe user input errors of a preceding
submit. Upon user submit, "save" action will be called.
* "save" action. the //form object// is retrieved filled with user inputs
through a jForms method. Then, it could check data for errors. If so, it
will redirect to "show" otherwise it will process data (save it to database
for example) and redirect to "end".
* "end" action. it will destroy the //form object// (it will clean data
stored in session), and could display a confirmation of user posting or
anything else...
===== Create a form object =====
Before using jForms, it is required to have [[xml|an xml descriptive file]] and
that one of your action creates a form object associated. Such object is
returned form @@M@jForms::create()@@ static method.
As every other jForms static method, its first argument is a selector of an XML
file and accepts a second optional argument which is an id for your form object.
Say you have an XML file @@F@contact.form.xml@@ in "main" module:
<code php>
$form = jForms::create("main~contact");
</code>
@@V@$form@@ is an object of the class generated after parsing of XML file. that
class inherits from @@C@jFormsBase@@. With @@V@$form@@, you'll have an API to
manipulate form data.
In the example above, we don't use a second argument. As said it is optional. It
is only needed if you want to display a form on some already existing data. For
example, if you want to edit a product stored in database, you'll give its id to
jForms.
Why? Browsers allow to open multiple tabs. As a result, a user could open
the same product edit form more than once at the same time **but** on different
products. To prevent saving data in the same session object (thus loosing
inputs) for each opened form, you must set a unique id to the //form object//.
This id can be anything (a string, a number) but generally you'll use a SQL
record key.
If your XML is @@F@product.form.xml@@ located in shop module, here is an example
of a form object creation on an existing product:
<code php>
$form = jForms::create("shop~product", $product_id);
</code>
Off course, if you want to edit a new product, no need of an id:
<code php>
$form = jForms::create("shop~product"); // new product
</code>
Now, read again our previous example. We did not give an id to the contact form
because we assume in this case this form is used to send a contact request, so
it will always be an empty form.
===== Form initialization =====
After form creation, you may need to pre-fill it.
==== Simple initialization ====
Use @@M@setData()@@ method of your form object. Give it your control name as
first argument and its value as second.
<code php>
$form->setData("firstname","Laurent");
</code>
You can of course, retrieve value from a dao, a business class or anything else.
==== Initialization from a dao ====
If you retrieve values from a dao, there is a more efficient way to fill your
form. @@M@initFromDao()@@ method allows to fill multiple form fields. Indicate a
dao selector as first argument. The second argument should be the value of the
primary key of the record to retrieve, if the id of the form doesn't correspond
to this key (the key value can be an array of values if the primary key is on
several fields). So if you don't indicate a key, the id of the form will be took
as the key.
<code php>
$form = jForms::create("shop~product", $product_id);
$form->initFromDao("shop~products");
</code>
Form will be filled with values of the record whose id is @@V@$product_id@@ in
"shop~products" dao. You can also indicate a record object to @@initFromDao()@@
instead of a selector.
However, note that only controls whose name (or ref) are the same as dao
properties will be pre-filled. Others will stay untouched.
You could use more than one dao to fill your fields. Your form fields could
correspond to multiple tables in database for example.
==== Initialization of a multiple choice control ====
@@E@<checkboxes>@@ and @@E@<listbox multiple="true">@@ controls could be filled
with more than one value. (Beware, here we talk about values to be pre-selected
and not the list if choices label).
You can still use @@M@setData()@@ by giving an array of values to pre-select:
<code php>
$form->setData('categories', array(5, 8, 10));
</code>
But, commonly, those value lists reside in database and are retrieve from a
//join// statement. ie. a table having as primary key two or more foreign keys.
Each foreign key being a primary key of a different table. Imagine a table for
products ('products'), a table for product categories ('categories'), and a
product can belong to more than one category, you will construct a //join//
table ('products_categories'), associating product keys and category keys
(product_id and category_id).
If you want to fill your listbox or your checkboxes, you should read from
'products_categories' table. jForms provide a method on your form object to
achieve this @@M@initControlFromDao()@@:
<code php>
$form->initControlFromDao("categories", "shop~products_categories");
</code>
Of course, you should before define a "shop~products_categories" dao. jForms
expects as first dao key the one identifying a product and as second one the one
identifying a category. Even if it is not the case, you could give an array fo
key names as third arg to @@M@initControlFromDao()@@:
<code php>
$form->initControlFromDao("categories", "shop~products_categories", array('product_id','category_id'));
</code>
Note that this example is an edit product form. Here we assume that the form id
corresponds to a product id and as so @@M@initControlFromDao()@@ will use it as
search criteria to retrieve category id.
==== Defining choices for multiple choices controls =====
In [[xml|jforms xml file]], we have documented several ways to populate choices
of a @@E@<menulist>@@, a @@E@<listbox>@@, a @@E@<radiobuttons>@@ or a
@@E@<checkboxes>@@ controls (static data, dao, class).
Those could still be unsufficient. In that situation, declare neither
@@E@<item>@@ tag nor @@dao*@@ or @@class@@ attribute in you XML file. In your
controller, define your choices as follow:
<code php>
// retrieve your choices in an associative array,
$data = array(...);
// create an object that implement jIFormsDatasource2
$datasource = new jFormsStaticDatasource();
$datasource->data = $data
// retrieve the control and assign data
$form->getControl('control_name')->datasource = $datasource;
</code>
In @@V@$data@@, keys should be **value** of choices and values should be **label** of choices.
Note : you should do this in "show" action, ie. action that display your form.
==== Activate/Deactivate controls ====
There are situations where you do not want to display some controls of your
form. Use @@M@deactivate()@@ and @@M@isActivated()@@. Those two methods expect a
control name as argument. The latter return true if the control is activated. It
is useful for checking a submitted form. The first one activate or deactivate a
control. It accepts an optional parameter indicating whether to deactivate (if
true) or activate (if false).
<code php>
$form->deactivate('control_name');
// similar to
$form->deactivate('control_name', true);
// and to re-activate it :
$form->deactivate('control_name', false);
// check a control state :
if ($form->isActivated('control_name')) ...
</code>
===== Get an already created form =====
In a specific action, you have created your form object with
@@M@jForms::create()@@, but following actions need to get the same form object.
Two jForms methods for this purpose: @@M@get()@@ and @@M@fill()@@.
@@M@get()@@ retrieve simply your form object. As for @@M@create()@@, give it a form selector:
<code php>
$form = jForms::get("shop~product");
</code>
If you had given an id on creation, you'll have to give it also to @@M@get()@@:
<code php>
$product_id = $this->param('id'); // id has been transmitted through http
$form = jForms::get("shop~product", $product_id);
</code>
Note: @@M@get()@@ method returns null if the form does not exist. It probably means
that user has mistepped action where your form was created. You should then
redirect him to this action. Or directly create your form (this could prove
sufficient on simple forms).
<code php>
$form = jForms::get("main~contact");
if ($form === null) {
$form = jForms::create("main~contact");
}
</code>
@@M@fill()@@ method also returns a form object (in fact it calls
@@M@jForms::get()@@), but achieve another functionality: it fills form data with
all contents received through HTTP post or get request. Clear, it should be
called after user submit (see preceding section on form submit).
<code php>
$product_id = $this->param('id');
$form = jForms::fill("shop~product", $product_id);
</code>
Note: identifier (id here) is still transmitted manually but following jelix
versions should automate this.
==== Adding fields dynamically ====
The deactivation is the preferred method, because it is simpler, and by reading
the XML file, you know all used controls.
However, in some case you need to add several controls, for exemple repeated
controls, depending of external values. For example, in a form dedicated to a
news article, when you modify it, you would like to add an input for each label
of photos attached to this article. So you would add a control for each label,
depending of the number of photos.
In this kind of case, you have to instancy some new controls by hand, and add
them to the form, before to manipulate it in each action:
* retrieve the form with @@M@jForms::get()@@ or @@M@jForms::create()@@ (but not
@@M@jForms::fill()@@, see below)
* instancy an object which inherits from @@C@jFormsControl@@. There is a class
for each type of controls: @@C@jFormsControlInput@@, @@C@jFormsControlListbox@@,
@@C@jFormsControlRadiobuttons@@, @@C@jFormsControlHtmlEditor@@, etc. See the full
list in the reference documentation.
* add this object to the form object, with the @@M@addControl@@ method, or the
@@M@addControlBefore@@ method to add the control after a specific one.
* you can then display the form, or fill it with data of the request, by using
@@M@initFromRequest()@@.
You have to add these fields each time you create or retrieve the form. Indeed,
each time you retrieve the form with @@M@jForms::get()@@ or
@@M@jForms::fill()@@, jForms always instancy the form object generated by jForms
from what it is described in the XML file. So the form object doesn't contain
your fields. That's why you have to add your fields before the display, but also
before the retrieval of submitted data, so jForms know which data to retrieve.
1 – adding a field during the initialization:
<code php>
$form = jForms::get('myModule~myForm');
$ctrl= new jFormsControlinput('identifiant');
$ctrl->required=true;
$ctrl->datatype->addFacet('maxLength',255);
$ctrl->label='Identifiant';
$ctrl->size=100;
$form->addControl($ctrl);
</code>
2 – adding a field after the form submit :
<code php>
$form = jForms::get('myModule~myForm');
$ctrl= new jFormsControlinput('identifiant');
$ctrl->required=true;
$ctrl->datatype->addFacet('maxLength',255);
$ctrl->label='Identifiant';
$ctrl->size=100;
$form->addControl($ctrl);
$form->initFromRequest();
</code>
You can put the code which add the field, into a private method of your
controller, so you don't have to duplicate it in each action you use the form.
**Warning** : you mustn't use the @@M@fill()@@ method, because this method do a
@@M@get()@@ followed immediately by @@M@initFromRequest()@@, so it doesn't give
you the opportunity to add your field before the retrieval of data. If you call
it, your field won't receive corresponding data.
3 - During the dynamic fill of a control
If the form contain a list depending on an other control, a http request is made
to the jforms controller to fill this list.
During this action, the controller emit an event @@jformsPrepareToFillDynamicList@@
before to generate the list content and to return it to the browser. This
event allow to prepare the form object with all expected controls.
The event has these parameters:
* @@form@@: the form object.
* @@controlRef@@: the id of the control containing the list that will be generated.