With the acf/prepare_field
it would work to remove the options for all my requirements.
So thanks @hube2 for pointing me at that direction.
I used some different code because i also have optgroups.
function filter_choices($field)
{
if (is_user_logged_in() && current_user_can('administrator')) {
// don't filter for admins
return $field;
}
$value = acf_get_array($field['value']);
$choices = acf_get_array($field['choices']);
// keys which will be removed
$disabled_options = array(1, 2, 3);
// value should be kept as selectable option for edit therefore remove it from disabled options
if (!is_null($value)) {
if (is_array($value)) {
$disabled_options = array_diff($disabled_options, $value);
} else {
$disabled_options = array_diff($disabled_options, array($value));
}
}
// delete keys in in normal options
$choices = array_diff_key($choices, array_flip((array) $disabled_options));
foreach ($choices as $choice_key => $choice_value) {
// delete keys in option groups
if (is_array($choice_value)) {
$choices[$choice_key] = array_diff_key($choice_value, array_flip((array) $disabled_options));
//remove empty groups from choices
if (sizeof($choices[$choice_key])==0) {
unset($choices[$choice_key]);
}
}
}
$field['choices'] = $choices;
return $field;
}
add_filter('acf/prepare_field/name=select_field_name', 'filter_choices', 20);
Anyhow a possibility to disable single options would also be good if this would be implemented in future acf versions.
Ups i have just seen that you have changed the filter function from acf/load_field
to acf/prepare_field
.
With prepare_field
the value is indeed available.
I will check if with this filter all requirements could be set.
The problem is we also have an “edit” possibility for not logined users by some “hidden key value” which they receive through email.
The post_id is then selected and given to the acf_form object
acf_form(array(
'id' => 'acf-form',
/* (int|string) The post ID to load data from and save data to. Defaults to the current post ID.
Can also be set to 'new_post' to create a new post on submit */
'post_id' => $post_id,
...
Sadly in the called filters function for select field the value is always “null” even When the priority is set to 1 / 10 / 20 / 1000.
A quick look into the source code even shows me that even in the filter ‘acf/pre_render_fields’ the values aren’t set….
from acf_field_functions.php
/**
* acf_render_fields
*
* Renders an array of fields. Also loads the field's value.
*
* @date 8/10/13
* @since 5.0.0
* @since 5.6.9 Changed parameter order.
*
* @param array $fields An array of fields.
* @param (int|string) $post_id The post ID to load values from.
* @param string $element The wrapping element type.
* @param string $instruction The instruction render position (label|field).
* @return void
*/
function acf_render_fields( $fields, $post_id = 0, $el = 'div', $instruction = 'label' ) {
// Parameter order changed in ACF 5.6.9.
if( is_array($post_id) ) {
$args = func_get_args();
$fields = $args[1];
$post_id = $args[0];
}
/**
* Filters the $fields array before they are rendered.
*
* @date 12/02/2014
* @since 5.0.0
*
* @param array $fields An array of fields.
* @param (int|string) $post_id The post ID to load values from.
*/
$fields = apply_filters( 'acf/pre_render_fields', $fields, $post_id );
// Filter our false results.
$fields = array_filter( $fields );
// Loop over and render fields.
if( $fields ) {
foreach( $fields as $field ) {
// Load value if not already loaded.
if( $field['value'] === null ) {
$field['value'] = acf_get_value( $post_id, $field );
}
// Render wrap.
acf_render_field_wrap( $field, $el, $instruction );
}
}
/**
* Fires after fields have been rendered.
*
* @date 12/02/2014
* @since 5.0.0
*
* @param array $fields An array of fields.
* @param (int|string) $post_id The post ID to load values from.
*/
do_action( 'acf/render_fields', $fields, $post_id );
}
the filter add_filter('acf/load_field/name=myselect'..
is called by far before the actual render of the select field and sadly also way before the value is set.
So your code doesn’t work.
Thx John for the explanation of the priority.
I already thought that this is the intention.
My Problem also isn’t that I don’t able to change the options (remove some) on specific conditions.
My problem is that i couldn’t fulfil all the requirements we have.
The missing option to disable individual options entries (weird sentence ^^) is an additional point.
We have already contacted the support but still waiting for some answer.
have a nice weekend 🙂
What should increasing the priority to 20 change?
From the “class-acf-field-select.php” i see that there isn’t an possibility to “disable” options.
The select itself use the “disable” in line 318.
if( !empty($field['disabled']) ) $select['disabled'] = 'disabled';
the select itself is rendered via
acf_select_input( $select );
which is in acf-input-functions.php
acf_get_select_input calls acf_walk_select_input($choices, $value)
where the “option tags are rended with “value”, “selected” and “data-i” attributes.
So no “disabled” html attribute.
// single (option)
} else {
$attrs = array(
'value' => $value
);
// If is selected.
$pos = array_search( esc_attr($value), $values );
if( $pos !== false ) {
$attrs['selected'] = 'selected';
$attrs['data-i'] = $pos;
}
$html .= sprintf( '<option %s>%s</option>', acf_esc_attr($attrs), esc_html($label) );
}
If there would be a way to access the form “post_id” to filter function of the field i could delete the “not wanted options” from the array when post_id is e.g. “new_post”.
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 Cookie Policy. If you continue to use this site, you consent to our use of cookies.