Support Forum
Hello,
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
Hi,
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.
Hi,
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
Hi,
You can use a callback function to return an array of value
and label
for the select options as well. Here is the demo code
add_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'
];
}
Hi,
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, like
add_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 the my_func9999
function as a callback, and not call it directly during the declaration, 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 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.
Hi,
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/
Hi,
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.