19 declare(strict_types=1);
95 case ($component instanceof
F\
Section):
101 case ($component instanceof
F\
Link):
104 case ($component instanceof
F\
Group):
105 return $default_renderer->render($component->getInputs());
107 case ($component instanceof
F\
Text):
110 case ($component instanceof
F\
Numeric):
116 case ($component instanceof
F\
Tag):
122 case ($component instanceof
F\
Select):
126 return $this->renderMarkdownField($component, $default_renderer);
129 return $this->renderTextareaField($component, $default_renderer);
131 case ($component instanceof
F\
Radio):
140 case ($component instanceof
F\
File):
143 case ($component instanceof
F\
Url):
146 case ($component instanceof
F\
Hidden):
152 case ($component instanceof
F\
Rating):
164 ?
string $id_for_label =
null,
165 ?
string $dependant_group_html =
null 167 $tpl = $this->
getTemplate(
"tpl.context_form.html",
true,
true);
169 $tpl->setVariable(
"LABEL", $label);
170 $tpl->setVariable(
"INPUT", $input_html);
172 $tpl->setVariable(
"INPUT_NAME", $component->getName());
176 $tpl->setVariable(
"BINDING_ID", $binding_id);
180 $tpl->setCurrentBlock(
'for');
181 $tpl->setVariable(
"ID", $id_for_label);
182 $tpl->parseCurrentBlock();
184 $tpl->touchBlock(
'tabindex');
189 $tpl->setVariable(
"BYLINE", $byline);
194 $tpl->setCurrentBlock(
'required');
195 $tpl->setVariable(
"REQUIRED_ARIA", $this->
txt(
'required_field'));
196 $tpl->parseCurrentBlock();
200 $tpl->touchBlock(
"disabled");
203 $error = $component->getError();
206 $tpl->setVariable(
"ERROR_LABEL", $this->
txt(
"ui_error"));
207 $tpl->setVariable(
"ERROR_ID", $error_id);
208 $tpl->setVariable(
"ERROR",
$error);
210 $tpl->setVariable(
"ERROR_FOR_ID", $id_for_label);
214 if ($dependant_group_html) {
215 $tpl->setVariable(
"DEPENDANT_GROUP", $dependant_group_html);
222 $name = $component->getName();
245 if (!is_null($escape)) {
246 $value = $escape($value);
248 if (isset($value) && $value !==
'') {
255 return function ($v) {
259 return htmlspecialchars((
string) $v, ENT_QUOTES);
265 return function ($v) {
269 return htmlentities((
string) $v);
275 $input_html = $default_renderer->render($component->getInputs());
278 $component->getLabel(),
285 $tpl = $this->
getTemplate(
"tpl.text.html",
true,
true);
288 if ($component->getMaxLength()) {
289 $tpl->setVariable(
"MAX_LENGTH", $component->getMaxLength());
295 $tpl->setVariable(
'ID', $label_id);
296 return $this->
wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
301 $tpl = $this->
getTemplate(
"tpl.numeric.html",
true,
true);
306 $tpl->setVariable(
'ID', $label_id);
307 return $this->
wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
312 $tpl = $this->
getTemplate(
"tpl.checkbox.html",
true,
true);
315 if ($component->getValue()) {
316 $tpl->touchBlock(
"value");
320 $tpl->setVariable(
'ID', $label_id);
321 return $this->
wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
326 $tpl = $this->
getTemplate(
"tpl.optionalgroup_label.html",
true,
true);
327 $tpl->setVariable(
'LABEL', $component->getLabel());
328 $tpl->setVariable(
"NAME", $component->getName());
329 if ($component->getValue()) {
330 $tpl->setVariable(
"CHECKED",
'checked="checked"');
334 $tpl->setVariable(
'ID', $label_id);
336 $label = $tpl->get();
337 $input_html = $default_renderer->render($component->getInputs());
345 if ($component->getValue() !==
null) {
346 list($value, ) = $component->getValue();
350 foreach ($component->getInputs() as $key => $group) {
351 $tpl = $this->
getTemplate(
"tpl.switchablegroup_label.html",
true,
true);
352 $tpl->setVariable(
'LABEL', $group->getLabel());
353 $tpl->setVariable(
"NAME", $component->getName());
354 $tpl->setVariable(
"VALUE", $key);
357 $tpl->setVariable(
'ID', $label_id);
359 if ($key == $value) {
360 $tpl->setVariable(
"CHECKED",
'checked="checked"');
366 $default_renderer->render($group),
374 $component->getLabel(),
381 $tpl = $this->
getTemplate(
"tpl.tag_input.html",
true,
true);
384 $configuration = $component->getConfiguration();
385 $value = $component->getValue();
396 $component = $component->withAdditionalOnLoadCode(
397 function (
$id) use ($configuration, $value) {
398 $encoded = json_encode($configuration);
399 $value = json_encode($value);
400 return "il.UI.Input.tagInput.init('{$id}', {$encoded}, {$value});";
404 if ($component->isDisabled()) {
405 $tpl->setVariable(
"DISABLED",
"disabled");
406 $tpl->setVariable(
"READONLY",
"readonly");
410 $tpl->setVariable(
'ID', $label_id);
411 return $this->
wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
416 $tpl = $this->
getTemplate(
"tpl.password.html",
true,
true);
419 if ($component->getRevelation()) {
420 $component = $component->withResetSignals();
421 $sig_reveal = $component->getRevealSignal();
422 $sig_mask = $component->getMaskSignal();
423 $component = $component->withAdditionalOnLoadCode(
function (
$id) use ($sig_reveal, $sig_mask) {
425 "$(document).on('$sig_reveal', function() { 426 const fieldContainer = document.querySelector('#$id .c-input__field .c-field-password'); 427 fieldContainer.classList.add('revealed'); 428 fieldContainer.getElementsByTagName('input').item(0).type='text'; 430 "$(document).on('$sig_mask', function() { 431 const fieldContainer = document.querySelector('#$id .c-input__field .c-field-password'); 432 fieldContainer.classList.remove('revealed'); 433 fieldContainer.getElementsByTagName('input').item(0).type='password'; 438 $glyph_reveal =
$f->symbol()->glyph()->eyeopen(
"#")
439 ->withOnClick($sig_reveal);
440 $glyph_mask =
$f->symbol()->glyph()->eyeclosed(
"#")
441 ->withOnClick($sig_mask);
443 $tpl->setVariable(
'PASSWORD_REVEAL', $default_renderer->render($glyph_reveal));
444 $tpl->setVariable(
'PASSWORD_MASK', $default_renderer->render($glyph_mask));
450 $tpl->setVariable(
'ID', $label_id);
451 return $this->
wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
456 $tpl = $this->
getTemplate(
"tpl.select.html",
true,
true);
459 $value = $component->getValue();
461 $tpl->setCurrentBlock(
"options");
463 $tpl->setVariable(
"SELECTED",
'selected="selected"');
465 if ($component->isRequired() && !$value) {
466 $tpl->setVariable(
"DISABLED_OPTION",
"disabled");
467 $tpl->setVariable(
"HIDDEN",
"hidden");
470 if (!($value && $component->isRequired())) {
471 $tpl->setVariable(
"VALUE",
null);
472 $tpl->setVariable(
"VALUE_STR", $component->isRequired() ? $this->
txt(
'ui_select_dropdown_label') :
'-');
473 $tpl->parseCurrentBlock();
476 foreach ($component->getOptions() as $option_key => $option_value) {
477 $tpl->setCurrentBlock(
"options");
478 if ($value == $option_key) {
479 $tpl->setVariable(
"SELECTED",
'selected="selected"');
481 $tpl->setVariable(
"VALUE", $option_key);
482 $tpl->setVariable(
"VALUE_STR", $option_value);
483 $tpl->parseCurrentBlock();
487 $tpl->setVariable(
'ID', $label_id);
488 return $this->
wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
494 $component = $component->withAdditionalOnLoadCode(
495 static function (
$id) use ($component):
string {
497 const id = document.querySelector('#$id .c-input__field textarea')?.id; 498 il.UI.Input.markdown.init( 500 '{$component->getMarkdownRenderer()->getAsyncUrl()}', 501 '{$component->getMarkdownRenderer()->getParameterName()}' 509 $textarea_tpl->setVariable(
'ID', $textarea_id);
511 $markdown_tpl = $this->
getTemplate(
"tpl.markdown.html",
true,
true);
512 $markdown_tpl->setVariable(
'TEXTAREA', $textarea_tpl->get());
514 $markdown_tpl->setVariable(
516 $component->getMarkdownRenderer()->render(
521 $markdown_tpl->setVariable(
523 $default_renderer->render(
524 $this->getUIFactory()->viewControl()->mode([
525 $this->
txt(
'ui_md_input_edit') =>
'#',
526 $this->
txt(
'ui_md_input_view') =>
'#',
532 $markdown_actions_glyphs = [
533 'ACTION_HEADING' => $this->
getUIFactory()->symbol()->glyph()->header(),
534 'ACTION_LINK' => $this->
getUIFactory()->symbol()->glyph()->link(),
535 'ACTION_BOLD' => $this->
getUIFactory()->symbol()->glyph()->bold(),
536 'ACTION_ITALIC' => $this->
getUIFactory()->symbol()->glyph()->italic(),
537 'ACTION_ORDERED_LIST' => $this->
getUIFactory()->symbol()->glyph()->numberedlist(),
538 'ACTION_UNORDERED_LIST' => $this->
getUIFactory()->symbol()->glyph()->bulletlist()
541 foreach ($markdown_actions_glyphs as $tpl_variable => $glyph) {
542 if ($component->isDisabled()) {
543 $glyph = $glyph->withUnavailableAction();
546 $action = $this->
getUIFactory()->button()->standard(
'',
'#')->withSymbol($glyph);
548 if ($component->isDisabled()) {
549 $action = $action->withUnavailableAction();
552 $markdown_tpl->setVariable($tpl_variable, $default_renderer->render($action));
555 return $this->
wrapInFormContext($component, $component->getLabel(), $markdown_tpl->get());
561 $component = $component->withAdditionalOnLoadCode(
562 static function (
$id):
string {
564 taId = document.querySelector('#$id .c-input__field textarea')?.id; 565 il.UI.Input.textarea.init(taId); 573 $tpl->setVariable(
'ID', $label_id);
574 return $this->
wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
579 $tpl = $this->
getTemplate(
"tpl.textarea.html",
true,
true);
581 if (0 < $component->getMaxLimit()) {
582 $tpl->setVariable(
'REMAINDER_TEXT', $this->
txt(
'ui_chars_remaining'));
583 $tpl->setVariable(
'REMAINDER', $component->getMaxLimit() - strlen($component->getValue() ??
''));
584 $tpl->setVariable(
'MAX_LIMIT', $component->getMaxLimit());
587 if (
null !== $component->getMinLimit()) {
588 $tpl->setVariable(
'MIN_LIMIT', $component->getMinLimit());
598 $tpl = $this->
getTemplate(
"tpl.radio.html",
true,
true);
601 foreach ($component->getOptions() as $value => $label) {
602 $opt_id =
$id .
'_' . $value .
'_opt';
604 $tpl->setCurrentBlock(
'optionblock');
605 $tpl->setVariable(
"NAME", $component->getName());
606 $tpl->setVariable(
"OPTIONID", $opt_id);
607 $tpl->setVariable(
"VALUE", $value);
608 $tpl->setVariable(
"LABEL", $label);
610 if ($component->getValue() !==
null && $component->getValue() == $value) {
611 $tpl->setVariable(
"CHECKED",
'checked="checked"');
613 if ($component->isDisabled()) {
614 $tpl->setVariable(
"DISABLED",
'disabled="disabled"');
617 $byline = $component->getBylineFor((
string) $value);
618 if (!empty($byline)) {
619 $tpl->setVariable(
"BYLINE", $byline);
622 $tpl->parseCurrentBlock();
625 return $this->
wrapInFormContext($component, $component->getLabel(), $tpl->get());
630 $tpl = $this->
getTemplate(
"tpl.multiselect.html",
true,
true);
632 $options = $component->getOptions();
633 if (count($options) > 0) {
634 $value = $component->getValue();
635 $name = $this->
applyName($component, $tpl);
636 foreach ($options as $opt_value => $opt_label) {
637 $tpl->setCurrentBlock(
"option");
638 $tpl->setVariable(
"NAME", $name);
639 $tpl->setVariable(
"VALUE", $opt_value);
640 $tpl->setVariable(
"LABEL", $opt_label);
642 if ($value && in_array($opt_value, $value)) {
643 $tpl->setVariable(
"CHECKED",
'checked="checked"');
645 $tpl->parseCurrentBlock();
648 $tpl->touchBlock(
"no_options");
651 return $this->
wrapInFormContext($component, $component->getLabel(), $tpl->get());
658 $tpl->setVariable(
'ID', $label_id);
659 return $this->
wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
667 $tpl = $this->
getTemplate(
"tpl.datetime.html",
true,
true);
670 if ($component->getTimeOnly() ===
true) {
671 $format = $component::TIME_FORMAT;
672 $dt_type = self::TYPE_TIME;
674 $dt_type = self::TYPE_DATE;
676 $component->getFormat(),
677 self::DATEPICKER_FORMAT_MAPPING
680 if ($component->getUseTime() ===
true) {
681 $format .=
' ' . $component::TIME_FORMAT;
682 $dt_type = self::TYPE_DATETIME;
686 $tpl->setVariable(
"DTTYPE", $dt_type);
688 $min_max_format = self::DATE_DATEPICKER_MINMAX_FORMAT;
689 if ($dt_type === self::TYPE_DATETIME) {
690 $min_max_format = self::DATETIME_DATEPICKER_MINMAX_FORMAT;
693 $min_date = $component->getMinValue();
694 if (!is_null($min_date)) {
695 $tpl->setVariable(
"MIN_DATE", date_format($min_date, $min_max_format));
697 $max_date = $component->getMaxValue();
698 if (!is_null($max_date)) {
699 $tpl->setVariable(
"MAX_DATE", date_format($max_date, $min_max_format));
702 $this->
applyValue($component, $tpl,
function (?
string $value) use ($dt_type) {
703 if ($value !==
null) {
704 $value = new \DateTimeImmutable($value);
705 return $value->format(match ($dt_type) {
706 self::TYPE_DATETIME => self::HTML5_NATIVE_DATETIME_FORMAT,
707 self::TYPE_DATE => self::HTML5_NATIVE_DATE_FORMAT,
708 self::TYPE_TIME => self::HTML5_NATIVE_TIME_FORMAT,
713 return [$component, $tpl];
718 $inputs = $component->getInputs();
724 $tpl->setVariable(
'ID', $from_input_id);
725 $input_html = $this->
wrapInFormContext($input, $input->getLabel(), $tpl->get(), $from_input_id);
728 ->withAdditionalPickerconfig([
'useCurrent' =>
false]);
730 $until_input_id = $this->
createId();
731 $tpl->setVariable(
'ID', $until_input_id);
732 $input_html .= $this->
wrapInFormContext($input, $input->getLabel(), $tpl->get(), $until_input_id);
734 $tpl = $this->
getTemplate(
"tpl.duration.html",
true,
true);
735 $tpl->setVariable(
'DURATION', $input_html);
736 return $this->
wrapInFormContext($component, $component->getLabel(), $tpl->get());
741 $inputs_html = $default_renderer->render($section->getInputs());
743 $headline_tpl = $this->
getTemplate(
"tpl.headlines.html",
true,
true);
744 $headline_tpl->setVariable(
"HEADLINE", $section->getLabel());
745 $nesting_level = $section->getNestingLevel() + 2;
746 if ($nesting_level > 6) {
749 $headline_tpl->setVariable(
"LEVEL", $nesting_level);
751 $headline_html = $headline_tpl->get();
758 $tpl = $this->
getTemplate(
"tpl.url.html",
true,
true);
763 $tpl->setVariable(
'ID', $label_id);
764 return $this->
wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
769 $template = $this->
getTemplate(
'tpl.file.html',
true,
true);
770 foreach ($input->getDynamicInputs() as $metadata_input) {
772 if (
null !== (
$data = $metadata_input->getValue())) {
773 $file_id = (!$input->hasMetadataInputs()) ?
774 $data :
$data[$input->getUploadHandler()->getFileIdentifierParameterName()] ??
null;
776 if (null !== $file_id) {
777 $file_info = $input->getUploadHandler()->getInfoResult($file_id);
790 $file_preview_template = $this->
getTemplate(
'tpl.file.html',
true,
true);
793 $input->getTemplateForDynamicInputs(),
796 $file_preview_template
799 $template->setVariable(
'FILE_PREVIEW_TEMPLATE', $file_preview_template->get(
'block_file_preview'));
806 $template->setVariable(
'ACTION_BUTTON', $default_renderer->render(
807 $this->getUIFactory()->button()->shy(
808 $this->
txt(
'select_files_from_computer'),
822 $template = $this->
getTemplate(
'tpl.hidden.html',
true,
true);
825 if ($input->isDisabled()) {
826 $template->setVariable(
"DISABLED",
'disabled="disabled"');
829 return $template->get();
837 parent::registerResources($registry);
838 $registry->
register(
'assets/js/tagify.min.js');
839 $registry->
register(
'assets/css/tagify.css');
840 $registry->
register(
'assets/js/tagInput.js');
842 $registry->
register(
'assets/js/dropzone.min.js');
843 $registry->
register(
'assets/js/dropzone.js');
844 $registry->
register(
'assets/js/input.js');
845 $registry->
register(
'assets/js/core.js');
846 $registry->
register(
'assets/js/file.js');
847 $registry->
register(
'assets/js/input.factory.min.js');
857 foreach ($input->getTriggeredSignals() as $s) {
859 "signal_id" => $s->getSignal()->getId(),
860 "event" => $s->getEvent(),
861 "options" => $s->getSignal()->getOptions()
864 if ($signals !==
null) {
865 $signals = json_encode($signals);
867 $input = $input->withAdditionalOnLoadCode(
function (
$id) use ($signals) {
868 $code =
"il.UI.input.setSignalsForId('$id', $signals);";
872 $input = $input->withAdditionalOnLoadCode($input->getUpdateOnLoadCode());
888 foreach ($origin->toArray() as $element) {
889 if (array_key_exists($element, $mapping)) {
890 $ret .= $mapping[$element];
906 $template->
setVariable(
'REMOVAL_GLYPH', $default_renderer->render(
907 $this->getUIFactory()->symbol()->glyph()->close()->withAction(
"#")
910 if (
null !== $file_info) {
920 if ($file_input->hasMetadataInputs()) {
921 $template->
setVariable(
'EXPAND_GLYPH', $default_renderer->render(
922 $this->getUIFactory()->symbol()->glyph()->expand()->withAction(
"#")
924 $template->
setVariable(
'COLLAPSE_GLYPH', $default_renderer->render(
925 $this->getUIFactory()->symbol()->glyph()->collapse()->withAction(
"#")
929 $template->
setVariable(
'METADATA_INPUTS', $default_renderer->render($metadata_input));
939 function (
$id) use ($input) {
940 $current_file_count = count($input->getDynamicInputs());
941 $translations = json_encode($input->getTranslations());
942 $is_disabled = ($input->isDisabled()) ?
'true' :
'false';
944 $should_upload_be_chunked = ($input->getMaxFileSize() > $php_upload_limit) ?
'true' :
'false';
945 $chunk_size = (
int) floor($php_upload_limit * self::FILE_UPLOAD_CHUNK_SIZE_FACTOR);
947 $(document).ready(function () { 948 il.UI.Input.File.init( 950 '{$input->getUploadHandler()->getUploadURL()}', 951 '{$input->getUploadHandler()->getFileRemovalURL()}', 952 '{$input->getUploadHandler()->getFileIdentifierParameterName()}', 954 {$input->getMaxFiles()}, 955 {$input->getMaxFileSize()}, 956 '{$this->prepareDropzoneJsMimeTypes($input->getAcceptedMimeTypes())}', 959 $should_upload_be_chunked, 975 $mime_type_string =
'';
976 foreach ($mime_types as $index => $mime_type) {
977 $mime_type_string .= (isset($mime_types[$index + 1])) ?
"$mime_type," : $mime_type;
980 return $mime_type_string;
985 $tpl = $this->
getTemplate(
"tpl.color_select.html",
true,
true);
987 $tpl->setVariable(
'VALUE', $component->getValue());
990 $tpl->setVariable(
'ID', $label_id);
991 return $this->
wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
996 $tpl = $this->
getTemplate(
"tpl.rating.html",
true,
true);
998 $aria_description_id =
$id .
'_desc';
999 $tpl->setVariable(
'DESCRIPTION_SRC_ID', $aria_description_id);
1001 $option_count = count(FiveStarRatingScale::cases()) - 1;
1003 foreach (range($option_count, 1, -1) as $option) {
1004 $tpl->setCurrentBlock(
'scaleoption');
1005 $tpl->setVariable(
'ARIALABEL', $this->
txt($option .
'stars'));
1006 $tpl->setVariable(
'OPT_VALUE', (
string) $option);
1007 $tpl->setVariable(
'OPT_ID',
$id .
'-' . $option);
1008 $tpl->setVariable(
'NAME', $component->getName());
1009 $tpl->setVariable(
'DESCRIPTION_ID', $aria_description_id);
1012 $tpl->setVariable(
"SELECTED",
' checked="checked"');
1014 if ($component->isDisabled()) {
1015 $tpl->setVariable(
"DISABLED",
'disabled="disabled"');
1017 $tpl->parseCurrentBlock();
1020 if (!$component->isRequired()) {
1021 $tpl->setVariable(
'NEUTRAL_ID',
$id .
'-0');
1022 $tpl->setVariable(
'NEUTRAL_NAME', $component->getName());
1023 $tpl->setVariable(
'NEUTRAL_LABEL', $this->
txt(
'reset_stars'));
1024 $tpl->setVariable(
'NEUTRAL_DESCRIPTION_ID', $aria_description_id);
1026 if ($component->getValue() === FiveStarRatingScale::NONE || is_null($component->getValue())) {
1027 $tpl->setVariable(
'NEUTRAL_SELECTED',
' checked="checked"');
1031 if (
$txt = $component->getAdditionalText()) {
1032 $tpl->setVariable(
'TEXT',
$txt);
1035 if ($component->isDisabled()) {
1036 $tpl->touchBlock(
'disabled');
1038 if ($average = $component->getCurrentAverage()) {
1039 $average_title = sprintf($this->
txt(
'rating_average'), $average);
1040 $tpl->setVariable(
'AVERAGE_VALUE', $average_title);
1041 $tpl->setVariable(
'AVERAGE_VALUE_PERCENT', $average / $option_count * self::CENTUM);
1044 return $this->
wrapInFormContext($component, $component->getLabel(), $tpl->get());
1052 $template->
setVariable(
'FILE_SIZE_LABEL', $this->
txt(
'file_notice'));
1057 $template->
setVariable(
'FILES_LABEL', $this->
txt(
'ui_file_upload_max_nr'));
1058 $template->
setVariable(
'FILES_VALUE', $input->getMaxFiles());
Registry for resources required by rendered output like Javascript or CSS.
FiveStarRatingScale
This is the scale for the Rating Input.
This implements the textarea input.
This class provides the data size with additional information to remove the work to calculate the siz...
trait JavaScriptBindable
Trait for components implementing JavaScriptBindable providing standard implementation.
convertSpecialCharacters(string $value)
txt(string $id)
Get a text from the language file.
A password is used as part of credentials for authentication.
This implements the text input.
setCurrentBlock(string $name)
Set the block to work on.
createId()
Get a fresh unique id.
setVariable(string $name, $value)
Set a variable in the current block.
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
getTemplate(string $name, bool $purge_unfilled_vars, bool $purge_unused_blocks)
Get template of component this renderer is made for.
getOnLoadCode()
Get the currently bound on load code.
cannotHandleComponent(Component $component)
This method MUST be called by derived component renderers, if.
Interface FileInfoResult.
register(string $name)
Add a dependency.
parseCurrentBlock()
Parse the block that is currently worked on.
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
getUIFactory()
Get a UI factory.
withAdditionalOnLoadCode(Closure $binder)
Add some onload-code to the component instead of replacing the existing one.
getComponentCanonicalNameAttribute(Component $component)
Base class for all component renderers.
bindJavaScript(JavaScriptBindable $component)
Bind the component to JavaScript.