1 | **Documentation**
|
2 |
|
3 | Clay uses an MVC framework to build Javascript web applications that
|
4 | fully communicate and integrate with Salesforce. This framework is the
|
5 | 3VOT-Model NPM package, which serves as the base to your apps, and the
|
6 | core of its MVC architecture is based on the Spine.js framework.
|
7 |
|
8 | Spine.js Framework integrates class support for Javascript, as
|
9 | internally it uses CoffeeScript classes, which can be used in 3vot Model
|
10 | aswell.
|
11 |
|
12 |
|
13 |
|
14 | If you need guidance for more advanced coding patterns and structures
|
15 | and can’t find it here yet, you can refer to Spine.js documentation, or
|
16 | send us an e-mail, to which we’ll be happy to answer.
|
17 |
|
18 | <p>For a web version, go to http://docs.clayforsalesforce.com. <br /></p>
|
19 |
|
20 |
|
21 |
|
22 |
|
23 | **Directory structure of the model app**
|
24 |
|
25 |
|
26 | ```
|
27 | |-app
|
28 |
|
29 | |-assets
|
30 |
|
31 | |-code
|
32 |
|
33 | | |-controllers
|
34 |
|
35 | | |-models
|
36 |
|
37 | | |-views
|
38 |
|
39 | |-node_modules
|
40 |
|
41 | | |-3vot
|
42 |
|
43 | | |-3vot-model
|
44 |
|
45 | | |-jqueryify
|
46 |
|
47 | |-start
|
48 |
|
49 | | |-3vot.js
|
50 |
|
51 | | |-desktop.js
|
52 |
|
53 | | |-phone.js
|
54 |
|
55 | | |-tablet.js
|
56 |
|
57 | |-templates
|
58 |
|
59 | | |-head.html
|
60 |
|
61 | | |-layout.html
|
62 |
|
63 | |-package.json
|
64 | ```
|
65 |
|
66 |
|
67 | **App folder** is where the compiled app goes. Don’t edit the files in
|
68 | this folder. They will be overwritten everytime the app is compiled.
|
69 | (folder is not showing expanded).
|
70 |
|
71 |
|
72 |
|
73 | **Assets folder** is where you put the assets for your app, such as
|
74 | images and stylesheets. It’s empty by default when the app is created.
|
75 |
|
76 |
|
77 |
|
78 | **Code folder** is where you should put all your scripts files, such as
|
79 | the controllers, models and views files for the 3VOT Model. On the root
|
80 | of the code folder is the index.js file, which is the main controller
|
81 | that gets called when the app starts and where you can define the models
|
82 | and controllers to be used and initialized, as well as making initial
|
83 | data requests to Salesforce.
|
84 |
|
85 |
|
86 | **Node_modules** is the directory for your dependencies (not showing
|
87 | expanded), which are defined on the package.json file on the root of
|
88 | your app folder. By default, Clay requires 3VOT, 3VOT-Model and
|
89 | Jqueryify packages. To install dependencies for your app, see below
|
90 | reference for package.json file.
|
91 |
|
92 |
|
93 |
|
94 | **Start folder** is where you setup how you want your app to show in
|
95 | each platform.
|
96 |
|
97 | 3vot.js is the main app starter file, and desktop.js, phone.js and
|
98 | tablet.js is where you define the controllers and layouts for each of
|
99 | this platforms, and whether you need to login oAuth providers, define
|
100 | api tokens, etc.
|
101 |
|
102 |
|
103 |
|
104 | **Templates folder** is where you have the head and layout html files
|
105 | for you app. If your app has different layouts for different platforms,
|
106 | this is where you should store them. Note that inside layout.html or
|
107 | head.html you need not to include \<head\> or \<body\> tags, and while
|
108 | having different layouts, it’s not possible to change the head file for
|
109 | every one of them, it has to be the same.
|
110 |
|
111 |
|
112 |
|
113 | Package.json file is where you define your dependencies and other
|
114 | compile options for your app:
|
115 |
|
116 | "**platforms**": "The file that will be dynamically loaded once we know
|
117 | the screen size. Located in the /start folder";
|
118 |
|
119 | "**extensions**": "Compile Option: require files with using it's
|
120 | extension";
|
121 |
|
122 | "**transforms**": "Compile Option: The NPM Browserify Transforms applied
|
123 | when compiling App";
|
124 |
|
125 | "**external**": "Performance Option: Allows to extract the common
|
126 | depedencies between apps ex: jquery, cache and speed all apps";
|
127 |
|
128 | "**gitDependencies**": "Bower and Github based Libraries that can be
|
129 | required within an app. ex: Angular";
|
130 |
|
131 | "**dependencies**": "NPM Browser Compatible Dependencies that can be
|
132 | required within an app. ex: 3vot-model";
|
133 |
|
134 |
|
135 |
|
136 |
|
137 |
|
138 | <p><br /></p>
|
139 | **3VOT-Model MVC specifics**
|
140 |
|
141 |
|
142 | **Models **
|
143 |
|
144 | Models should be the viewed only as a connector to Salesforce, and
|
145 | should not include other logics, such as controller logic. Inside the
|
146 | Model file you should only declare the model and the fields required, and then export it to be required by the
|
147 | controllers.
|
148 |
|
149 | Model data is obtained through Ajax connection to Salesforce.
|
150 |
|
151 | **Implementation**
|
152 |
|
153 | 3vot-model is an NPM Dependency that connects with Visualforce API
|
154 | Controller.
|
155 |
|
156 |
|
157 |
|
158 | Hence, it’s necessary to initiate it, by requiring 3vot-model on your
|
159 | model file.
|
160 |
|
161 | ```var _3Model = require("3vot-model");```
|
162 |
|
163 |
|
164 |
|
165 | After that, we have to create a model, which is done by subclassing the
|
166 | 3vot-model Model object through the setup method, passing the desired
|
167 | model name (string) and the desired attributes:
|
168 |
|
169 | ```NewModel = _3Model.Model.*setup*("ModelName", “attribute1”, “attribute
|
170 | 2”, …, “attribute n”);```
|
171 |
|
172 |
|
173 |
|
174 | This Model is a constructor for new instances of the model.
|
175 |
|
176 |
|
177 |
|
178 | For better standards, we advise on the following code structure:
|
179 |
|
180 |
|
181 | //Declare the desired attributes inside an array
|
182 | ```var fields = [“attribute1”, “attribute 2”, …, “attribute n”]; ```
|
183 |
|
184 | //Create the Model
|
185 |
|
186 | ```NewModel = _3Model.Model.*setup*("ModelName", fields);```
|
187 |
|
188 |
|
189 | **Methods and classes can be added to the model.**
|
190 |
|
191 |
|
192 |
|
193 | Use the extend method for adding/overriding class methods, and the
|
194 | include method to add/override instance methods.
|
195 |
|
196 | ```
|
197 | NewModel.extend({
|
198 |
|
199 | find: function(){
|
200 |
|
201 | /\* ... \*/
|
202 |
|
203 | }
|
204 |
|
205 | });
|
206 |
|
207 |
|
208 |
|
209 | NewModel.find(); //calling the new method
|
210 |
|
211 |
|
212 |
|
213 | NewModel.include({
|
214 |
|
215 | name: "Default Name"
|
216 |
|
217 | });
|
218 |
|
219 |
|
220 |
|
221 | ((new NewModel).name === "Default Name" ); //returns true
|
222 | ```
|
223 |
|
224 |
|
225 | **New Model Instances and Classes**
|
226 |
|
227 |
|
228 |
|
229 | You can create new Model instances using the constructor method, via
|
230 | new:
|
231 |
|
232 |
|
233 |
|
234 | ```var model = new Model({object_attributes: “optional”});```
|
235 |
|
236 |
|
237 |
|
238 | You can also use the Model.create method:
|
239 |
|
240 |
|
241 |
|
242 | ```var model = Model.create({object_attributes: “optional”});```
|
243 |
|
244 |
|
245 |
|
246 |
|
247 |
|
248 | To add classes to Models, use the Model.setup method:
|
249 |
|
250 |
|
251 | ```
|
252 | NewModel = _3Model.Model.setup("NewModel", fields);
|
253 |
|
254 |
|
255 |
|
256 | NewModel.Setup(“NewModelName”);
|
257 | ```
|
258 |
|
259 |
|
260 | Saving and Retrieving Objects
|
261 |
|
262 |
|
263 |
|
264 |
|
265 | **Saving and retrieving records**
|
266 |
|
267 |
|
268 |
|
269 | Saving and updating
|
270 | ```
|
271 | var _3Model = require("3vot-model") //requiring npm package
|
272 |
|
273 | var fields = ["Name","Type", "Website"] // declaring the fields
|
274 |
|
275 | Account = _3Model.Model.setup("Account", fields); // creating the
|
276 | account Model
|
277 |
|
278 |
|
279 |
|
280 | var account = new Account({first_name: “John”, last_name: “Smith”});
|
281 | //Account.create(); can be used aswell
|
282 |
|
283 |
|
284 |
|
285 | account.save(); //Saves the object in Salesforce.
|
286 | ```
|
287 |
|
288 |
|
289 | When you save the instance, an id property is created for the object if
|
290 | one isn’t created already.
|
291 |
|
292 |
|
293 |
|
294 | If you change a property, use the same method to update the model.
|
295 |
|
296 |
|
297 | ```
|
298 | account.last_name = “Doe”;
|
299 |
|
300 |
|
301 |
|
302 | account.save(); //
|
303 |
|
304 |
|
305 |
|
306 | account; // {first_name: “John”, last_name: “Doe”}
|
307 | ```
|
308 | Retrieving Records
|
309 |
|
310 |
|
311 |
|
312 | Model Methods to retrieve matching instances:
|
313 |
|
314 | .first(integer(opcional)), ex: Account.first(); / Account.first(10);
|
315 |
|
316 | .last(integer(opcional)), ex: Account.last(); / Account.last(3);
|
317 |
|
318 | .all(), ex: Account.all()
|
319 |
|
320 | .splice(start_position(integer, optional), ex: Account.splice(10); /
|
321 | Account.splice(2,6);
|
322 |
|
323 | .each(CallbackFunction()) – the function should be returning
|
324 | this.desiredProperty or argument.desiredPropery, ex: return
|
325 | account.firstname; This iterates every record on the model, and returns
|
326 | their disered property values
|
327 |
|
328 | ex:
|
329 | ```
|
330 | Account.each(CallbackFunction(account) {
|
331 |
|
332 | return account.first_name;
|
333 |
|
334 | });
|
335 | ```
|
336 |
|
337 |
|
338 | .select(function()) – will select the instances that have the property
|
339 | you
|
340 |
|
341 | ex:
|
342 | ```
|
343 | Account.select(function(account) {
|
344 |
|
345 | return account.first_name;
|
346 |
|
347 | });
|
348 | ```
|
349 |
|
350 |
|
351 |
|
352 |
|
353 | **EVENTS**
|
354 |
|
355 |
|
356 |
|
357 | It’s easy to implement callback functions on Model events. Using the
|
358 | Model.bind method, callbacks will be automatically associated.
|
359 |
|
360 |
|
361 |
|
362 | Use: ```Model.bind(“event”,callbackFunction());```
|
363 |
|
364 |
|
365 |
|
366 | Available events:
|
367 |
|
368 | save - record was saved (either created/updated)
|
369 |
|
370 | update - record was updated
|
371 |
|
372 | create - record was created
|
373 |
|
374 | destroy - record was destroyed
|
375 |
|
376 | change - any of the above, record was created/updated/destroyed
|
377 |
|
378 | refresh - when records are invalidated or appended using the refresh
|
379 | method
|
380 |
|
381 | error - validation failed
|
382 |
|
383 |
|
384 |
|
385 | ex: ```PartyGuests.bind(“create”,buyMoreBooze());```
|
386 |
|
387 |
|
388 |
|
389 | You can trigger events manually with the Model.trigger method, passing
|
390 | as arguments the event and the arguments required for the callback
|
391 | function thats going to be executed. You can use this to create custom
|
392 | events.
|
393 |
|
394 |
|
395 |
|
396 | You can use the Model.listenTo method to have objects waiting for events
|
397 | on other objects. Use Model.listenTo(object,”event”,callbackFunction());
|
398 | ex:
|
399 | ```Invites.listenTo(PartyGuests,”create”,sendInvitationEmail(newPartyGuest));```
|
400 |
|
401 |
|
402 |
|
403 | Model.ListenToOnce will be listening for the next time the event occurs,
|
404 | and only that one. Same arguments as the previous model.
|
405 |
|
406 |
|
407 |
|
408 | Events can be unbind using Model.unbind method.
|
409 |
|
410 | For deeper incursion on the SpineJs Models:
|
411 | http://spinejs.com/api/models
|
412 |
|
413 |
|
414 |
|
415 |
|
416 | **Controllers**
|
417 |
|
418 |
|
419 |
|
420 | Generally, controllers deal with adding and responding to DOM events,
|
421 | rendering templates and keeping views and models in sync.
|
422 |
|
423 |
|
424 |
|
425 | To connect to the DOM objects, 3vot Model, like Spine, uses the el
|
426 | property. El represents the current controller's HTML element, and is
|
427 | instantiated when the former is first created. You can attribute el to
|
428 | CSS classes or HTML tags. You assign the el object property as argument
|
429 | when instanciating, or later:
|
430 | ```
|
431 | var contacts = Contact.create({el: \$(“div\>li”)}); //JQuery selector
|
432 |
|
433 | var Contact.el = \$(".contact-list");
|
434 |
|
435 | var Contact.el = \$("\#contactThingy");
|
436 | ```
|
437 |
|
438 | The el property should be attached to a html tag, which is stored on the
|
439 | Model’s tag property. By default it’s set to “div”, but you can change
|
440 | it:
|
441 |
|
442 |
|
443 |
|
444 | ```var Contact.tag = “li”;```
|
445 |
|
446 |
|
447 |
|
448 | **3Vot Model has events on controllers too**
|
449 |
|
450 |
|
451 |
|
452 | Just set the events property to an array of object literals, in the
|
453 | following format: {"eventType selector": "functionName"}. If no selector
|
454 | is provided, then the event will be set directly on el. Otherwise the
|
455 | events will be delegated to any of el's children matching the selector.
|
456 |
|
457 |
|
458 |
|
459 |
|
460 |
|
461 | **Model methods apply to controllers as well.**
|
462 |
|
463 |
|
464 |
|
465 | **Controller methods which change el and elements property.**
|
466 |
|
467 |
|
468 |
|
469 | ```Controller.html(html);```
|
470 |
|
471 |
|
472 |
|
473 | Replaces el's property’s html by passing in either a piece of HTML, a
|
474 | jQuery element, or another controller instance.
|
475 |
|
476 |
|
477 |
|
478 | ```Controller.append(elementOrController);```
|
479 |
|
480 |
|
481 |
|
482 | Appends the given element, or controller instance, to el property.
|
483 |
|
484 |
|
485 |
|
486 | ```Controller.appendTo(elementOrController);```
|
487 |
|
488 |
|
489 |
|
490 | Appends el property to the given element or controller instance.
|
491 |
|
492 |
|
493 |
|
494 | ```Controller.prepend(elementOrController);```
|
495 |
|
496 |
|
497 |
|
498 | Prepends el to the given element or controller instance.
|
499 |
|
500 |
|
501 |
|
502 | ```replace(element);```
|
503 |
|
504 |
|
505 |
|
506 | Replaces el’s current value with the given element.
|
507 |
|
508 |
|
509 |
|
510 | **Views / Templates**
|
511 |
|
512 |
|
513 |
|
514 | Views are defined through small html templates that get dinamically
|
515 | rendered and refreshed.
|
516 |
|
517 |
|
518 |
|
519 | 3vot Model uses HYPERLINK "https://github.com/sstephenson/eco" Eco:
|
520 | Embedded CoffeeScript templates for its ease of use and
|
521 | integration/versatility, compiling the templates via node.js.
|
522 |
|
523 |
|
524 |
|
525 | To compile the views, you have to require it and than pass it the Model
|
526 | instances to fill the assigned el elements, passing them to the html.
|
527 | Like so:
|
528 |
|
529 |
|
530 | ```
|
531 | render: function(){
|
532 |
|
533 | var accounts = Account.all();
|
534 |
|
535 | var tempEl = "";
|
536 |
|
537 | for(index in accounts){
|
538 |
|
539 | var account = accounts[index];
|
540 |
|
541 | tempEl += accountItemTemplate(account); //returns each rendered
|
542 | template as a string
|
543 |
|
544 | }
|
545 |
|
546 | el.html( tempEl ); //updates the el.property’s element in the app’s
|
547 | html.
|
548 |
|
549 | }
|
550 | ```
|
551 |
|
552 |
|
553 | For more info, you should refer to the website for more information on
|
554 | the use, but here are a few importante directions on integrating it on
|
555 | .eco template files:
|
556 |
|
557 |
|
558 |
|
559 | \<% expression %\>: Evaluate a CoffeeScript expression without printing
|
560 | its return value.
|
561 |
|
562 | \<%= expression %\>: Evaluate a CoffeeScript expression, escape its
|
563 | return value, and print it.
|
564 |
|
565 | \<%- expression %\>: Evaluate a CoffeeScript expression and print its
|
566 | return value without escaping it.
|
567 |
|
568 | \<%= @property %\>: Print the escaped value of the property property
|
569 | from the context object passed to render.
|
570 |
|
571 | \<%= @helper() %\>: Call the helper method helper from the context
|
572 | object passed to render, then print its escaped return value.
|
573 |
|
574 | \<% @helper -\> %\>...\<% end %\>: Call the helper method helper with a
|
575 | function as its first argument. When invoked, the function will capture
|
576 | and return the content ... inside the tag.
|
577 |
|
578 | \<%% and %%\> will result in a literal \<% and %\> in the rendered
|
579 | template, respectively.
|
580 |
|
581 |
|
582 |
|
583 | An exemple for a Salesforce contact list template view:
|
584 |
|
585 |
|
586 | ```
|
587 | \<li class="list-group-item contact-item"\>
|
588 |
|
589 | \<span data-id="\<%= @id %\>" class="editable btn_edit"\>
|
590 |
|
591 | \<%= @Name %\>
|
592 |
|
593 | \<%= @Email%\>
|
594 |
|
595 | \</span\>
|
596 |
|
597 | \<span class="badge btn_delete" data-id="\<%= @id %\>"\>x\</span\>
|
598 |
|
599 | \</li\>
|
600 | ```
|
601 |
|
602 |
|
603 | If you need to use JQuery to manipulate your templates DOM, just use a
|
604 | .jeco extension for your template file instead of .eco.
|
605 |
|
606 |
|
\ | No newline at end of file |