Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIX] UI: Align Container\Form renderers #8444

Open
wants to merge 1 commit into
base: release_10
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,20 +61,4 @@ protected function extractRequestData(ServerRequestInterface $request): InputDat
{
return new PostDataFromServerRequest($request);
}

/**
* @inheritdoc
*/
public function getPromptButtons(): array
{
return [];
}

/**
* @inheritdoc
*/
public function getPromptTitle(): string
{
return '';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,17 @@

class FormRendererFactory extends Render\DefaultRendererFactory
{
public const NO_BUTTONS_FORM = [
public const FORM_CONTEXTS_WITHOUT_BUTTONS = [
'StateStatePrompt',
'RoundTripModal',
];

public function getRendererInContext(Component\Component $component, array $contexts): Render\AbstractComponentRenderer
{
$has_context_without_buttons = array_intersect(self::NO_BUTTONS_FORM, $contexts);
$has_context_without_buttons = array_intersect(self::FORM_CONTEXTS_WITHOUT_BUTTONS, $contexts);

if (! empty($has_context_without_buttons)) {
return new NoButtonsContextRenderer(
return new FormWithoutSubmitButtonsContextRenderer(
$this->ui_factory,
$this->tpl_factory,
$this->lng,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,27 @@
use ILIAS\UI\Component;
use LogicException;

class NoButtonsContextRenderer extends AbstractComponentRenderer
class FormWithoutSubmitButtonsContextRenderer extends Renderer
{
/**
* @inheritdoc
*/
public function render(Component\Component $component, RendererInterface $default_renderer): string
{
if (!$component instanceof Form\Form) {
$this->cannotHandleComponent($component);
if ($component instanceof Form\Standard) {
return $this->renderFormWithoutSubmitButtons($component, $default_renderer);
}
return $this->renderNoSubmit($component, $default_renderer);

$this->cannotHandleComponent($component);
}

protected function renderNoSubmit(
Form\Form $component,
protected function renderFormWithoutSubmitButtons(
Form\Standard $component,
RendererInterface $default_renderer
): string {
$tpl = $this->getTemplate("tpl.no_submit.html", true, true);
$tpl = $this->getTemplate("tpl.without_submit_buttons.html", true, true);

$this->maybeAddDedicatedName($component, $tpl);
$this->maybeAddRequired($component, $tpl);
$this->addPostURL($component, $tpl);
$this->maybeAddError($component, $tpl);
Expand Down Expand Up @@ -75,41 +77,4 @@ static function (string $id) use ($component): string {

return $tpl->get();
}

protected function addPostURL(Component\Input\Container\Form\FormWithPostURL $component, Template $tpl): void
{
if ('' !== ($url = $component->getPostURL())) {
$tpl->setCurrentBlock("action");
$tpl->setVariable("URL", $url);
$tpl->parseCurrentBlock();
}
}

protected function maybeAddError(Form\Form $component, Template $tpl): void
{
if (null !== ($error = $component->getError())) {
$tpl->setCurrentBlock("error");
$tpl->setVariable("ERROR", $error);
$tpl->parseCurrentBlock();
}
}

protected function maybeAddRequired(Form\Form $component, Template $tpl): void
{
if ($component->hasRequiredInputs()) {
$tpl->setVariable("TXT_REQUIRED_TOP", $this->txt("required_field"));
$tpl->setVariable("TXT_REQUIRED", $this->txt("required_field"));
}
}

/**
* @inheritdoc
*/
protected function getComponentInterfaceName(): array
{
return [
Component\Input\Container\Form\Standard::class,
FormWithoutSubmitButton::class,
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,14 @@ public function render(Component\Component $component, RendererInterface $defaul
return $this->renderStandard($component, $default_renderer);
}

if ($component instanceof Form\FormWithoutSubmitButton) {
return $this->renderNoSubmit($component, $default_renderer);
}

$this->cannotHandleComponent($component);
}

protected function renderStandard(Form\Standard $component, RendererInterface $default_renderer): string
{
$tpl = $this->getTemplate("tpl.standard.html", true, true);
if ($component->getDedicatedName() !== null) {
$tpl->setVariable("NAME", 'name="' . $component->getDedicatedName() . '"');
}

$this->maybeAddDedicatedName($component, $tpl);
$this->maybeAddRequired($component, $tpl);
$this->addPostURL($component, $tpl);
$this->maybeAddError($component, $tpl);
Expand All @@ -68,39 +62,11 @@ protected function renderStandard(Form\Standard $component, RendererInterface $d
return $tpl->get();
}

protected function renderNoSubmit(Form\FormWithoutSubmitButton $component, RendererInterface $default_renderer): string
protected function maybeAddDedicatedName(Form\Form $component, Template $tpl): void
{
$tpl = $this->getTemplate("tpl.no_submit.html", true, true);

$this->maybeAddRequired($component, $tpl);
$this->addPostURL($component, $tpl);
$this->maybeAddError($component, $tpl);

$tpl->setVariable("INPUTS", $default_renderer->render($component->getInputGroup()));

/** @var $component Form\FormWithoutSubmitButton */
$enriched_component = $component->withAdditionalOnLoadCode(
static function (string $id) use ($component): string {
return "
// @TODO: we need to refactor the signal-management to prevent using jQuery here.
$(document).on('{$component->getSubmitSignal()}', function () {
let form = document.getElementById('$id');
if (!form instanceof HTMLFormElement) {
throw new Error(`Element '$id' is not an instance of HTMLFormElement.`);
}

// @TODO: we should use the triggering button as an emitter here. When doing
// so, please also change file.js processFormSubmissionHook().
form.requestSubmit();
});
";
}
);

$id = $this->bindJavaScript($enriched_component) ?? $this->createId();
$tpl->setVariable("ID", $id);

return $tpl->get();
if ($component->getDedicatedName() !== null) {
$tpl->setVariable("NAME", 'name="' . $component->getDedicatedName() . '"');
}
}

protected function addPostURL(Component\Input\Container\Form\FormWithPostURL $component, Template $tpl): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@
use ILIAS\UI\Implementation\Component\Input;
use ILIAS\UI\Implementation\Component\Input\NameSource;
use ILIAS\UI\Implementation\Component\SignalGeneratorInterface;
use ILIAS\UI\Implementation\Component\Prompt\IsPromptContentInternal;
use ILIAS\UI\Component\Signal;
use ILIAS\UI\Implementation\Component\JavaScriptBindable as JavaScriptBindableTrait;
use ILIAS\UI\Component\JavaScriptBindable;

/**
* This implements a standard form.
*/
class Standard extends Form implements C\Input\Container\Form\Standard, JavaScriptBindable
class Standard extends Form implements C\Input\Container\Form\Standard, IsPromptContentInternal, JavaScriptBindable
{
use HasPostURL;
use JavaScriptBindableTrait;
Expand All @@ -55,10 +56,10 @@ public function __construct(
/**
* @inheritDoc
*/
public function withSubmitLabel(string $caption): C\Input\Container\Form\Standard
public function withSubmitLabel(string $label): C\Input\Container\Form\Standard
{
$clone = clone $this;
$clone->submit_caption = $caption;
$clone->submit_caption = $label;
return $clone;
}

Expand All @@ -70,6 +71,16 @@ public function getSubmitLabel(): ?string
return $this->submit_caption;
}

public function getPromptButtons(): array
{
return [];
}

public function getPromptTitle(): string
{
return '';
}

public function getSubmitSignal(): Signal
{
return $this->submit_signal;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
<form id="{ID}" role="form" class="c-form c-form--horizontal" enctype="multipart/form-data"<!-- BEGIN reference_error --> describedby="{ERROR_ID}"<!-- END reference_error --> {NAME}<!-- BEGIN action --> action="{URL}"<!-- END action --> method="post" novalidate="novalidate">
<!-- BEGIN error -->
<div id="{ERROR_ID}" class="c-form__error-msg alert alert-danger">
{ERROR}
</div>
<div class="c-form__error-msg alert alert-danger" id="{ERROR_ID}"><span class="sr-only">{ERROR_LABEL}: </span>{ERROR}</div>
<!-- END error -->

{INPUTS}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public function getNewDedicatedName(string $dedicated_name): string
/**
* @author Thibeau Fuhrer <[email protected]>
*/
class NoSubmitFormTest extends \ILIAS_UI_TestBase
class FormWithoutSubmitButtonsTest extends \ILIAS_UI_TestBase
{
protected SignalGenerator $signal_generator;
protected NameSource $namesource;
Expand Down Expand Up @@ -144,7 +144,8 @@ public function testRenderWithRequiredInputs(): void
public function testRenderWithError(): void
{
$post_url = 'http://ilias.localhost/some_url?param1=foo&param2=bar';
$error_lang_var = 'ui_error_in_group';
$error_lang_var = 'ui_error';
$error_lang_var_in_group = 'ui_error_in_group';

$dummy_input = $this->buildInputFactory()->text('test_label')->withAdditionalTransformation(
$this->refinery->custom()->constraint(
Expand All @@ -171,11 +172,12 @@ static function ($value): bool {
$form = $form->withRequest($request);
$data = $form->getData();

$expected_html =
"<form id=\"id_1\" role=\"form\" class=\"c-form c-form--horizontal\" enctype=\"multipart/form-data\" action=\"$post_url\" method=\"post\" novalidate=\"novalidate\">" .
"<div id=\"\" class=\"c-form__error-msg alert alert-danger\">$error_lang_var</div>" .
$dummy_input->getCanonicalName() .
"</form>";
$expected_html = <<<EOT
<form id="id_2" role="form" class="c-form c-form--horizontal" enctype="multipart/form-data" describedby="id_1" action="$post_url" method="post" novalidate="novalidate">
<div class="c-form__error-msg alert alert-danger" id="id_1"><span class="sr-only">$error_lang_var:</span>$error_lang_var_in_group
</div>{$dummy_input->getCanonicalName()}
</form>
EOT;

$context = $this->createMock(\ILIAS\UI\Component\Modal\RoundTrip::class);
$context->method('getCanonicalName')->willReturn('RoundTripModal');
Expand Down
Loading