Wiki source code of D2W Rules Reference - Cookbook - FAQ
Version 90.1 by Johan Henselmans on 2011/04/19 14:43
Show last authors
author | version | line-number | content |
---|---|---|---|
1 | === Rule Lists === | ||
2 | |||
3 | Below are some commonly used rules and information on keys which control D2W templates. You may wish to keep your own library of commonly used D2W rules, something like "D2WRuleLibrary.d2wmodel", which can then be used to copy and paste rules into your projects. | ||
4 | |||
5 | ==== For quick reference: ==== | ||
6 | |||
7 | ~1. How do I make my attributes and entities editable? | ||
8 | |||
9 | {{noformat}} | ||
10 | |||
11 | 100: true => isEntityEditable = true [com.webobjects.directtoweb.BooleanAssignment] | ||
12 | |||
13 | |||
14 | {{/noformat}} | ||
15 | |||
16 | 2. How do I make my relationships editable in ERD2W? (They are already are editable in D2W.) | ||
17 | Add two rules. This: | ||
18 | |||
19 | {{noformat}} | ||
20 | |||
21 | 90: task = 'edit' and smartRelationship.isToMany = 1 => componentName = "ERD2WEditToManyFault" | ||
22 | [com.webobjects.directtoweb.Assignment] | ||
23 | |||
24 | |||
25 | {{/noformat}} | ||
26 | |||
27 | and the below: | ||
28 | |||
29 | {{noformat}} | ||
30 | |||
31 | 90: task = 'edit' and smartRelationship != null and not (smartRelationship.isToMany = 1) => componentName = "ERD2WEditToOneRelationship" | ||
32 | [com.webobjects.directtoweb.Assignment] | ||
33 | |||
34 | |||
35 | {{/noformat}} | ||
36 | |||
37 | 3. Similarly how do I make my relationships display nicely in an Inspect page in ERD2W? By default they show up as an array fault. | ||
38 | There are many possible components to choose from. These are just a couple as an example. | ||
39 | Add two rules. This: | ||
40 | |||
41 | {{noformat}} | ||
42 | |||
43 | 90: task = 'inspect' and smartRelationship.isToMany = 1 => componentName = "ERD2WDisplayToManyList" | ||
44 | [com.webobjects.directtoweb.Assignment] | ||
45 | |||
46 | |||
47 | {{/noformat}} | ||
48 | |||
49 | and the below: | ||
50 | |||
51 | {{noformat}} | ||
52 | |||
53 | 90: task = 'inspect' and smartRelationship != null and not (smartRelationship.isToMany = 1) => componentName = "ERD2WDisplayToOne" | ||
54 | [com.webobjects.directtoweb.Assignment] | ||
55 | |||
56 | |||
57 | {{/noformat}} | ||
58 | |||
59 | 4. I don't like the defaults for attributes that D2W chooses. Sometimes it chooses wisely, but not always. How do I change what gets displayed for an entity's attributes? | ||
60 | |||
61 | The key is: displayPropertyKeys. This key represents a list of attributes to display for an entity. An example rule: | ||
62 | |||
63 | {{noformat}} | ||
64 | |||
65 | 100: entity.name = 'MyEntity' => displayPropertyKeys = ("attribute1","attribute2", "relationship1","relationship2.attribute3") [Assignment] | ||
66 | |||
67 | |||
68 | {{/noformat}} | ||
69 | |||
70 | Note that you can pick attributes across relationships. You now have total control of what gets displayed. | ||
71 | |||
72 | 5. If you want to use [[WOL:Click to Open]] for your D2W project, you'll need to disable it when you are generating ERExcelLook pages or the resulting Excel file will be unreadable gibberish. | ||
73 | |||
74 | The key is: clickToOpenEnabled. This key is on ERD2WPage and controls whether clickToOpen is enabled for that specific page. An example rule: | ||
75 | |||
76 | {{noformat}} | ||
77 | |||
78 | 10 : pageConfiguration like '*Excel*' => clickToOpenEnabled = false [com.webobjects.directtoweb.BooleanAssignment] | ||
79 | |||
80 | |||
81 | {{/noformat}} | ||
82 | |||
83 | 6. How do I control the list of visible Entities in my PageWrapper? My select entity popup is showing entities I don't want to be visible (ERAttachment, Lookup values, etc). | ||
84 | |||
85 | {{noformat}} | ||
86 | |||
87 | 100: *true* => visibleEntityNames = ("Foo","Bar","Baz","FooBar") [Assignment] | ||
88 | |||
89 | |||
90 | {{/noformat}} | ||
91 | |||
92 | 7. How do I easily use my own custom component in a Direct to Web page? | ||
93 | |||
94 | Step 1: | ||
95 | |||
96 | Add the following rules to your rule file: | ||
97 | |||
98 | {{noformat}} | ||
99 | |||
100 | 100: pageConfiguration = "ListTheEntity" and propertyKey = "theProperty" => componentName = "D2WCustomComponent" | ||
101 | 100: pageConfiguration = "ListTheEntity" and propertyKey = "theProperty" => customComponentName = "MyThePropertyComponent" | ||
102 | |||
103 | |||
104 | {{/noformat}} | ||
105 | |||
106 | Step 2: | ||
107 | |||
108 | Create a component in your project named 'MyThePropertyComponent' and give it an 'object' and 'key' binding. The object will receive the current object, and the key will receive the current propertyKey (as a string) from DirectToWeb. Do with them what you will. | ||
109 | |||
110 | {{code}} | ||
111 | |||
112 | public EOEnterpriseObject object() { | ||
113 | return (EOEnterpriseObject) valueForBinding("object"); | ||
114 | } | ||
115 | |||
116 | public String key() { | ||
117 | return (String) valueForBinding("key"); | ||
118 | } | ||
119 | |||
120 | {{/code}} | ||
121 | |||
122 | 8. How do I use features such as sections and tabs with the rules? | ||
123 | |||
124 | {{noformat}} | ||
125 | |||
126 | 100: (entity.name = 'Movie' and (task = 'inspect' or task = 'edit')) => subTask = "tab" | ||
127 | 100: (entity.name = 'Movie' and (task = 'inspect' or task = 'edit')) => tabSectionsContents = ( ("Foo", ("FooBar", "title", "category", "dateReleased"), ("FooBaz", "plotSummary", "posterName")), ("Bar", "revenue", "studio")) | ||
128 | |||
129 | |||
130 | {{/noformat}} | ||
131 | |||
132 | The second rule will give you: | ||
133 | |||
134 | Tabs: Foo, Bar | ||
135 | |||
136 | Sections under Foo: FooBar, FooBaz | ||
137 | |||
138 | Like: | ||
139 | |||
140 | FooBar | ||
141 | title | ||
142 | category | ||
143 | dateReleased | ||
144 | |||
145 | FooBaz | ||
146 | plotSummary | ||
147 | posterName | ||
148 | |||
149 | 9. A simpler way to specify this stuff is: | ||
150 | |||
151 | {{noformat}} | ||
152 | |||
153 | displayPropertyKeys = ("(section11)", "key11".... "(section2)", "key21") | ||
154 | |||
155 | and | ||
156 | |||
157 | displayPropertyKeys = ("[Tab1]", "(section11)", "key11".... "[Tab2]", "(section21)", "key21") | ||
158 | |||
159 | for tab pages. | ||
160 | |||
161 | {{/noformat}} | ||
162 | |||
163 | 10. Changing the display name for a PageConfiguration | ||
164 | |||
165 | You may want to use a Page Configuration Name that is consistent with the rules for your application (uses an EntityName), but it looks weird when it is parsed for display in the default way. | ||
166 | |||
167 | For example, in Bugtracker there is a page configuration named "EditMyPeople" which makes perfect sense for the rules, but not too much as an "Edit My Profile" page. The easy way around it is: | ||
168 | |||
169 | {{noformat}} | ||
170 | |||
171 | 100: (pageConfiguration = 'EditMyPeople' => displayNameForPageConfiguration = "Edit My Profile" | ||
172 | |||
173 | |||
174 | {{/noformat}} | ||
175 | |||
176 | However, it is better practice to get labels out of the rules altogether unless you want to make use of variables inside them. You put labels in your Localizable.strings file. If you just want plain text, no rule is necessary. For the following examples, "MyDocuments" is the pageConfigurationName. | ||
177 | |||
178 | {{noformat}} | ||
179 | |||
180 | Localizable.strings | ||
181 | "Pages.MyDocuments" = "List My Documents!"; | ||
182 | |||
183 | {{/noformat}} | ||
184 | |||
185 | This entry can be used with no associated rule and it will do the right thing. | ||
186 | |||
187 | If you want to use the @@session.variable.blah@@ in your pageConfigurationNames, you'll need to use a rule with a delayed assignment. | ||
188 | |||
189 | {{noformat}} | ||
190 | |||
191 | Localizable.strings | ||
192 | "Pages.MyDocuments" = "List @@session.loggedInUser.fullName@@'s Documents"; | ||
193 | |||
194 | Rule: | ||
195 | 100 : pageConfiguration = 'MyDocuments' => displayNameForPageConfiguration = "Pages.MyDocuments" [ERDDelayedLocalizedAssignment] | ||
196 | |||
197 | {{/noformat}} | ||
198 | |||
199 | ==== Adding a normal component to a ModernDirectToWeb App ==== | ||
200 | |||
201 | Suppose you have a component somewhere that you would like to use to a direct To Web App as an extra option, under the tab section. How do get this component to work with the rest of the Direct To Web App? | ||
202 | |||
203 | The way to do this is described in some [[mails>>http://lists.apple.com/archives/webobjects-dev/2011/Mar/msg00366.html]] , but it took me some time to understand all the intricacies, so here it goes: | ||
204 | |||
205 | We have a component HelloWorld, that consist of the following contents: | ||
206 | |||
207 | {{color value="#569191"}} | ||
208 | < | ||
209 | {{/color}} | ||
210 | |||
211 | {{color value="#115454"}}wo:WOForm{{/color}}{{color value="#569191"}}>{{/color}} | ||
212 | |||
213 | What is your name?{{color value="#569191"}}<{{/color}}{{color value="#115454"}}wo:WOTextField{{/color}} {{color value="#901291"}}value{{/color}} {{color value="#569191"}}={{/color}} {{color value="#c07212"}}"[username]"{{/color}}{{color value="#569191"}}/>{{/color}} | ||
214 | |||
215 | {{color value="#569191"}} | ||
216 | < | ||
217 | {{/color}} | ||
218 | |||
219 | {{color value="#115454"}}wo:WOSubmitButton{{/color}} {{color value="#901291"}}action{{/color}}{{color value="#569191"}}={{/color}}{{color value="#c07212"}}"[fixUsername]"{{/color}}{{color value="#569191"}}/>{{/color}} | ||
220 | |||
221 | {{color value="#569191"}} | ||
222 | </ | ||
223 | {{/color}} | ||
224 | |||
225 | {{color value="#115454"}}wo:WOForm{{/color}}{{color value="#569191"}}>{{/color}} | ||
226 | |||
227 | {{color value="#569191"}} | ||
228 | < | ||
229 | {{/color}} | ||
230 | |||
231 | {{color value="#115454"}}wo:WOConditional{{/color}} {{color value="#901291"}}condition{{/color}} {{color value="#569191"}}={{/color}} {{color value="#c07212"}}"[username]"{{/color}}{{color value="#569191"}}>{{/color}} | ||
232 | |||
233 | {{color value="#000000"}} | ||
234 | Hello | ||
235 | {{/color}} | ||
236 | |||
237 | {{color value="#569191"}}<{{/color}}{{color value="#115454"}}wo:WOString{{/color}} {{color value="#901291"}}value{{/color}} {{color value="#569191"}}={{/color}} {{color value="#c07212"}}"[userNameExtended]"{{/color}}{{color value="#569191"}}/>{{/color}} | ||
238 | |||
239 | {{color value="#569191"}} | ||
240 | </ | ||
241 | {{/color}} | ||
242 | |||
243 | {{color value="#115454"}}wo:WOConditional{{/color}}{{color value="#569191"}}>{{/color}} | ||
244 | |||
245 | \\ | ||
246 | |||
247 | {{color value="#8f1069"}} | ||
248 | import | ||
249 | {{/color}} | ||
250 | |||
251 | com.webobjects.appserver.WOContext; | ||
252 | |||
253 | {{color value="#8f1069"}} | ||
254 | import | ||
255 | {{/color}} | ||
256 | |||
257 | er.extensions.components.ERXComponent;\\ | ||
258 | |||
259 | {{color value="#8f1069"}} | ||
260 | public | ||
261 | {{/color}} | ||
262 | |||
263 | {{color value="#8f1069"}}class{{/color}} __HelloWorld__ {{color value="#8f1069"}}extends{{/color}} ERXComponent { | ||
264 | |||
265 | {{color value="#8f1069"}}private{{/color}} String {{color value="#2608ca"}}username{{/color}}; | ||
266 | |||
267 | {{color value="#8f1069"}}private{{/color}} {{color value="#000000"}}String{{/color}} {{color value="#2608ca"}}userNameExtended{{/color}}{{color value="#000000"}};{{/color}}\\ | ||
268 | |||
269 | {{color value="#8f1069"}}public{{/color}} HelloWorld(WOContext context) { | ||
270 | |||
271 | {{color value="#8f1069"}}super{{/color}}(context); | ||
272 | |||
273 | }\\ | ||
274 | |||
275 | {{color value="#8f1069"}}public{{/color}} ERXComponent fixUserName() { | ||
276 | |||
277 | {{color value="#549172"}}//create a new component, which will be sent to the user with it's name appended{{/color}} | ||
278 | |||
279 | HelloWorld aPage = (HelloWorld) pageWithName({{color value="#4a0ffe"}}"HelloWorld"{{/color}}); | ||
280 | |||
281 | {{color value="#549172"}}// we do not like WOBers without the name{{/color}} {{color value="#549172"}}{+}David{+}{{/color}} | ||
282 | |||
283 | {{color value="#000000"}} | ||
284 | | ||
285 | {{/color}} | ||
286 | |||
287 | {{color value="#000000"}}String newUserName={{/color}}{{color value="#4a0ffe"}}"Hello David-"{{/color}}{{color value="#000000"}}+username()+{{/color}}{{color value="#4a0ffe"}}"(There is no WOBber that doesn't have David in his firstname)"{{/color}}{{color value="#000000"}};{{/color}} | ||
288 | |||
289 | {{color value="#000000"}} | ||
290 | | ||
291 | {{/color}} | ||
292 | |||
293 | {{color value="#549172"}}//set the User Name on the new page{{/color}} | ||
294 | |||
295 | aPage.setUsername(newUserName); | ||
296 | |||
297 | {{color value="#8f1069"}}return{{/color}} aPage; | ||
298 | |||
299 | }\\ | ||
300 | |||
301 | {{color value="#8f1069"}}public{{/color}} String username() { | ||
302 | |||
303 | {{color value="#8f1069"}}return{{/color}} {{color value="#2608ca"}}username{{/color}}{{color value="#000000"}};{{/color}} | ||
304 | |||
305 | }\\ | ||
306 | |||
307 | {{color value="#8f1069"}}public{{/color}} {{color value="#8f1069"}}void{{/color}} setUsername(String username) { | ||
308 | |||
309 | {{color value="#8f1069"}}this{{/color}}.{{color value="#2608ca"}}username{{/color}} = username; | ||
310 | |||
311 | }\\ | ||
312 | |||
313 | {{color value="#8f1069"}}public{{/color}} String userNameExtended() { | ||
314 | |||
315 | {{color value="#8f1069"}}return{{/color}} {{color value="#2608ca"}}userNameExtended{{/color}}{{color value="#000000"}};{{/color}} | ||
316 | |||
317 | }\\ | ||
318 | |||
319 | {{color value="#8f1069"}}public{{/color}} {{color value="#8f1069"}}void{{/color}} setUserNameExtended(String userNameExtended) { | ||
320 | |||
321 | {{color value="#8f1069"}}this{{/color}}.{{color value="#2608ca"}}userNameExtended{{/color}} = userNameExtended; | ||
322 | |||
323 | } | ||
324 | |||
325 | } | ||
326 | |||
327 | Normally, this Component will pickup a username, and will create a correct user name. | ||
328 | |||
329 | Now suppose we want to make this component a Direct To Web Component. | ||
330 | |||
331 | First I will do the obvious: | ||
332 | |||
333 | I will add the component to the NavigationList: | ||
334 | |||
335 | { | ||
336 | |||
337 | name = Root; | ||
338 | |||
339 | children = ("Home","HelloWorld"); | ||
340 | |||
341 | }, | ||
342 | |||
343 | { | ||
344 | |||
345 | name = "HelloWorld"; | ||
346 | |||
347 | action = "HelloWorld"; | ||
348 | |||
349 | }, | ||
350 | |||
351 | { | ||
352 | |||
353 | name = "Home"; | ||
354 | |||
355 | action = "session.navController.homeAction"; | ||
356 | |||
357 | } | ||
358 | |||
359 | First insert/copy this component from your normal App to the Modern Direct To Web App. Next you have to make sure that the component will follow the normal flow of a Direct To Web App. The way to accomplish this is to refactor the ERXComponent or WOComponent by a ERD2WPage or D2WPage. This will make sure that the component gets the d2wcontext, that every D2WPage needs. | ||
360 | |||
361 | Next we add the page to the navigation menu, to the navigation controller and the rules in user.d2wmodel of our application | ||
362 | |||
363 | Finally, we make sure that every component call gets replaced by a D2W.Factory call | ||
364 | |||
365 | HelloWorld aPage = (HelloWorld) D2W.factory().pageForConfigurationNamed({{color value="#4a0ffe"}}"HelloWorld"{{/color}}, session()); | ||
366 | |||
367 | {{color value="#8f1069"}} | ||
368 | return | ||
369 | {{/color}} | ||
370 | |||
371 | aPage; | ||
372 | |||
373 | instead of | ||
374 | |||
375 | ==== ==== | ||
376 | |||
377 | ==== ERExcelLook specific rules ==== | ||
378 | |||
379 | [[Additional tips for ERExcelLook]] |