Support Forum
Support › Meta Box Conditional Logic › Conditional MB Using Clone-able Select FieldResolved
I a group field that begins with a select fields. Based on the select fields value determines what fields are visible in the rest of the group as well as trigger another metabox to be visible. The group is clone-able.
The cloneable group is sf_sign_modules
:
https://gist.github.com/mgratch/6044e6178827f93f6943adf693c78305#file-functions-php-L17
The select field sf_sign_module_type
is defined here: https://gist.github.com/mgratch/6044e6178827f93f6943adf693c78305#file-functions-php-L22
The room-availability
metabox to show/hide is defined here: https://gist.github.com/mgratch/6044e6178827f93f6943adf693c78305#file-functions-php-L509
The metabox conditional checks are defined here: https://gist.github.com/mgratch/6044e6178827f93f6943adf693c78305#file-functions-php-L576
Expected behavior: When I select the value room-availability-module
from the sf_sign_module_type
select field or a cloned version of it i.e. sf_sign_modules[1][sf_sign_module_type]
the room-availability
metabox should be visible.
What is happening: the room-availability
metabox is not visible.
Thank you, any help is appreciated.
Hi,
Thanks a lot for your very detail topic!
After looking at the bug and the code, I found a bug in this case. I've released a new version of the plugin. Please update it.
Hi,
Thank you for such a quick a reply.
When I select the value room-availability-module
from the sf_sign_module_type
select field the room-availability
metabox is visible. Unfortunately sf_sign_module_type
clones i.e. sf_sign_modules[1][sf_sign_module_type]
still do not trigger the conditional action.
Thanks again!
I got it. The thing here is the plugin detects the first element that contains the condition, which is the first clone in this case.
It would be very confusing if it detects all elements and parse the conditions. The plugin can't understand whether to show "room-availability" when all clones satisfy the condition or any clone satisfy it. In this case, this is "any", but in general, there's no way to know that :(.
I think to solve this problem, please just set the first clone as the trigger for the rules.
I get your point, I can't think of a situation where ALL clones would have to meet 1 condition, but regardless I get it.
in case anyone needs it or you see a good way to include it I created the following callback:
// js functions
function checkCompareStatement(needle, haystack, compare) {
if (needle === null || typeof needle === 'undefined') {
needle = '';
}
switch (compare) {
case '=':
if ($.isArray(needle) && $.isArray(haystack)) {
return $(needle).not(haystack).length === 0 && $(haystack).not(needle).length === 0;
}
return needle == haystack;
case '>=':
return needle >= haystack;
case '>':
return needle > haystack;
case '<=':
return needle <= haystack;
case '<':
return needle < haystack;
case 'contains':
if ($.isArray(needle)) {
return $.inArray(haystack, needle) > -1;
} else if ($.type(needle) === 'string') {
return needle.indexOf(haystack) > -1;
}
return false;
case 'in':
if (!$.isArray(needle)) {
return haystack.indexOf(needle) > -1;
}
var found = false;
$.each(needle, function(index, value) {
if ($.isNumeric(value)) {
value = parseInt(value);
}
if (haystack.indexOf(value) > -1) {
found = true;
}
});
return found;
case 'start_with':
case 'starts with':
return needle.indexOf(haystack) === 0;
case 'end_with':
case 'ends with':
haystack = new RegExp(haystack + '$');
return haystack.test(needle);
case 'match':
haystack = new RegExp(haystack);
return haystack.test(needle);
case 'between':
if ($.isArray(haystack) && typeof haystack[0] !== 'undefined' && typeof haystack[1] !== 'undefined') {
return checkCompareStatement(needle, haystack[0], '>=') && checkCompareStatement(needle, haystack[1], '<=');
}
}
}
function check_for_clone(haystack, compare, needle) {
var val;
var $elements = $('[name*="' + haystack + '"]');
$.each($elements, function() {
if (true === checkCompareStatement(needle, this.value, compare)) {
val = this.value;
return false;
}
})
return val;
}
// your field or metabox
'visible' => array(
'when' => array(
array( 'check_for_clone("sf_sign_module_type", "=", "room-availability-module")', '=', 'room-availability-module') ,
array( 'check_for_clone("sf_sign_module_type", "=", "room-current-activity-module")', '=', 'room-current-activity-module'),
array( 'check_for_clone("sf_sign_module_type", "=", "room-upcoming-activity-module")', '=', 'room-upcoming-activity-module'),
),
'relation' => 'or',
),
I am simply re-using the built-in checkCompareStatement
-- if some of your functions had global access it could be very useful, along with other conditional passed parameters, i.e. needle
, compare
, haystack
Hey @mgratch, your solution is great! Thanks for posting it here for others. I completely forgot about the custom callback. Nice work!