Closed rob-baker-ar closed 5 months ago
This issue also occurs if I leave out the fom field form the Matrix block and call this directly:
{{ freeform.form("[formHandle]").render() }}
Hi @rob-baker-ar,
Sorry for the delay and the trouble you're experiencing.
I have tested this out on my end, and it seems to work alright. I am using a sample Freeform formatting template like Flexbox or Basic Light and the template code I have for the entry + Matrix field is:
<div class="entry">
<h1>{{ entry.title }}</h1>
{{ entry.body }}
{% for block in entry.myMatrixField.all() %}
{% if block.type == "form" %}
<h3>{{ block.myFreeformForm.name }}</h3>
{{ block.myFreeformForm.render }}
<p>{{ block.someOtherField }}</p>
{% elseif block.type == "whatever" %}
<p>Whatever</p>
{% endif %}
{% endfor %}
</div>
It displays correctly and seems to submit correctly.
Are you doing something different from what I am doing? And does it work for you if you adjust your template code to something similar to mine and use a sample Freeform formatting template such as Flexbox? 🙂
My best guess is that you are using a custom formatting template and something in there needs to be adjusted. If that's the case, can you please share it with me and I can help with that? 🙂
Hi @kjmartens,
Thanks for the update.
If I use a built in / example template for rendering the form, it works OK. It has been hard to narrow down exactly what is at the rout of this due to #1224 but I think I narrowed it down:
In my (old) template there was something like this:
{% for row in form %}
...
{% for field in row %}
...
{{ field.renderInput({
id: "field_id",
class: "field_class"
}) }}
...
{% endfor %}
...
{% endfor %}
This generates the previously referred to error. I have been trying to work out what options to pass in to that method to replicate the old functionality as it's not 100% clear from the code or docs and came up with this:
{% for row in form %}
...
{% for field in row %}
...
{{ field.renderInput({
attributes: {
input: {
id: "field_id",
class: "field_class"
}
}
}) }}
...
{% endfor %}
...
{% endfor %}
But this is not 100% working either. Seems to behave differently depending on whether the form is rendered from a standard Twig context or from a controller which delivers the HTML via AJAX to the front-end (some forms we load just in time when users are scrolling through long pages, which helps with DOM complexity and CSRF as we use front-end static caching).
I realise this is not necessarily a "normal" implementation / approach, but it works (worked?) in v4 and suited us quite well. I may have to think again on how this bit works.
The PHP code to render the form in the AJAX context looks like:
$options = []; // these options are in fact identical to those passed in when in the Twig context
$form = Freeform::getInstance()->forms->getFormByHandle($form_handle);
$html = (string) $form->render($options);
Hi @rob-baker-ar,
I have tested the Freeform 5 approach like this, and it works correctly in my testing:
{{ field.renderInput({
attributes: {
input: {
id: "zesty",
novalidate: true,
class: "input-element",
},
}
}) }}
However, you mention you're using AJAX and not a normal implementation. Can I ask, are you using a formatting template for your form? Or is this coded directly into the (regular) template that the form is being loaded into?
@kjmartens The snippet above is in a custom formatting template - defined in Freeform > Settings > Formatting Templates. My code does not interfere with this, so it should be using the same formatting template for rendering in both contexts.
The important bits from the controller I have that renders the form for AJAX:
v4 version:
$form_model = Freeform::getInstance()->forms->getFormByHandle($form_handle);
$form = $form_model->getForm();
$html = $form->render($options);
v5 version
$form = Freeform::getInstance()->forms->getFormByHandle($form_handle);
$html = $form->render($options);
$options
contains dynamicNotification
, submitClass
& overrideValues
for v4 and fields
to do the same thing in v5.
Thanks for the additional information, @rob-baker-ar. I've queued this up for @gustavs-gutmanis to have a peek at and see what insight he can offer here. 🙂
@rob-baker-ar,
Is it possible you still are calling id
directly instead of through attributes
somewhere else in the template? Is there any chance we could see your complete formatting template and controller? 🙂
I can't share the whole template / controller, but in the version I had, as can be seen above, the template call for input render looked like:
{{ field.renderInput({
id: "field_id",
class: "field_class"
}) }}
Which makes sense when you look at the headline error: It's trying to assign a string
to a field that expects an int
. In the old code that would have made sense, but in the new, because it's not wrapped in an attributes
key, I'm guessing it's trying to overwrite the field id from the database on the abstract field class, which would of course need an int
opposed to a string
. It's arguable whether it should be possible at all to manipulate that id from a Twig / render context.
In the controller, having checked again, there was nothing more than what's above, but was, generally speaking, doing the old way of overriding values, so this may all come down to that in the end. It would be helpful if there were examples in the docs of exactly what to pass in to the various different rendering methods (i.e. field.render()
, field.renderInput()
, etc) as well as the top-level form.render()
.
Hi @rob-baker-ar,
You should be passing these as attributes to the specific target element (probably input
in this case).
But you're completely on point regarding docs clarity and the fact that it shouldn't even be possible to override an ID. That is an oversight on our part and will be corrected, sorry for the inconvenience.
We will also address docs examples, of course.
Describe the bug or issue you're experiencing
I get a
TypeError
exception of "Cannot assign string to property Solspace\Freeform\Fields\AbstractField::$id of type ?int" when trying to call therender()
method (with no parameters) on a "Freeform form" field attached to a Matrix block.This is on an install that has just been upgraded from v4. This is in our DEV environment - Freeform v5 has not been put live yet.
I am not seeing any issues in the CMS / control panel screens for the form.
The form is fairly simple (9 text fields, 1 email, 1 drop down, 1checkboxes field, a hidden field and a button), no integrations,
Steps to reproduce
{{ formField.render() }}
)Expected behavior
The form renders as before.
Versions
Redacted Stack Trace