craft/fields/Matrix::validateEntries
use new:X
index as fallback if uid is empty to index new entries individually
#15103
-
Lets say we have an Entry with a matrix field and want to be able to create such an entry via site request via ajax. {{ hiddenInput('fields[matrix][sortOrder][]', 'new:1') }}
{{ hiddenInput('fields[matrix][sortOrder][]', 'new:2') }}
{{ hiddenInput('fields[matrix][sortOrder][]', 'new:3') }}
{% namespace "fields[matrix][blocks][new:1]" %}
{{ hiddenInput('type', 'text') }}
<input type="text" name="title">
{% endnamespace %}
{% namespace "fields[matrix][blocks][new:2]" %}
{{ hiddenInput('type', 'text') }}
<input type="text" name="title">
{% endnamespace %}
{% namespace "fields[matrix][blocks][new:3]" %}
{{ hiddenInput('type', 'quoteModule') }}
<input type="text" name="title">
{% endnamespace %} leaving all titles blank results in errors for all fields, unfortunately those have no uid yet, so this line https://github.com/craftcms/cms/blob/5.1.7/src/fields/Matrix.php#L1014 if (!$entry->validate()) {
$element->addModelErrors($entry, "$this->handle[$entry->uid]");
$allEntriesValidate = false;
} will create an array like
I hope I don't need to explain why it could be tedious to find the exact matching HTML element / matrix block for each possible error. // use a counter
$i = 1;
if ($value instanceof EntryQuery) {
/** @var Entry[] $entries */
$entries = $value->getCachedResult() ?? (clone $value)->status(null)->limit(null)->all();
$allEntriesValidate = true;
$scenario = $element->getScenario();
foreach ($entries as $entry) {
$entry->setOwner($element);
/** @var Entry $entry */
if (
$scenario === Element::SCENARIO_ESSENTIALS ||
($entry->enabled && $scenario === Element::SCENARIO_LIVE)
) {
$entry->setScenario($scenario);
}
if (!$entry->validate()) {
$uniqueId = $entry->uid;
// if empty index by new + counter
if(empty($uniqueId)){
$uniqueId = "new:" . ($i++);
}
$element->addModelErrors($entry, "$this->handle[$uniqueId]");
$allEntriesValidate = false;
}
}
if (!$allEntriesValidate) {
// Just in case the entries weren't already cached
$value->setCachedResult($entries);
}
} else {
$entries = $value->all();
} This way we have an array like {
"matrix[new:1].title": [
"Title cannot be blank.",
],
"matrix[new:2].title": [
"Title cannot be blank.",
],
"matrix[new:3].title": [
"Title cannot be blank.",
]
} And we can return |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 4 replies
-
Thanks for pointing that out. That’s actually a bug, as for blocks with multiple errors, it would just be impossible to know how they’re grouped (at least without looking at the errors on each nested entry). I’ve just fixed that for the next release. Going with the format |
Beta Was this translation helpful? Give feedback.
Thanks for pointing that out. That’s actually a bug, as for blocks with multiple errors, it would just be impossible to know how they’re grouped (at least without looking at the errors on each nested entry).
I’ve just fixed that for the next release. Going with the format
newX
instead ofnew:X
, to be consistent withMatrix::serializeValue()
. (95205c2)