solspace / craft-freeform

Freeform for Craft: The most reliable form builder that's ready for wherever your project takes you.
https://docs.solspace.com/craft/freeform/v5/
Other
47 stars 61 forks source link

$this->getValue() is blank on custom field #1383

Closed Coysh closed 4 months ago

Coysh commented 4 months ago

What happened?

I'm creating a custom field to use CKEditor 5. The implementation is working fine, and the HTML is being passed to Freeform and is appearing in the database.

However the value is not being displayed in Freeform, and constantly comes back NULL:

WysiwygField.php

<?php

namespace modules\ealistings\Fields;

use Solspace\Freeform\Attributes\Field\Type;
use Solspace\Freeform\Fields\AbstractField;

#[Type(
    name: 'WYSIWYG Editor',
    typeShorthand: 'wysiwyg',
    iconPath: __DIR__ . '/wysiwyg-field.svg',
    previewTemplatePath: __DIR__ . '/wysiwyg-field.ejs',
)]
class WysiwygField extends AbstractField
{

    #[Input\TextArea(
        label: 'Default value',
        instructions: 'Enter a default value for this field',
    )]
    protected ?string $defaultValue = '';

    protected function getInputHtml(): string
    {
        $attributes = $this->getAttributes()->getInput()->clone();

        $attributes
            ->setIfEmpty('name', $this->getHandle())
            ->setIfEmpty('id', $this->getIdAttribute())
            ->replace('class', 'wysiwyg-editor')
            ->setIfEmpty('placeholder', 'Enter your content here...')
            ->setIfEmpty('value', $this->getValue())
            ->set($this->getRequiredAttribute());

        #This displays NULL
        #echo "<pre>";var_dump($this->getValue());echo "</pre>";die();

        return '<textarea data-test="true" id="editor"' . $attributes . '>' . htmlentities($this->getValue()) . ' </textarea>';
    }

    public function getType(): string
    {
        return 'wysiwyg';
    }
}

You can see the value in the database here:

CleanShot 2024-06-27 at 17 20 09@2x

And the FreeForm blank entry:

CleanShot 2024-06-27 at 17 20 36

Don't think it's relevant, but wysiwyg-field.ejs

<textarea placeholder="<%= placeholder %>"><%= defaultValue %></textarea>

Errors and Stack Trace (if available)

No response

How can we reproduce this?

  1. Create custom field
  2. Enter value into field and submit form

Freeform Edition

Pro

Freeform Version

5.5

Craft Version

Latest

When did this issue start?

No response

Previous Freeform Version

No response

gustavs-gutmanis commented 4 months ago

Hi @Coysh,

Glad you're trying out custom field types. I will add a better default rendering of an unknown field type in submissions, but even with that, I guess you would like to see the formatted HTML or a textarea in that place.

There is an event \Solspace\Freeform\Services\SubmissionsService::EVENT_RENDER_FIELD which lets you override the way a field is rendered in the submissions edit view. It dispatches the \Solspace\Freeform\Events\Submissions\RenderSubmissionFieldEvent event.

Here's how we use this event to render custom stripe payment data:

    public function renderSubmissionFieldTemplate(RenderSubmissionFieldEvent $event): void
    {
        $field = $event->getField();
        if (!$field instanceof StripeField) {
            return;
        }

        $template = file_get_contents(__DIR__.'/../Templates/submission-field.twig');
        $noPaymentTemplate = file_get_contents(__DIR__.'/../Templates/submission-field-no-payment.twig');

        $stripeSvg = file_get_contents(__DIR__.'/../Assets/stripe.svg');

        $payment = PaymentRecord::findOne([
            'submissionId' => $event->getSubmission()->id,
            'fieldId' => $field->getId(),
        ]);

        if (!$payment) {
            $event->setOutput(
                \Craft::$app->view->renderString(
                    $noPaymentTemplate,
                    [
                        'field' => $field,
                        'submission' => $event->getSubmission(),
                        'stripeSvg' => $stripeSvg,
                    ]
                )
            );

            return;
        }

        $paymentMethod = $payment?->getPaymentMethod();

        $event->setOutput(
            \Craft::$app->view->renderString(
                $template,
                [
                    'field' => $field,
                    'amount' => $this->priceService->getFormattedAmount($payment->amount, $payment->currency),
                    'currency' => $payment?->currency,
                    'stripeSvg' => $stripeSvg,
                    'paymentMethodIcon' => $this->iconService->getIconFromPaymentMethod($paymentMethod),
                    'paymentMethod' => $paymentMethod,
                    'submission' => $event->getSubmission(),
                    'payment' => $payment,
                ]
            )
        );
    }

This lets you render your own twig templates, to take care of rendering the field. In your case, you would probably just use Craft's built in textarea field in your twig template.

{% import "_includes/forms" as forms %}

{{ forms.textareaField({
    label: field.label,
    name: field.handle,
    id: field.handle,
    required: field.required,
    errors: submission.errors(field.handle),
    value: submission[field.handle].value,
    placeholder: field.placeholder,
    rows: 8,
}) }}

But you could roll the actual CKEditor instance in the Submission Editor as well. Hope this helps.

Coysh commented 4 months ago

Hi @gustavs-gutmanis - thanks for this. I will have a look tomorrow. I'm assuming it's not displaying by default because it's custom HTML? Or is is it purely because I haven't rendered/outputted anything for the custom field?

gustavs-gutmanis commented 4 months ago

It's rendering the thing you have in your html input method. But in the Submissions Edit view it looks rather terrible. I will adjust the default render of unknown types to be a text input field, and then if anyone needs a more sophisticated version, they would use the event.

Coysh commented 4 months ago

Thanks - really helpful