User Tools

Site Tools


component_class

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
component_class [2021/04/28 21:10] – [Components in headless scripts] sahlcomponent_class [2023/08/15 11:49] (current) sahl
Line 59: Line 59:
  
   * The id will match the id set by the ''SetID()'' function. If no ID is set, one will be auto-generated.   * The id will match the id set by the ''SetID()'' function. If no ID is set, one will be auto-generated.
-  * It will add a class //platform_component// +  * It will add three data-elements: io_url, componentclass and componentproperties for internal handling.
-  * It will add a class //platform_component_CLASSNAME// where CLASSNAME is the name of the class. +
-  * It will add up to three data-elements: redraw_url, componentclass and componentproperties for internal handling.+
  
 ==== Example ==== ==== Example ====
  
 <code html output.html> <code html output.html>
-<div class="platform_component platform_component_textoutput" id="example_output" data-componentproperties="..." data-redraw_url="..." data-componentclass="textOutput">+<div id="example_output" data-componentproperties="..." data-redraw_url="..." data-componentclass="textOutput">
 <span style="color:red;">Platform4PHP is cool</span> <span style="color:red;">Platform4PHP is cool</span>
 </div> </div>
 </code> </code>
  
-==== Javascript and CSS handling ====+==== Javascript and CSS loading ====
  
-A component will typically need its own css-files and javascript to function properly. These can just be included in the constructor using the general ''Page::JSFile()'' and ''Page::CSSFile()''. Platform will ensure that each file is only included once. +A component will typically need its own css-files and javascript to function properly. These can just be included in the constructor using either ''Component::JSFile()'' and ''Component::CSSFile()''. Platform will ensure that each file is only included once. 
  
 <code php> <code php>
Line 79: Line 77:
  
   public function __construct() {   public function __construct() {
-    Page::JSFile('script.js'); +    static::JSFile('script.js'); 
-    Page::CSSFile('style.css');+    static::CSSFile('style.css');
     parent::__construct();     parent::__construct();
   );   );
Line 87: Line 85:
 </code> </code>
  
-In order for javascript to work, especially if the page is hyper-dynamic, it need to be wrapped in the following structure:+==== Using CSS ====
  
-<code js textoutput.js> +Using CSS is easySetting the ID of the component is accomplished using the ''SetID()'' function and classes can be added to the component using ''AddClass()''. 
-  addPlatformComponentHandlerFunction('CLASS_IN_LOWERCASE'function(item{ + 
-    // Do your stuff here! +==== Using Javascript ==== 
-  });+ 
 +All components have an associated javascript object named ''Platform.Component''. In javascript this object can be obtained from any component using the Jquery ''platformComponent()'' function, such as: 
 + 
 +<code js> 
 +var component_object = $('#my_component').platformComponent();
 </code> </code>
  
-CLASS_IN_LOWERCASE should be exchanged with the class name of the PHP class in lowercaseso for the class textOutputit should read like this:+This object have the following functions: 
 +^Function^Description^ 
 +|redraw()|Redraw the component.| 
 +|addIOForm(form, func, failfunc)|Set a form to be posted to the component backend. See below.| 
 +|backendIO(values, func)|Send some information to the component backend (and get an answer). See below.| 
 +|timedIO(valuescallback, polltime, precision)|Send some information to the component backend at a timed interval.| 
 +|removeTimedIO()|Stop sending information to the component backend at a timed interval.| 
 + 
 +==== Communicating between the frontend and backend ==== 
 + 
 +Use the ''backendIO(valuesfunc)'' javascript function to communicate between the frontend and backend. All values provided through the //values// parameter will be passed as ''$_POST'' parameters and can be handled by overwriting the ''handleIO()''-function in your PHP component class. Everything you return from this function will be passed back to the javascript-function //func//. 
 + 
 +=== Example ===
  
-<code js textoutput.js> +<code js script.js> 
-  addPlatformComponentHandlerFunction('textoutput', function(item) { +mycomponent.backendIO({event: 'setvalue', value: 'myvalue'}, function(data) { console.log('This is called with the return values from the PHP function.'); console.log(data);})
-    // Do your stuff here! +
-  });+
 </code> </code>
  
-The item variable passed is a Jquery-selector pointing to the DOM node of the component. This will always point to a single nodeso there is no need to iterate it. If several components of the same type exists, the function will be called multiple times.+This will immediately pass the variables to the ''handleIO()''-function, where they can be handled. 
 + 
 +<code php component.php> 
 +public function handleIO() : array { 
 +  if ($_POST['event'] == 'setvalue' && $_POST['value'] == 'myvalue') return ['status' => true, 'text' => 'This was exactly as expected.']; 
 +  else return ['status' => false, 'text' => 'I didn\'t expect that input!']; 
 +
 +</code> 
 + 
 + 
 +==== Passing forms into the backend ==== 
 + 
 +Forms can also be passed into the backend, much like the example above. Here you just use the ''addIOForm(form, func, failfunc)''. The //form// parameter is a jquery selector pointing to your form. The //func// parameter is a function called after the form is submitted with success and the //failfunc// parameter is a function called if the form fails. 
 + 
 +When the form is submitted it is directed to the ''handleIO()''-function in your PHP component class. 
 + 
 +=== Example === 
 + 
 +<code js script.js> 
 +mycomponent.addIOForm($('#myform'), function(data) { console.log('This is called on success.'); }) 
 +</code> 
 + 
 +When the form is submitted (and validates in the frontend), it will be intercepted by the component and the form output will end up in the ''handleIO()'' PHP function: 
 + 
 +<code php component.php> 
 +public function handleIO() : array { 
 +  $form = new \Platform\Form(); // You need to get the appropriate form. 
 +  if (! $form->validate) return ['status' => 0'form_errors' => $form->getAllErrors()]; 
 +  return ['status' => 1, 'message' => 'This entire array is returned to javascript']; 
 +
 +</code> 
 + 
 +There are some requirements to the return value when handling forms. First you must return a value //status// in your return array. This should be 0 if form validation failed, and 1 if form validation succeeded. If the form failed you should also return all form errors in the //form_errors// field of your return array. 
 + 
 +In addition to this, you are free to return whatever values you want. These will be returned to the functions in javascript. 
 + 
 +=== Form handling without javascript === 
 + 
 +For basic form handlingyou can do this without using javascript. 
 + 
 +<code php component.php> 
 +  class myComponent { 
 +    ... 
 +    $form = new \Platform\Form(); // You need to get the appropriate form. 
 +    $this->registerForm($form); 
 +    ... 
 +  } 
 +</code> 
 + 
 +This will ensure that the form is handled by the component ''handleIO()''-function when it is submitted. 
 + 
 +==== Sending events directly to the backend ==== 
 + 
 +Typically events are handled using the ''on()'' function in javascript, but in Platform you can redirect these events to the backend directly. This can be done using the ''registerEvent()'' function, where you name the event you want passed to the backend. The event name will be passed in the ''$_POST['event']'' variable and can be handled in the ''handleIO()'' functionAll event parameters are lost when doing this. 
 + 
 +<code php component.php> 
 +class MyComponent { 
 +   ... 
 +   $this->registerEvent('mycustomevent'); 
 +    
 +   public function handleIO() { 
 +     if ($_POST['event'] == 'mycustomevent') { 
 +       // Handle the custom event 
 +     } 
 +   } 
 +
 +</code> 
 + 
 +==== Special return instructions (reserved words) ==== 
 + 
 +When returning an array from the ''handleIO()'' function, there are some reserved words you can use to trigger a special behaviour in the frontend.  
 + 
 +^Keyword^Description^ 
 +|data|Attach data attributes to the component.| 
 +|destroy|Destroy the component in the DOM| 
 +|properties|Update the component properties in the frontend.| 
 +|redirect / target|Redirect the user to another URL. An optional target can be provided| 
 +|script|Javascript that will be executed in the frontend.| 
 +|trigger|Trigger an event on the component, which will bubble if the component doesn't handle it.| 
 + 
 +=== Example === 
 + 
 +You can execute generic javascript. 
 + 
 +<code php> 
 +  public function handleIO() { 
 +    return ['script' => 'alert(\'This will cause an alert in the frontend!\');']; 
 +  } 
 +</code> 
 + 
 +If you change component properties in the ''handleIO()''-function you will need to pass them back to the front-end. 
 + 
 +<code php> 
 +  public function handleIO() { 
 +    return ['properties' => $this->getEncodedProperties()]; 
 +  } 
 +</code> 
 + 
 +If the component is redrawable, the redraw can also be executed by returning true in the //redraw//-key: 
 + 
 +<code php> 
 +  public function handleIO() { 
 +    return ['redraw' => true]; 
 +  } 
 +</code> 
 + 
 +==== Putting it all together ==== 
 + 
 +In this example we will make a component which prompts the user for a name and age, and then displays this information afterwards. This is obtained 100 % in PHP: 
 + 
 +<code php example.php> 
 +class myExample extends Component { 
 + 
 +  public $form = null; 
 +   
 +  public function __construct() { 
 +    // Set component properties 
 +    $this->setPropertyMap([ 
 +      'name' => '', 
 +      'age' => 0 
 +    ]); 
 +   
 +    // Construct form 
 +    $this->form = new Form('name_age_form'); 
 +    $this->form->addField(TextField::Field('Name', 'name')); 
 +    $this->form->addField(TextField::Field('Age', 'age')); 
 +    $this->form->addField(SubmitButton::Field('Send', 'send')); 
 +     
 +    // Attach form to component 
 +    $this->registerForm($this->form); 
 +     
 +    // Redirect the resetcomponent event to the backend 
 +    $this->registerEvent('resetcomponent'); 
 +  } 
 +   
 +  public function renderContent() { 
 +    // Check if name is attached to component 
 +    if ($this->name) { 
 +      // Display text 
 +      echo 'You have entered '.$this->name.' as name and '.$this->age.' as age.'; 
 +      // Display a link to reset the component 
 +      $menuitem = new MenuItem('Reset component', '#TRIGGER=resetcomponent'); 
 +      $menuitem->render(); 
 +    } else { 
 +      // Display the form 
 +      $this->form->render(); 
 +    } 
 +  } 
 +   
 +  public function handleIO() { 
 +    // Check if form is submitted. 
 +    if ($this->form->isSubmitted()) { 
 +      // Validate form 
 +      $result = $this->form->validate(); 
 +      // Send error if not validated 
 +      if (! $result) return ['status' => false, 'form_errors' => $form->getAllErrors()]; 
 +      // Get values and transfer to component properties 
 +      $values = $this->form->getValues(); 
 +      $this->name = $values['name']; 
 +      $this->age = $values['age']; 
 +      // Return status, updated properties and a redraw request. 
 +      return ['status' => true, 'properties' => $this->getEncodedProperties(), 'redraw' => true]; 
 +    } 
 +    // Check if reset was triggered 
 +    if ($_POST['event'] == 'resetcomponent') { 
 +      // Clear properties 
 +      $this->name = ''; 
 +      $this->age = 0; 
 +      // Return updated properties and a redraw request. 
 +      return ['properties' => $this->getEncodedProperties(), 'redraw' => true]; 
 +    } 
 +  } 
 +
 +</code>
  
 ===== Components in headless scripts ===== ===== Components in headless scripts =====
Line 109: Line 294:
 If you use components in headless scripts, which are scripts that doesn't contain a complete html page, but are instead meant to be loaded dynamically, be sure to call the ''Page::setPagestarted()'' function before adding your components. Otherwise included javascript and css-files will not load correctly. If you use components in headless scripts, which are scripts that doesn't contain a complete html page, but are instead meant to be loaded dynamically, be sure to call the ''Page::setPagestarted()'' function before adding your components. Otherwise included javascript and css-files will not load correctly.
  
-===== Component event model =====+===== Adding to the DOM using javascript =====
  
-Components are designed to work with the Javascript/Jquery event modelso communication is expected to take place by triggering events on the DOM node containing the component. There are some built-in events already available on all basic components:+If you load components onto your page using javascript (by loading a PHP script which generate components)you need to execute the ''Platform.apply()'' jquery function on the DOM node where the components comes into existence in order to initialize them.
  
-^event^Effect^ +<code php> 
-|redraw|Redraws the component by fetching its content from the serverSee below.|+var html = SOME HTML CONTAINING COMPONENTS. 
 + 
 +var node = domnode.html(html); 
 + 
 +Platform.apply(node); 
 +</code>
  
 ===== Automatic component redraw ===== ===== Automatic component redraw =====
Line 145: Line 335:
  
 In this case everyone can replay the Ajax redraw request and see the content of the component. In this case everyone can replay the Ajax redraw request and see the content of the component.
 +
 +===== Extending the component javascript class =====
 +
 +If you want to extend the javascript object associated with your custom component, this can be done in three easy steps.
 +
 +==== 1. Give the component an unique class name ====
 +
 +You first need to give your component a unique DOM class name, which is accomplished by overwriting the ''$component_class'' static variable in your component
 +
 +<code php>
 +protected static $component_class = 'my_custom_platform_component';
 +</code>
 +
 +==== 2. Create a new javascript class for your component ====
 +
 +Now create a new javascript class for your component. It must extend the Platform.Component class:
 +
 +<code js>
 +class MyCustomPlatformComponentClass extends Platform.Component {
 +
 + // Code goes here
 +}
 +</code>
 +
 +==== 3. Associate the DOM class with the javascript class ====
 +
 +This is done like this in javascript:
 +
 +<code js>
 +Platform.Component.bindClass('MyCustomPlatformComponentClass', my_custom_platform_component);
 +</code>
 +    
 +
component_class.1619644249.txt.gz · Last modified: 2021/04/28 21:10 by sahl

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki