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

[Core] add dynamic list with ajax requests #4361

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
105 changes: 105 additions & 0 deletions lib/BridgeCard.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ private static function renderForm(
$form .= self::getNumberInput($inputEntry, $idArg, $id);
} elseif ($inputEntry['type'] === 'list') {
$form .= self::getListInput($inputEntry, $idArg, $id) . "\n";
} elseif ($inputEntry['type'] === 'dynamic_list') {
$form .= self::getDynamicListInput($inputEntry, $idArg, $id) . "\n";
} elseif ($inputEntry['type'] === 'checkbox') {
$form .= self::getCheckboxInput($inputEntry, $idArg, $id);
} else {
Expand Down Expand Up @@ -234,6 +236,109 @@ public static function getListInput(array $entry, string $id, string $name): str
return $list;
}

public static function getDynamicListInput(array $entry, string $id, string $name): string
{
$required = $entry['required'] ?? null;
if ($required) {
trigger_error('The required attribute is not supported for lists');
unset($entry['required']);
}

if (!isset($entry['ajax_route']) || !isset($entry['fields_name_used_as_value']) || !isset($entry['fields_name_used_for_display'])) {
trigger_error('The ajax_route and fields_name_used_as_value and fields_name_used_for_display attributes are required');
}

$attributes = self::getInputAttributes($entry);

$fieldsDisplayString = '';
foreach ($entry['fields_name_used_for_display'] as $index => $field) {
if ($index === 0) {
$fieldsDisplayString = 'option.' . $field;
} else {
$fieldsDisplayString .= ' + \' - \' + option.' . $field;
}
}

$fieldsValueString = '';
$fieldsNameUsedAsValueSeparator = isset($entry['fields_name_used_as_value_separator']) ? $entry['fields_name_used_as_value_separator'] : '-';
foreach ($entry['fields_name_used_as_value'] as $index => $field) {
if ($index === 0) {
$fieldsValueString = 'option.' . $field;
} else {
$fieldsValueString .= ' + \'' . $fieldsNameUsedAsValueSeparator . '\' + option.' . $field;
}
}

$list = sprintf(
'<input %s id="input-%s" name="%s" autocomplete="off" type="text" list="options-%s" onmousedown="
const id = \'%s\';
const inputElement = document.getElementById(\'input-\' + id);
const errorElement = document.getElementById(\'error-\' + id);
const datalist = document.getElementById(\'options-\' + id);
const options = document.getElementById(\'options-\' + id).options;

let hasError = errorElement.innerHTML === \'\' ? false : true;
if (!hasError && (!options || options.length === 0)) {
// set himself disabled while the request is progressing
inputElement.disabled = true;
inputElement.value = \'loading...\';
// used to not be blocked by cors
const proxy = \'%s\';

// Perform AJAX request
const xhr = new XMLHttpRequest();

xhr.open(\'GET\', proxy + \'%s\', true);
xhr.onerror = function () {
errorElement.innerHTML = \'failed fetching data\';
inputElement.value = \'\';
inputElement.disabled = false;
hasError = true;
}
xhr.onload = function () {
if (xhr.status === 200) {
// Parse the response and update the datalist
datalist.innerHTML = \'\'; // Clear existing options
let options = JSON.parse(xhr.responseText); // Assuming JSON response
if (%s) {
options = options[\'%s\'];
}
options.forEach(option => {
const opt = document.createElement(\'option\');

opt.innerHTML = %s; // the displayed value
opt.value = %s; // the value
datalist.appendChild(opt);
});
// set himself enabled when the request is done
inputElement.value = \'\';
inputElement.disabled = false;
} else {
errorElement.innerHTML = \'failed fetching data\';
inputElement.value = \'\';
inputElement.disabled = false;
}
};
xhr.send();
}
" />' . "\n",
$attributes,
$id,
$name,
$id,
$id,
Configuration::getConfig('proxy', 'url') ?: 'https://cors-anywhere.herokuapp.com/',
$entry['ajax_route'],
isset($entry['field_for_options']) ? 'true' : 'false',
isset($entry['field_for_options']) ? $entry['field_for_options'] : null,
$fieldsDisplayString,
$fieldsValueString,
);
$list .= sprintf('<datalist id="options-%s"></datalist>' . "\n", $id);
$list .= sprintf('<br><div id="error-%s" style="color: red; height: 28px"></div>' . "\n", $id);

return $list;
}

public static function getCheckboxInput(array $entry, string $id, string $name): string
{
Expand Down
Loading