Conditional MB Using Clone-able Select Field
Support › MB Conditional Logic › Conditional MB Using Clone-able Select FieldResolved
- This topic has 5 replies, 2 voices, and was last updated 6 years, 10 months ago by
Anh Tran.
-
AuthorPosts
-
July 6, 2018 at 4:23 AM #10465
mgratch
ParticipantI 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-L17The select field
sf_sign_module_type
is defined here: https://gist.github.com/mgratch/6044e6178827f93f6943adf693c78305#file-functions-php-L22The
room-availability
metabox to show/hide is defined here: https://gist.github.com/mgratch/6044e6178827f93f6943adf693c78305#file-functions-php-L509The 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 thesf_sign_module_type
select field or a cloned version of it i.e.sf_sign_modules[1][sf_sign_module_type]
theroom-availability
metabox should be visible.What is happening: the
room-availability
metabox is not visible.Thank you, any help is appreciated.
July 6, 2018 at 3:15 PM #10468Anh Tran
KeymasterHi,
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.
July 7, 2018 at 12:36 AM #10470mgratch
ParticipantHi,
Thank you for such a quick a reply.
When I select the value
room-availability-module
from thesf_sign_module_type
select field theroom-availability
metabox is visible. Unfortunatelysf_sign_module_type
clones i.e.sf_sign_modules[1][sf_sign_module_type]
still do not trigger the conditional action.Thanks again!
July 7, 2018 at 11:25 AM #10473Anh Tran
KeymasterI 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.
July 10, 2018 at 4:09 AM #10502mgratch
ParticipantI 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
July 11, 2018 at 4:07 PM #10515Anh Tran
KeymasterHey @mgratch, your solution is great! Thanks for posting it here for others. I completely forgot about the custom callback. Nice work!
-
AuthorPosts
- You must be logged in to reply to this topic.