User Tools

Site Tools


component_class

Component class

The component class is a base UI class providing a close binding between PHP and Javascript. The class is intended to be subclassed.

Simple component

In order to create a new, simple component just override the renderContent-function, such as:

class helloWorld extends Component {
 
  public function renderContent() {
    echo 'Hello world';
  }
}
 
$mycomponent = new helloWorld();
 
// Start page
 
$mycomponent->render();

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 extend the component from above to make the text and text color configurable, do this:

class textOutput extends Component {
 
  public function __construct() {
    $this->addPropertyMap(array(
      'text' => 'Hello world',
      'color' => 'black'
    );
    parent::__construct();
  );
 
  public function renderContent() {
    echo '<span style="color:'.$this->color.';">';
    echo $this->text;
    echo '</span>';
  }
}
 
$mycomponent = new textOutput();
$mycomponent->text = 'Platform4PHP is cool';
$mycomponent->color = 'red';
$mycomponent->render();

Note how the configuration properties are easily set and read.

HTML output

The base component will render a div with the following properties:

  • The id will match the id set by the SetID() function. If no ID is set, one will be auto-generated.
  • It will add three data-elements: io_url, componentclass and componentproperties for internal handling.

Example

output.html
<div id="example_output" data-componentproperties="..." data-redraw_url="..." data-componentclass="textOutput">
<span style="color:red;">Platform4PHP is cool</span>
</div>

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 either Component::JSFile() and Component::CSSFile(). Platform will ensure that each file is only included once.

class textOutput extends Component {
 
  public function __construct() {
    static::JSFile('script.js');
    static::CSSFile('style.css');
    parent::__construct();
  );
 
}

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:

var component_object = $('#my_component').platformComponent();

This object have the following functions:

FunctionDescription
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

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);})

This will immediately pass the variables to the handleIO()-function, where they can be handled.

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!'];
}

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

script.js
mycomponent.addIOForm($('#myform'), function(data) { console.log('This is called on success.'); })

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:

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'];
}

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.

component.php
  class myComponent {
    ...
    $form = new \Platform\Form(); // You need to get the appropriate form.
    $this->registerForm($form);
    ...
  }

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.

component.php
class MyComponent {
   ...
   $this->registerEvent('mycustomevent');
 
   public function handleIO() {
     if ($_POST['event'] == 'mycustomevent') {
       // Handle the custom event
     }
   }
}

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.

KeywordDescription
dataAttach data attributes to the component.
destroyDestroy the component in the DOM
propertiesUpdate the component properties in the frontend.
redirect / targetRedirect the user to another URL. An optional target can be provided
scriptJavascript that will be executed in the frontend.
triggerTrigger an event on the component, which will bubble if the component doesn't handle it.

Example

You can execute generic javascript.

  public function handleIO() {
    return ['script' => 'alert(\'This will cause an alert in the frontend!\');'];
  }

If you change component properties in the handleIO()-function you will need to pass them back to the front-end.

  public function handleIO() {
    return ['properties' => $this->getEncodedProperties()];
  }

If the component is redrawable, the redraw can also be executed by returning true in the redraw-key:

  public function handleIO() {
    return ['redraw' => true];
  }

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:

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];
    }
  }
}

Components in headless scripts

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.

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.

var html = SOME HTML CONTAINING COMPONENTS.
 
var node = domnode.html(html);
 
Platform.apply(node);

Automatic component redraw

It is possible for Platform-components to automatically redraw themselves if they are designed correctly. The 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 properties. In other words, the component should be able to render by doing just the following:

$component = new textOutput();
$component->setPropertyMap(PROPERTIES NEEDED TO RENDER COMPONENT);
$component->render();

In this case, you can force the component to redraw, by just triggering the Javascript redraw event on it.

Advanced redrawing

If you make a component which isn't able to redraw itself, then you should overwrite the static variable:

protected static $can_redraw = false;

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:

protected static $is_secure = false;

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

protected static $component_class = 'my_custom_platform_component';

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:

class MyCustomPlatformComponentClass extends Platform.Component {
 
 // Code goes here
}

3. Associate the DOM class with the javascript class

This is done like this in javascript:

Platform.Component.bindClass('MyCustomPlatformComponentClass', my_custom_platform_component);
component_class.txt · Last modified: 2023/08/15 11:49 by sahl

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki