Support Forum
Support › Meta Box Group › whats wrong with my validation?
I am doing an event custom post type. I'd like to check if the start takes place after the end. in my admin-ajax action I return false for testing purposes, but regardless if there is a value or not the post gets always saved.
This is my post type:
register_post_type(PREFIX . 'event', [
'label' => esc_html__('Termine', NAME_SPACE),
'labels' => [
'name' => esc_html__('Termine', NAME_SPACE),
'singular_name' => esc_html__('Termin', NAME_SPACE),
'add_new' => esc_html__('Termin hinzufügen', NAME_SPACE),
'add_new_item' => esc_html__('Neuen Termin hinzufügen', NAME_SPACE),
'edit_item' => esc_html__('Termin bearbeiten', NAME_SPACE),
'new_item' => esc_html__('Neuer Termin', NAME_SPACE),
'view_item' => esc_html__('Termin anzeigen', NAME_SPACE),
'view_items' => esc_html__('Termine anzeigen', NAME_SPACE),
'search_items' => esc_html__('Termine suchen', NAME_SPACE),
'not_found' => esc_html__('Keine Termine gefunden', NAME_SPACE),
'not_found_in_trash' => esc_html__('Keine Termine im Papierkorb gefunden', NAME_SPACE),
'parent_item_colon' => esc_html__('Haupt Termin:', NAME_SPACE),
'all_items' => esc_html__('Alle Termine', NAME_SPACE),
'archives' => esc_html__('Termin Archive', NAME_SPACE),
'attributes' => esc_html__('Termin Attribute', NAME_SPACE),
'insert_into_item' => esc_html__('In Termin einfügen', NAME_SPACE),
'uploaded_to_this_item' => esc_html__('Zu diesem Termin hochladen', NAME_SPACE),
'featured_image' => esc_html__('Termin-Bild', NAME_SPACE),
'set_featured_image' => esc_html__('Termin-Bild festlegen', NAME_SPACE),
'remove_featured_image' => esc_html__('Termin-Bild entfernen', NAME_SPACE),
'use_featured_image' => esc_html__('Als Termin-Bild benutzen', NAME_SPACE),
'menu_name' => esc_html__('Termine', NAME_SPACE),
'filter_items_list' => esc_html__('Termin-Liste filtern', NAME_SPACE),
'filter_by_date' => esc_html__('', NAME_SPACE),
'items_list_navigation' => esc_html__('Temine-Liste paginierung', NAME_SPACE),
'items_list' => esc_html__('Termine-Liste', NAME_SPACE),
'item_published' => esc_html__('Termin veröffentlicht', NAME_SPACE),
'item_published_privately' => esc_html__('Termin privat veröffentlicht', NAME_SPACE),
'item_reverted_to_draft' => esc_html__('Zum Entwurf zurücksetzteter Termin', NAME_SPACE),
'item_scheduled' => esc_html__('Geplanter Termin', NAME_SPACE),
'item_updated' => esc_html__('Termin aktualisiert', NAME_SPACE),
],
'description' => '',
'public' => true,
'hierarchical' => false,
'exclude_from_search' => false,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_nav_menus' => true,
'show_in_admin_bar' => true,
'show_in_rest' => false,
'query_var' => false,
'can_export' => true,
'delete_with_user' => false,
'has_archive' => true,
'rest_base' => '',
'show_in_menu' => true,
'menu_position' => '',
'menu_icon' => 'dashicons-calendar',
'capability_type' => 'post',
'supports' => ['revisions'],
'taxonomies' => [],
'rewrite' => [
'slug' => 'termin',
'with_front' => false,
]
]);
These are my field:
$event_validation_error_message = __('Der Start darf nicht nach dem Ende stattfinden', NAME_SPACE);
$jquery_date_format = 'dd-mm-yy';
$fields[] = [
'title' => __('Veranstaltung-Optionen', NAME_SPACE),
'post_types' => [PREFIX . 'event'],
'context' => 'side',
'fields' => [
[
'id' => PREFIX . 'day_long',
'name' => __('Ganztägig?', NAME_SPACE),
'type' => 'switch',
'style' => 'rounded',
'on_label' => 'Ja',
'off_label' => 'Nein',
],
[
'name' => __('Veranstaltungszeit', NAME_SPACE),
'id' => PREFIX . 'event_time',
'type' => 'group',
'hidden' => [
'when' => [[PREFIX . 'day_long', '!=', false]],
'relation' => 'or',
],
'fields' => [
[
'name' => __('Start'),
'id' => 'start_time',
'type' => 'datetime',
'size' => 27,
'js_options' => [
'dateFormat' => $jquery_date_format,
'controlType' => 'slider',
'showButtonPanel' => false,
],
'inline' => true,
'timestamp' => true,
'required' => true,
],
[
'name' => __('Ende'),
'id' => 'end_time',
'type' => 'datetime',
'size' => 27,
'js_options' => [
'dateFormat' => $jquery_date_format,
'controlType' => 'slider',
'showButtonPanel' => false,
],
'inline' => true,
'timestamp' => true,
'required' => true,
]
]
],
[
'name' => __('Veranstaltungstage', NAME_SPACE),
'id' => PREFIX . 'event_days',
'type' => 'group',
'visible' => [
'when' => [[PREFIX . 'day_long', '!=', false]],
'relation' => 'or',
],
'fields' => [
[
'name' => __('Start'),
'id' => PREFIX . 'start_day',
'type' => 'date',
'size' => 27,
'js_options' => [
'dateFormat' => $jquery_date_format,
'showButtonPanel' => false,
],
'inline' => true,
'timestamp' => true,
'required' => true,
],
[
'name' => __('Ende'),
'id' => PREFIX . 'end_day',
'type' => 'date',
'size' => 27,
'js_options' => [
'dateFormat' => $jquery_date_format,
'showButtonPanel' => false,
],
'inline' => true,
'timestamp' => true,
'required' => true,
]
]
],
],
'validation' => [
'rules' => [
PREFIX . 'event_time' => [
'remote' => admin_url('admin-ajax.php?action=validate_event'),
],
PREFIX . 'event_days' => [
'remote' => admin_url('admin-ajax.php?action=validate_event'),
],
],
'messages' => [
PREFIX . 'event_time' => [
'remote' => $event_validation_error_message
],
PREFIX . 'event_days' => [
'remote' => $event_validation_error_message,
],
],
],
];
$fields[] = [
'title' => __('Titel', NAME_SPACE),
'post_types' => [PREFIX . 'event'],
'context' => 'after_title',
'style' => 'seamless',
'fields' => [
[
'type' => 'heading',
'name' => __('Titel', NAME_SPACE),
],
[
'id' => PREFIX . 'title',
'type' => 'text',
'required' => true,
],
]
];
This is my Ajax Action
add_action('wp_ajax_validate_event', function () {
echo 'false';
die();
});
What is wrong?
Hello,
The remote validation will work when you type something to the field so it won't work with the group field. Also, please note that the remote validation does not work with the Block editor, it works with Classic editor only.
You can test this feature again with your field title
.
Where in the docs is it mentioned that the validation does not work with the group field? Afaik the documentation only says "add a key validation to the field group settings". Since the group field has its own 'fields' key it should work according to the docs.
However, I found a workaround:
$fields[] = [
'title' => __('Validation', NAME_SPACE),
'post_types' => [PREFIX . 'event'],
'context' => 'form_top',
'style' => 'seamless',
'fields' => [
[
'id' => PREFIX . 'validation',
'type' => 'group',
'visible' => ['eventDateValidator()', false],
'fields' => [
[
'id' => 'error_message',
'type' => 'custom_html',
'std' => "<div class='hidden event-error'><p>$event_validation_error_message</p></div>",
],
[
'id' => 'hidden',
'type' => 'hidden',
'required' => true
],
]
]
],
];
This filed is only visible if my eventDateValidator() returns false, since the hidden field is required but is missing the std value prevents the submit. Seems very hacky to me.
Any other approaches to compare two custom fields values before submitting?
Hello,
We use the validation JS to validate the input value from the user. The group field works as a wrapper field and there isn't an input for this field. Also, it isn't possible to compare two current field values when submitting. It only takes one field value and sends it to the Ajax per field.
If you want to compare two fields when submitting, please take a look at the Sanitization feature https://docs.metabox.io/sanitization/
Also, it isn't possible to compare two current field values when submitting.
If you want to compare two fields when submitting, please take a look at the Sanitization feature https://docs.metabox.io/sanitization/
That's contradictory, isn't it?
I don't understand why sanitization will help, since I can't guess the correct values. If the input value for an event start date is not equal or smaller than the value for an event end date, I could swap them, but it would be confusing to save values to the database that might be wrong, without notifying the user.
Also, it isn't possible to compare two current field values when submitting.
It's not straight forward, but it is possible, as mentioned in my last post. The validation callback for a hidden field with a missing std value can compare two fields domElements. The missing std. value will prevent the form submit. You also need to initiate mutation observers observing the two input values and run rwmb.runConditionalLogic() (please note my other question regarding this function here) every time the value changes.
Hello,
As I mentioned above, the remote validation only supports validating a single field only. It does not validate by comparing two field values. You can create your own JS code to compare two or more field values.
The sanitization doesn't notify the user after processing the value but you can access all subfield values with this feature.