protected function processRender(FormInterface $form, Request $request): void
    {
        /** @var Presenter $presenter */
        $presenter = $this->getPresenter();
        if (!$presenter->isAjax()) {
            throw new BadRequestException('The render signal is only allowed in ajax mode.');
        }

        $fields = $request->getPost($this->lookupPath(Presenter::class, true).self::NAME_SEPARATOR.'fields');
        if (!$fields) {
            throw new BadRequestException('No fields specified for rendering.');
        }

        $form->handleRequest($request);
        if (!$form->isSubmitted()) {
            throw new BadRequestException('The form was not submitted.');
        }

        $view = $this->getView();
        $widgets = [];
        foreach ($fields as $field) {
            // Validate the field identifier for security reasons. A dot in the identifier would be particularly dangerous.
            if (!Strings::match($field, '~^(?:\[\w++\])++$~')) {
                throw new BadRequestException(
                    sprintf('Field identifier "%s" contains unallowed characters.', $field)
                );
            }

            // Skip duplicates. The renderer would return an empty string on second try.
            if (isset($widgets[$field])) {
                continue;
            }

            // Wrap an exception from PropertyAccessor in a BadRequestException.
            try {
                $fieldView = $this->propertyAccessor->getValue($view, $field);
            } catch (ExceptionInterface $e) {
                throw new BadRequestException(
                    sprintf('FormView not found for field identifier "%s".', $field),
                    0,
                    $e
                );
            }

            // Render the field widget.
            $widgets[$field] = $this->renderer->searchAndRenderBlock($fieldView, 'widget');
        }

        $presenter->sendJson((object) ['widgets' => $widgets]);
    }