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

Support React form fields #995

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
26 changes: 26 additions & 0 deletions src/Classes/MyRadio/MyRadioForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,16 @@ public function render($frmcustom = [])
$captcha = null;
}

// If we're using a React field, load in the prerequisites
$hasReact = !empty(array_filter(/**
* @param MyRadioFormField $field
* @return boolean
*/ $this->fields,
function ($field) {
return $field->getType() === MyRadioFormField::TYPE_REACT;
}
));

$fields = [];
$redact = [];
foreach ($this->fields as $field) {
Expand Down Expand Up @@ -346,6 +356,22 @@ public function render($frmcustom = [])
->addVariable('redact', $redact)
->addVariable('captcha', $captcha)
->addVariable('frm_custom', $frmcustom);

if ($hasReact) {
$reactComponentFields = [];
foreach ($fields as $field) {
if ($field['type'] !== MyRadioFormField::TYPE_REACT) {
continue;
}
$componentType = $field['options']['component'];
if (!isset($reactComponentFields[$componentType])) {
$reactComponentFields[$componentType] = [];
}
$reactComponentFields[$componentType][] = $field;
}
$twig = $twig->addVariable('react', $reactComponentFields);
}

$twig->render();
}

Expand Down
20 changes: 20 additions & 0 deletions src/Classes/MyRadio/MyRadioFormField.php
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,22 @@ class MyRadioFormField
*/
const TYPE_SECTION_CLOSE = 0x16;

/**
* The constant used to specify this MyRadioFormField is a custom React component.
*
* It takes the following custom options:
* * component - the name of the component to render
* (must be default export of a file called "Public/js/myradio.form.react.{component|lowercase}.js)
*
* The component is imported from the above file, and rendered with the following props:
* * formName: the name of the form
* * field: the output of $this->render(), JSON-encoded
*
* It should render an <input type="hidden" name={formName + "-" + field.name} value={JSON.stringify(value)} />
* (in other words, a input named the same as all other field inputs, with the field's value JSON-encoded).
*/
const TYPE_REACT = 0x17;

/**
* The name/id of the Form Field.
*
Expand Down Expand Up @@ -602,6 +618,7 @@ public function render()
* @return mixed The submitted field value
*
* @throws MyRadioException if the field type does not have a valid read handler
* @throws \JsonException if the React field type returns invalid JSON
*
* @todo Verify all returns deal with repeated elements correctly
*/
Expand Down Expand Up @@ -843,6 +860,9 @@ public function readValue($prefix)

return $times;
break;
case self::TYPE_REACT:
// React fields should dump in JSON
return json_decode($_REQUEST[$name], true, 512, JSON_THROW_ON_ERROR);
default:
throw new MyRadioException(
'Field type ' . $this->type . ' does not have a valid value interpreter definition.'
Expand Down
2 changes: 2 additions & 0 deletions src/Public/js/vendor/es-module-shims.min.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/Public/js/vendor/es-module-shims.min.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/Public/js/vendor/htm.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading