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/05/01 15:28] – [Backend handling of events] On-the-Fly javascript 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(formfunc, failfunc)|Set a form to be posted to the component backend. See below.| 
 +|backendIO(valuesfunc)|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.|
  
-<code js textoutput.js> +==== Communicating between the frontend and backend ==== 
-  addPlatformComponentHandlerFunction('textoutput', function(item) { + 
-    // Do your stuff here! +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> </code>
  
-The item variable passed is a Jquery-selector pointing to the DOM node of the component. This will always point to a single node, so there is no need to iterate it. If several components of the same type existsthe function will be called multiple times.+This will immediately pass the variables to the ''handleIO()''-functionwhere they can be handled.
  
-===== Easy Javascript / PHP interaction =====+<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>
  
-Components support easy interaction between Javascript and PHP. This interaction can both take place using forms and also directly from Javascript. 
  
-In javascript this interaction takes place through two JQuery plugins called ''componentIO'' and ''componentIOForm''.+==== Passing forms into the backend ====
  
-In PHP everything is handled by overriding the ''handleIO()'' function in the Component.+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.
  
-==== Easy form interaction ====+When the form is submitted it is directed to the ''handleIO()''-function in your PHP component class.
  
-If you have a form, you can get your component to handle it. In javascript do this:+=== Example ===
  
 <code js script.js> <code js script.js>
-mycomponent.componentIOForm($('#myform'), function(data) { console.log('This is called on success.'); })+mycomponent.addIOForm($('#myform'), function(data) { console.log('This is called on success.'); })
 </code> </code>
  
-//mycomponent// is expected to be the jquery node for a valid component. //myform// is the HTML ID for a form. The anonymous function is called if the form is handled without errors. +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:
- +
-When the form is submitted it will be intercepted by the component and the form output will end up in the ''handleIO()'' PHP function:+
  
 <code php component.php> <code php component.php>
Line 133: Line 147:
 </code> </code>
  
-If you want the form to fail, you need to return an array with two keys. //status// which must be 0 or false, and //form_errors// which should contain the output from ''Form->getAllErrors()''. This will automatic cause the frontend to fail the form.+There are some requirements to the return value when handling formsFirst 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.
  
-Otherwise the array returned from the function will be passed into the javascript anonymous function.+In addition to this, you are free to return whatever values you want. These will be returned to the functions in javascript.
  
-=== Without javascript ===+=== Form handling without javascript ===
  
-It is possible to attach a form entirely from PHP like this:+For basic form handling, you can do this without using javascript.
  
 <code php component.php> <code php component.php>
Line 145: Line 159:
     ...     ...
     $form = new \Platform\Form(); // You need to get the appropriate form.     $form = new \Platform\Form(); // You need to get the appropriate form.
-    $this->attachIOForm($form);+    $this->registerForm($form);
     ...     ...
   }   }
 </code> </code>
  
-When this form is submitted it is processed by the component like above, but without the need to write javascript-code.+This will ensure that the form is handled by the component ''handleIO()''-function when it is submitted.
  
-==== Easy general interaction ====+==== Sending events directly to the backend ====
  
-If you just want to pass some variables to the ''handleIO()''-function, you can also do that easily: +Typically events are handled using the ''on()'' function in javascriptbut in Platform you can redirect these events to the backend directlyThis 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 js script.js> +
-mycomponent.componentIOForm({action: 'setvalue', value: 'myvalue'}, function(data) { console.log('This is called with the return values from the PHP function.');}) +
-</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['action'] == '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> +
- +
-The return values will be passed back into the javascript anonymous functions. +
- +
-==== Backend handling of events ==== +
- +
-It is possible to redirect javascript events to the backend. To do this use the ''registerEvent()'' function. This will redirect javascript events of the registered type to the backend. The event name will be passed in the ''$_POST['event']'' variable and can be handled in the ''handleIO()'' function.+
  
 <code php component.php> <code php component.php>
Line 188: Line 183:
 </code> </code>
  
-==== On-the-fly javascript ====+==== Special return instructions (reserved words) ====
  
-If you set the //script// key on the array returned from the ''handleIO()'' function, then that value will be evaluated as javascript in the frontend, so you don'have to make a custom javascript file for minor functions.+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 componentwhich will bubble if the component doesn'handle it.| 
 + 
 +=== Example === 
 + 
 +You can execute generic javascript.
  
 <code php> <code php>
Line 196: Line 203:
     return ['script' => 'alert(\'This will cause an alert in the frontend!\');'];     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> </code>
  
Line 202: 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 238: 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.1619882911.txt.gz · Last modified: 2021/05/01 15:28 by sahl

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki