PageRenderTime 48ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/templates/jui/page/learn/understand/base/adding.html

https://github.com/atk4/atk4-web
HTML | 160 lines | 115 code | 45 blank | 0 comment | 0 complexity | 7ac2ad1d375bcdaf1b4f665e12a5ec1b MD5 | raw file
  1. <?$Content?>
  2. <div class="g-row">
  3. <div class="g-12">
  4. <h1>Adding objects in Agile Toolkit</h1>
  5. <p>Adding is the fundamental concept of Agile Toolkit. You don't produce HTML strings like you do with other toolkits, you manipulate with objects. You add objects like this:
  6. </p>
  7. <?Code?>
  8. $view = $page->add('LoremIpsum');
  9. <?/?>
  10. <p>Try this code. Copy it into "page/index.php" inside function init() of your local Agile Toolkit installation. You will see that a few paragraphs of "Lorem Ipsum" text filler will appear on your page.</p>
  11. <?MoreInfo?>Geeky Note encapsulation and dependency injection.
  12. <p>Adding is a combination of encapsulation and dependency injection patterns. When you add object A into object B essentially it extends the functionality of object B. Depending on the type of the A object, results might be different: Adding "View" will enhance the presentation of object B. Adding model can configure an object with fields. Adding a controller will change the default behaviour of the object</p>
  13. <p>In other frameworks there is no adding. You rely on a "new" operator to create new objects and supply them with dependencies. This is called dependency injection. If your object relies on a global variable or assumes a class name of an object it relies on it is considered a bad development practice. In Agile Toolkit, the object "B" IS the dependency container. It will supply link to API, database connection, logging class and more. For the cases when you need to use a different set of classes, you can create a new API class and add your object into this separate API or one of it's sub-objects.</p>
  14. <p>Agile Toolkit never relies on global variables therefore it's possible to have multiple APIs for testing, integration or benchmarking purposes.</p>
  15. <?/?>
  16. <h2>Run-time Tree</h2>
  17. <p>In the real world, certain objects are containers. Your bag may contain your wallet and your wallet may contain your credit cards. In Agile Toolkit all objects are also containers. You can also imagine it as a tree-like structure. The top node or a top container is called "Application". This object may contain controllers, models and a page. The page will contain views such as Forms, Text, Buttons, LoremIpsum object etc.</p>
  18. <p>When you add objects it also cross-links them with the "owner". When you added LoremIpsum into $page, the $page became "owner" of LoremIpsum, LoremIpsum became "Element" of $page. All objects are also given a unique identifier within it's owner - short_name. Another property which is automatically added to any object is "name": globally unique identifier.</p>
  19. <?MoreInfo?>Geeky Note Object Presence and independence.
  20. <p>The rule of thumb in Agile Toolkit is that the $name of an object will not change between different requests. By assuming that the object's name will be always the same, it is often used to identify objects in Agile Toolkit. Let's look at how Agile Toolkit resolves a situation when you have two forms on your page.</p>
  21. <p>Like any other object, Form has a name. When Form is submitted, each Form on your page will compare it's name with the argument received from the browser. Therefore the right object will be able to react accordingly.</p>
  22. <p>Other objects use presence also. Paginator, for example, remembers which page you are looking at. If you have multiple listings with pagination on the same page, they will not intervene.</p>
  23. <?/?>
  24. <?Example?>
  25. $page->add('Button')->set('Click me');
  26. <?/?>
  27. <h2>init() method</h2>
  28. <p>When you add an object, Agile Toolkit will automatically execute method init() of a new object. This method is often used to initialize an object. When you are creating your own object, the first method you'll learn to define would be init() method. In fact — you have already created a custom object. You have changed the init() method of your index page.</p>
  29. <p>You can also extend and define your own View classes. By adding code in their init() method, you can build more advanced objects or an object with altered behaviour. Please always remember to call parent::init() before you place any code of your own.</p>
  30. <?MoreInfo?>Geeky Note Constructors: Encapsulation versus Inheritance
  31. <p>Object-oriented development offers developers two powerful principles, encapsulation and inheritance. They achieve similar goals, but are quite different in their nature. As a developer you must be able to decide which principle is best in your application. However, often you'll see both principles used together.</p>
  32. <p>Another concept of Agile Toolkit is pure encapsulation. When you extend one object to add more object into it, you are using both principles. In practice this could be a ContactForm class which adds more fields inside init() method.</p>
  33. <p>Agile Toolkit objects never rely on default PHP constructors.</p>
  34. <?/?>
  35. <p>Next, let's create our own button class with a slightly different behaviour from the button supplied by Agile Toolkit. This button's label will be automatically set to "Click Me". Place the following code inside lib/MyButton.php</p>
  36. <?Code?>
  37. class MyButton extends Button {
  38. function init(){
  39. parent::init();
  40. $this->set('Click Me');
  41. }
  42. }
  43. <?/?>
  44. <p>Next add this on your index page: </p>
  45. <?Code?>
  46. $page->add('MyButton');
  47. <?/?>
  48. <p>As you have expected the newly created button will have a different label. Remember this principle and every time you feel a need to duplicate some code, put it inside a separate class instead. Here is another example which can help you create a re-usable contact form. Place this code inside lib/Form/ContactForm.php:</p>
  49. <?Code?>
  50. class Form_ContactForm extends Form {
  51. function init(){
  52. parent::init();
  53. $this->addField('Line','name');
  54. $this->addField('Line','surname');
  55. $this->addSubmit('Send');
  56. }
  57. }
  58. <?/?>
  59. <p>Notice that you might, optionally, add more fields or buttons outside of the class on your page after object is added:</p>
  60. <?Code?>
  61. $contact_form = $page->add('Form_ContactForm');
  62. $contact_form->addButton('Cancel');
  63. <?/?>
  64. <p>Apart from using $contact_form instead of $this, the syntax and effect is identical. Always put code you want to re-use inside the class but remember that you can still tweak it on a per-use basis.</p>
  65. <h2>Indirect Adding of Objects</h2>
  66. <p>For convenience, objects may define new methods for adding certain types of objects. For example, in the form above you can see "addField". This method will actually call add() but will use "Form_Field_Line" class instead of just "Line". You must remember that you can always use "add" method instead of addField, addSubmit or addButton for maximum control.</p>
  67. <p>Most functions starting with "add" are wrappers for add(). There are some functions which do not use this convention: js(), dsql() and exception() will also rely on add(). $grid-&gt;addColumn(), however, this does not currently create new object.</p>
  68. <h2>The second argument</h2>
  69. <p>In some cases you would like to specify a short_name of a new object. You do that when you add a field to a form class. A short_name of a field object will be used to construct POST reply. When it's important to specify the new object's short_name the second argument of add() method can be used to specify the new name.</p>
  70. <p>It is also possible to change the name of an object after it was added using rename() method, although only use that method if you have no other alternative (some objects may not work well with renaming)</p>
  71. <?MoreInfo?>Geeky Note changing default properties
  72. <p>The second argument can be also an associative array. If you do specify an array, the add() method will set initial object properties as per this array. This may be useful to specify additional parameters. A good example is to specify "grid_class" property to init() method of CRUD and substitute default "Grid" class with your own.</p>
  73. <p>In your own objects, please avoid this approach if possible. The init() method of objects must be as lightweight as possible and must only do the initialization and avoid any complex operations such as retrieving data from database. That is the job for object renderer.</p>
  74. <?/?>
  75. <?Code?>
  76. $page->add('Form','my_form');
  77. if($page->hasElement('my_form')){
  78. // has form
  79. }
  80. $page->getElement('my_form')->owner; // refers back to $page
  81. <?/?>
  82. <?Code?>
  83. $model->add('MyObject',array('foo'=>'bar'));
  84. echo $model->foo;
  85. <?/?>
  86. <h2>Working with existing objects</h2>
  87. <p><b>$this->hasElement($short_name)</b> return child object if found, or false if not found.</p>
  88. <p><b>$this->getElement($short_name)</b> similar to hasElement() but will produce an exception if not found. Use this when chaining.</p>
  89. <p><b>$this->destroy()</b> remove the current object from its owner. For a view, this will remove it from rendered page.</p>
  90. <p><b>$this->rename($new_short_name)</b> can rename an object, but might not work with some objects.</p>
  91. <p><b>$this->newInstance()</b> will add a copy of the object and add into the same owner. Unlike cloning, object state is not copied.</p>
  92. <p>Properties: <b>$this->name</b> name is unique to the system. <b>$this->short_name</b> is unique amongst owners children. <b>$this->template</b> reference to the SMlite template for the current view. <b>$this->owner</b> reference to the object whose add() was used (the parent). <b>$this->api</b> refers to the API class of the parent object.</p>
  93. <h2>Excercise</h2>
  94. <p>Create your own class which will produce video playback controls. You don't need to link it with video or make controls work, just make it look like one:</p>
  95. <?Execute?>
  96. class VideoControls extends View {
  97. function init(){
  98. parent::init();
  99. $this->add('Button')->set('Rewind');
  100. $this->add('Button','play_button')->set('Play');
  101. $this->add('Button')->set('Stop');
  102. $this->add('Button')->set('FastForward');
  103. }
  104. }
  105. $this->add('VideoControls');
  106. <?/?>
  107. <p>Once you are ready with this task, create another instance of a video playback controls and destroy "play" button:</p>
  108. <?Execute?>
  109. $this->add('VideoControls')
  110. ->getElement('play_button')->destroy();
  111. <?/?>
  112. <p>For solution look at <a href="https://github.com/atk4/atk4-web/edit/master/templates/jui/page/learn/understand/base/adding.html" target="_blank">the source
  113. of ths page</a></p>
  114. </div></div>
  115. <?$Next?>