Home › Forums › Front-end Issues › Sending user to Tab on validation errors › Reply To: Sending user to Tab on validation errors
I’ve expanded on this to just highlight the field group and the tab in which fields below have errors. I haven’t tested this code extensively but it should work with all of the simple fields (everything except repeater, flexible content, etc). Those may work as well but I haven’t tested them.
This is sort of the approach I’ve been needing when I start getting a lot of fields and a lot of tabs on a page template.
(function($) {
$(function() {
var TabErrorMarker = {
errorClass: 'acf-tab-validation-errors',
errors: [],
fields: [],
init: function($form) {
var self = this;
this.$form = $form;
this.$tabs = this.$form.find('.acf-tab-wrap a');
var $groups = this.$form.find('.acf-postbox');
// Find all Field groups in form and then find all tabs in form.
// Then build a tabs array where each tab keeps track of its parent field group as well as its child fields.
$groups.each(function(gIndex) {
var $group = $(this),
gKey = $group.attr('id').replace('acf-', ''),
$tabs = $group.find('.acf-tab-wrap a');
$tabs.each(function(index) {
self.addTabObject($(this), {
index: $group.index(),
$el: $group
});
});
});
// ACF Hooks for adding/removing error classes on tabs and field groups of error fields hidden behind tabs.
acf.add_filter('validation_complete', this.proxy(this.validateTabs));
acf.add_action('validation_begin', this.proxy(this.removeErrors));
acf.add_action('invalid_field', this.proxy(this.addTabError));
return this;
},
addTabObject($tabLink, group) {
// Build the tab object before handing it off to the 'this.fields' array.
var self = this,
key = $tabLink.attr('data-key'),
$label = group.$el.find('.acf-field-tab').filter('[data-key="' + key + '"]'),
$fields = $label.nextUntil('.acf-field-tab'),
tab = {
index: $tabLink.index(),
key: key,
$link: $tabLink,
$label: $label
};
$fields.each(function(fIndex) {
self.addFieldObject($(this), tab, group);
});
return tab;
},
addFieldObject($field, tab, group) {
var key = $field.attr('data-key'),
type = $field.attr('data-type'),
$input = $field.find('#acf-' + key),
field = {
index: $field.index(),
key: key,
type: type,
$input: $input,
tab: tab,
group: group
};
this.fields.push(field);
return field;
},
validateTabs: function(json, $form){
// Check for validation errors and begin looping through all tabs in the form if any.
this.errors = (json.errors || []);
if(this.errors.length) {
this.addErrors();
} else {
this.removeErrors();
}
return json;
},
addErrors: function() {
// Loop over each error, find the field related to the error and mark the parent tab with an error class.
this.errors.forEach(this.proxy(function(err, index) {
var key = this.errors[index].input.replace('acf[', '').replace(']', ''),
$field = this.$form.find('.acf-field[data-key="' + key + '"]');
this.addTabError($field, this.$form);
}));
return this;
},
removeErrors: function () {
// Loop over each tab and check if all fields below that tab are error free.
// If so, remove the error class from the tab.
var self = this;
this.$tabs.each(function(i) {
self.removeTabError($(this));
});
return this;
},
addTabError: function($field) {
// Add the error class to the tab and field group of any field that has validation errors
var index = $field.index();
key = $field.attr('data-key'),
$input = $field.find('[id="acf-' + key + '"]'),
$tabLabels = $($field.get(0), this.$form).prevAll('.acf-field-tab'),
tabKey = $tabLabels.eq(0).attr('data-key'),
$tab = $('.acf-tab-wrap a[data-key=' + tabKey + ']', this.$form),
$group = $tab.closest('.acf-postbox');
$tab.addClass(this.errorClass);
$group.addClass(this.errorClass);
return this;
},
removeTabError: function($tabLink) {
// Remove the error class to the tab and field group of any field that has validation errors
var self = this,
$tabLinks = $tabLink.parents('ul').find('li a');
// Loop over each tab link, find all fields with an error class
$tabLinks.each(function(i) {
var $tab = $(this),
$group = $tab.closest('.acf-postbox'),
$errorFields = $tab.parents('.acf-fields').children('.acf-field.acf-error');
if ($errorFields.length === 0) {
$tab.removeClass(self.errorClass);
$group.removeClass(self.errorClass);
}
});
return this;
},
proxy: function(func) {
// Simple proxy function to ensure the context of a callback function is this object's instance.
var self = this;
return function() {
return func.apply(self, arguments);
};
}
};
$(function () {
var $form = $('#wpbody form');
TabErrorMarker.init($form);
});
});
})(jQuery);
And here is the CSS to highlight the tabs and field groups that have errors.
.acf-tab-button.acf-tab-validation-errors {
border-color: #F55E4F !important;
color: #F55E4F !important;
}
.acf-postbox.acf-tab-validation-errors > .hndle {
border-color: #F55E4F !important;
color: #F55E4F !important;
}
.acf-postbox.acf-tab-validation-errors > .handlediv {
color: #F55E4F !important;
}
The result looks like the image below.
Welcome to the Advanced Custom Fields community forum.
Browse through ideas, snippets of code, questions and answers between fellow ACF users
Helping others is a great way to earn karma, gain badges and help ACF development!
We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Privacy Policy. If you continue to use this site, you consent to our use of cookies.