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 [2020/06/24 20:00] sahlcomponent_class [2023/08/15 11:49] (current) sahl
Line 16: Line 16:
  
 $mycomponent = new helloWorld(); $mycomponent = new helloWorld();
 +
 +// Start page
 +
 $mycomponent->render(); $mycomponent->render();
 </code> </code>
  
-===== Component configuration =====+===== Component properties ===== 
 + 
 +In order for components to work correctly, all variables needed for configuring the component should be implemented as //properties//. This can be done with the addPropertyMap function, which expect an array of property keys and default values.
  
-To make your component configurable, override the $properties array with some default values. To extend the component from above to make the text and text color configurable, do this:+To extend the component from above to make the text and text color configurable, do this:
  
 <code php> <code php>
 class textOutput extends Component { class textOutput extends Component {
  
-  protected $properties = array( +  public function __construct() { 
-    'text' => 'Hello world', +    $this->addPropertyMap(array( 
-    'color' => 'black'+      'text' => 'Hello world', 
 +      'color' => 'black' 
 +    ); 
 +    parent::__construct();
   );   );
  
Line 44: Line 52:
 </code> </code>
  
-Note how the configuration properties is easily set and read.+Note how the configuration properties are easily set and read.
  
-===== HTML and Javascript bindings =====+===== HTML output =====
  
-The component will always render in double div with the following properties:+The base component will render a div with the following properties:
  
-An outer div with a static class //platform_component// and an inner div with a class based on the class name of the component, so if the component is named textOutputthe class will be named //platform_component_textoutput//.+  * The id will match the id set by the ''SetID()'' function. If no ID is setone will be auto-generated. 
 +  * It will add three data-elements: io_url, componentclass and componentproperties for internal handling.
  
-Other classes can also be added for internal handling.+==== Example ====
  
-The outer div will have an auto-generated id or you can set the id with the ''setID''-function.+<code html output.html> 
 +<div id="example_output" data-componentproperties="..." data-redraw_url="..." data-componentclass="textOutput"> 
 +<span style="color:red;">Platform4PHP is cool</span> 
 +</div> 
 +</code>
  
-===== Example =====+==== Javascript and CSS loading ====
  
-<code php index.php>+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>
 class textOutput extends Component { class textOutput extends Component {
  
-  public $configuration = array+  public function __construct() { 
-    'text=> 'Hello world', +    static::JSFile('script.js'); 
-    'color' => 'black'+    static::CSSFile('style.css'); 
 +    parent::__construct();
   );   );
  
 +}
 +</code>
 +
 +==== Using CSS ====
 +
 +Using CSS is easy. Setting the ID of the component is accomplished using the ''SetID()'' function and classes can be added to the component using ''AddClass()''.
 +
 +==== 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>
 +
 +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(values, callback, 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(values, func)'' 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 script.js>
 +mycomponent.backendIO({event: 'setvalue', value: 'myvalue'}, function(data) { console.log('This is called with the return values from the PHP function.'); console.log(data);})
 +</code>
 +
 +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 handling, you 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()'' function. All 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() {   public function renderContent() {
-    echo '<span style="color:'.$this->color.';">'; +    // Check if name is attached to component 
-    echo $this->text+    if ($this->name) { 
-    echo '</span>';+      // 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>
  
-$mycomponent new textOutput()+===== Components in headless scripts ===== 
-$mycomponent->text = 'Platform4PHP is cool'+ 
-$mycomponent->color = 'red'+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. 
-$mycomponent->setID('example_output'); + 
-$mycomponent->render();+===== Adding to the DOM using javascript ===== 
 + 
 +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. 
 + 
 +<code php> 
 +var html = SOME HTML CONTAINING COMPONENTS. 
 + 
 +var node = domnode.html(html); 
 + 
 +Platform.apply(node);
 </code> </code>
  
-<code html output.html> +===== Automatic component redraw ===== 
-<div class="platform_component" id="example_output" data-configuration="..."> + 
-<div class="platform_component_textoutput"+It is possible for Platform-components to automatically redraw themselves if they are designed correctlyThe condition for a component to be able to redraw itself, is that it must be able to do so based solely on the content of its propertiesIn other words, the component should be able to render by doing just the following: 
-<span style="color:red;">Platform4PHP is cool</span> + 
-</div+<code php
-</div>+$component new textOutput()
 +$component->setPropertyMap(PROPERTIES NEEDED TO RENDER COMPONENT); 
 +$component->render();
 </code> </code>
  
-===== Other javascript functionality =====+In this case, you can force the component to redraw, by just triggering the Javascript //redraw// event on it.
  
-There are some build-in javascript functionality, which can be triggered with events.+==== Advanced redrawing ====
  
-^event^Effect^ +If you make a component which isn't able to redraw itself, then you should overwrite the static variable:
-|disable|Disables the component, by rendering black square over it.| +
-|enable|Re-enables the component.| +
-|disable_others|Disable every other component except this.| +
-|enable_others|Re-enables every other component except this.| +
-|redraw|Redraws the component by fetching its content from the server|+
  
-==== Prevent disabling ====+<code php> 
 +protected static $can_redraw false; 
 +</code> 
 + 
 +If a component is to redraw itself, it needs to know if it should validate itself for security reasons. By default it will fail to redraw if it can't detect a valid session. 
 + 
 +To skip this check, then overwrite the static variable: 
 + 
 +<code php> 
 +protected static $is_secure false; 
 +</code> 
 + 
 +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> 
 +    
  
-Some components are purely visual and shouldn't be allowed to be disabled. To prevent a component from becoming disabled, set the static ''$can_disable'' variable to false in the php file. 
component_class.1593028826.txt.gz · Last modified: 2020/06/24 20:00 by sahl

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki