Callbacks for the controls with choices
- This topic has 6 replies, 2 voices, and was last updated 2 years, 7 months ago by
Robert Zeigler.
-
AuthorPosts
-
September 7, 2022 at 7:50 PM #38206
Robert Zeigler
ParticipantHello,
When declaring a field with choices (options) like
select_advanced
,
instead of providing the complete set of options and making the declaration heavier,
it would be nice to have an option to provide a callback function / method that will be called on demand when necessary, and it will return an array of options.Once abstracted from the actual data / content, the field declaration part will run faster,
and we'll stop wrapping it with conditions to avoid declaring the fields when they are not used within a specific HTTP request.This is what I do:
[ 'type' => 'select_advanced', 'name' => esc_html__( 'Supervisor', 'apms' ), 'id' => 'supervisor_id', 'options' => APMS_User_DAO::get_instance()->get_supervisors(), 'required' => true, 'js_options' => [ 'placeholder' => esc_html__( 'Choose Supervisor', 'apms' ), ], 'admin_columns' => true ]
This is what I would like to do:
[ 'type' => 'select_advanced', 'name' => esc_html__( 'Supervisor', 'apms' ), 'id' => 'supervisor_id', 'options' => function() { // I might have additional information that I can use to generate the options // which is not available during the declaration // and this callback will be called only when needed return APMS_User_DAO::get_instance()->get_supervisors(); }, 'required' => true, 'js_options' => [ 'placeholder' => esc_html__( 'Choose Supervisor', 'apms' ), ], 'admin_columns' => true ]
Thank You
September 7, 2022 at 11:02 PM #38212Long Nguyen
ModeratorHi,
Running an anonymous function in an array is deprecated from PHP 7.2 and removed from PHP 8.0. Please use a declare function like the code you are doing.
September 8, 2022 at 1:33 AM #38218Robert Zeigler
ParticipantHi,
I'm not talking about anonymous functions, it's about the plugin not allowing to pass a callback function and requireing the options to be initialized during the field definition.
Please ignore the code samples and read the text above.Thank You
September 8, 2022 at 12:35 PM #38223Long Nguyen
ModeratorHi,
You can use a callback function to return an array of
value
andlabel
for the select options as well. Here is the demo codeadd_filter( 'rwmb_meta_boxes', 'your_prefix_function_name' ); function your_prefix_function_name( $meta_boxes ) { $meta_boxes[] = [ 'title' => __( 'My Custom Fields', 'your-text-domain' ), 'id' => 'my-custom-fields', 'fields' => [ [ 'type' => 'select_advanced', 'name' => esc_html__( 'Supervisor', 'apms' ), 'id' => 'supervisor_id', 'options' => my_func9999(), 'required' => true, 'js_options' => [ 'placeholder' => esc_html__( 'Choose Supervisor', 'apms' ), ], 'admin_columns' => true ] ], ]; return $meta_boxes; } function my_func9999() { return [ 'a' => 'A', 1 => 1, 2 => 2, 'b' => 'B' ]; }
September 9, 2022 at 3:53 PM #38246Robert Zeigler
ParticipantHi,
Yes, I can call the function and it will return the options, but in your example it's a simple function that doesn't take time to execute. And it is not used as a callback, because I have to call it manually.
Now, say that
my_func9999
function runs queries against the database, requests some data from third party services, etc., and takes a second or more to execute. Then each time I declare that field, it will slow down the request.
So the only option I have currently is to avoid declaring that field and wrap the declaration with a condition check, likeadd_filter( 'rwmb_meta_boxes', 'your_prefix_function_name' ); function your_prefix_function_name( $meta_boxes ) { if( $i_really_need_this_field_during_this_request ) { $meta_boxes[] = [ 'title' => __( 'My Custom Fields', 'your-text-domain' ), 'id' => 'my-custom-fields', 'fields' => [ [ 'type' => 'select_advanced', 'name' => esc_html__( 'Supervisor', 'apms' ), 'id' => 'supervisor_id', 'options' => my_func9999(), 'required' => true, 'js_options' => [ 'placeholder' => esc_html__( 'Choose Supervisor', 'apms' ), ], 'admin_columns' => true ] ], ]; } return $meta_boxes; }
It is hard to determine if
$i_really_need_this_field_during_this_request
is true or false.
So this can be solved if the plugin allows to pass themy_func9999
function as a callback, and not call it directly during the declaration, likefunction your_prefix_function_name( $meta_boxes ) { $meta_boxes[] = [ 'title' => __( 'My Custom Fields', 'your-text-domain' ), 'id' => 'my-custom-fields', 'fields' => [ [ 'type' => 'select_advanced', 'name' => esc_html__( 'Supervisor', 'apms' ), 'id' => 'supervisor_id', // I'm passing this function as a callback, instead of calling it directly, // so only when the plugin needs the options, it can call the callback function itself and get the options 'options' => 'my_func9999', 'required' => true, 'js_options' => [ 'placeholder' => esc_html__( 'Choose Supervisor', 'apms' ), ], 'admin_columns' => true ] ], ]; return $meta_boxes; }
Or plugin can provide a filter to get the options like
function your_prefix_function_name( $meta_boxes ) { $meta_boxes[] = [ 'title' => __( 'My Custom Fields', 'your-text-domain' ), 'id' => 'my-custom-fields', 'fields' => [ [ 'type' => 'select_advanced', 'name' => esc_html__( 'Supervisor', 'apms' ), 'id' => 'supervisor_id', // I'm not passing any option, I'll use a filter hook to provide the options later 'options' => array(), 'required' => true, 'js_options' => [ 'placeholder' => esc_html__( 'Choose Supervisor', 'apms' ), ], 'admin_columns' => true ] ], ]; return $meta_boxes; } add_filter( 'rwmb_meta_boxes_get_options', 'my_func9999_v2', 10, 3 ); function my_func9999_v2( $options, $box_id, $field_id ) { if( 'my-custom-fields' === $box_id && 'supervisor_id' === $field_id ) { $options['a'] = 'A'; $options[1] = 1; $options[2] = 2; $options['b'] = 'B'; } return $options; }
So when the plugin needs the options, for example when it is going to draw the dropdown, it can call the callback function, or it can run
apply_filters
to get the options.I know that the plugin doesn't support passing callbacks and it doesn't filter the options either, but it would be great if it could do that, it would free the developers from writing a lot of messy conditions and it will work much more faster.
Hope it makes sense.
Thank's a lot.September 11, 2022 at 1:41 PM #38258Long Nguyen
ModeratorHi,
Thanks for the additional information.
In this case, I think you can use the filter
rwmb_normalize_field
to add options for the select field and you can run your custom function to get the options. Please read more on the documentation https://docs.metabox.io/filters/rwmb-normalize-field/September 17, 2022 at 11:14 PM #38343Robert Zeigler
ParticipantHi,
The plugin runs this filter
rwmb_normalize_field
always, on any page,
including the pages that don't show/use the custom fields.So the only way is to declare the fields only after checking the current page to be the one that is going to use that field.
Thank you for your help very much, we can close this ticket.
And sorry for the late response. -
AuthorPosts
- You must be logged in to reply to this topic.