Drupal 7
Ok, here's the problem: I'm trying to create a select list of countries. I have other custom lists to create, so I'm not going to download a module. Here's the current settings: http://screencast.com/t/njzbKh3Lr4 I have defined a custom function donation_form_countries_array that I originally placed as the "allowed values function."

<?php

function donation_form_countries_array()
{
	return array(
    'AF'=>'Afghanistan',
	'AL'=>'Albania',
	'DZ'=>'Algeria',
	'AS'=>'American Samoa',
	'AD'=>'Andorra',
	'AO'=>'Angola',
	'AI'=>'Anguilla',
	'AQ'=>'Antarctica',
	'AG'=>'Antigua And Barbuda',
	'AR'=>'Argentina',
	'AM'=>'Armenia',
	'AW'=>'Aruba',
	'AU'=>'Australia',
	'AT'=>'Austria',
	'AZ'=>'Azerbaijan',
	'BS'=>'Bahamas',
	'BH'=>'Bahrain',
	'BD'=>'Bangladesh',
	'BB'=>'Barbados',
	'BY'=>'Belarus',
	'BE'=>'Belgium',
	'BZ'=>'Belize',
	'BJ'=>'Benin',
	'BM'=>'Bermuda',
	'BT'=>'Bhutan',
	'BO'=>'Bolivia',
	'BA'=>'Bosnia And Herzegovina',
	'BW'=>'Botswana',
	'BV'=>'Bouvet Island',
	'BR'=>'Brazil',
	'IO'=>'British Indian Ocean Territory',
	'BN'=>'Brunei',
	'BG'=>'Bulgaria',
	'BF'=>'Burkina Faso',
	'BI'=>'Burundi',
	'KH'=>'Cambodia',
	'CM'=>'Cameroon',
	'CA'=>'Canada',
	'CV'=>'Cape Verde',
	'KY'=>'Cayman Islands',
	'CF'=>'Central African Republic',
	'TD'=>'Chad',
	'CL'=>'Chile',
	'CN'=>'China',
	'CX'=>'Christmas Island',
	'CC'=>'Cocos (Keeling) Islands',
	'CO'=>'Columbia',
	'KM'=>'Comoros',
	'CG'=>'Congo',
	'CK'=>'Cook Islands',
	'CR'=>'Costa Rica',
	'CI'=>'Cote D\'Ivorie (Ivory Coast)',
	'HR'=>'Croatia (Hrvatska)',
	'CU'=>'Cuba',
	'CY'=>'Cyprus',
	'CZ'=>'Czech Republic',
	'CD'=>'Democratic Republic Of Congo (Zaire)',
	'DK'=>'Denmark',
	'DJ'=>'Djibouti',
	'DM'=>'Dominica',
	'DO'=>'Dominican Republic',
	'TP'=>'East Timor',
	'EC'=>'Ecuador',
	'EG'=>'Egypt',
	'SV'=>'El Salvador',
	'GQ'=>'Equatorial Guinea',
	'ER'=>'Eritrea',
	'EE'=>'Estonia',
	'ET'=>'Ethiopia',
	'FK'=>'Falkland Islands (Malvinas)',
	'FO'=>'Faroe Islands',
	'FJ'=>'Fiji',
	'FI'=>'Finland',
	'FR'=>'France',
	'FX'=>'France, Metropolitan',
	'GF'=>'French Guinea',
	'PF'=>'French Polynesia',
	'TF'=>'French Southern Territories',
	'GA'=>'Gabon',
	'GM'=>'Gambia',
	'GE'=>'Georgia',
	'DE'=>'Germany',
	'GH'=>'Ghana',
	'GI'=>'Gibraltar',
	'GR'=>'Greece',
	'GL'=>'Greenland',
	'GD'=>'Grenada',
	'GP'=>'Guadeloupe',
	'GU'=>'Guam',
	'GT'=>'Guatemala',
	'GN'=>'Guinea',
	'GW'=>'Guinea-Bissau',
	'GY'=>'Guyana',
	'HT'=>'Haiti',
	'HM'=>'Heard And McDonald Islands',
	'HN'=>'Honduras',
	'HK'=>'Hong Kong',
	'HU'=>'Hungary',
	'IS'=>'Iceland',
	'IN'=>'India',
	'ID'=>'Indonesia',
	'IR'=>'Iran',
	'IQ'=>'Iraq',
	'IE'=>'Ireland',
	'IL'=>'Israel',
	'IT'=>'Italy',
	'JM'=>'Jamaica',
	'JP'=>'Japan',
	'JO'=>'Jordan',
	'KZ'=>'Kazakhstan',
	'KE'=>'Kenya',
	'KI'=>'Kiribati',
	'KW'=>'Kuwait',
	'KG'=>'Kyrgyzstan',
	'LA'=>'Laos',
	'LV'=>'Latvia',
	'LB'=>'Lebanon',
	'LS'=>'Lesotho',
	'LR'=>'Liberia',
	'LY'=>'Libya',
	'LI'=>'Liechtenstein',
	'LT'=>'Lithuania',
	'LU'=>'Luxembourg',
	'MO'=>'Macau',
	'MK'=>'Macedonia',
	'MG'=>'Madagascar',
	'MW'=>'Malawi',
	'MY'=>'Malaysia',
	'MV'=>'Maldives',
	'ML'=>'Mali',
	'MT'=>'Malta',
	'MH'=>'Marshall Islands',
	'MQ'=>'Martinique',
	'MR'=>'Mauritania',
	'MU'=>'Mauritius',
	'YT'=>'Mayotte',
	'MX'=>'Mexico',
	'FM'=>'Micronesia',
	'MD'=>'Moldova',
	'MC'=>'Monaco',
	'MN'=>'Mongolia',
	'MS'=>'Montserrat',
	'MA'=>'Morocco',
	'MZ'=>'Mozambique',
	'MM'=>'Myanmar (Burma)',
	'NA'=>'Namibia',
	'NR'=>'Nauru',
	'NP'=>'Nepal',
	'NL'=>'Netherlands',
	'AN'=>'Netherlands Antilles',
	'NC'=>'New Caledonia',
	'NZ'=>'New Zealand',
	'NI'=>'Nicaragua',
	'NE'=>'Niger',
	'NG'=>'Nigeria',
	'NU'=>'Niue',
	'NF'=>'Norfolk Island',
	'KP'=>'North Korea',
	'MP'=>'Northern Mariana Islands',
	'NO'=>'Norway',
	'OM'=>'Oman',
	'PK'=>'Pakistan',
	'PW'=>'Palau',
	'PA'=>'Panama',
	'PG'=>'Papua New Guinea',
	'PY'=>'Paraguay',
	'PE'=>'Peru',
	'PH'=>'Philippines',
	'PN'=>'Pitcairn',
	'PL'=>'Poland',
	'PT'=>'Portugal',
	'PR'=>'Puerto Rico',
	'QA'=>'Qatar',
	'RE'=>'Reunion',
	'RO'=>'Romania',
	'RU'=>'Russia',
	'RW'=>'Rwanda',
	'SH'=>'Saint Helena',
	'KN'=>'Saint Kitts And Nevis',
	'LC'=>'Saint Lucia',
	'PM'=>'Saint Pierre And Miquelon',
	'VC'=>'Saint Vincent And The Grenadines',
	'SM'=>'San Marino',
	'ST'=>'Sao Tome And Principe',
	'SA'=>'Saudi Arabia',
	'SN'=>'Senegal',
	'SC'=>'Seychelles',
	'SL'=>'Sierra Leone',
	'SG'=>'Singapore',
	'SK'=>'Slovak Republic',
	'SI'=>'Slovenia',
	'SB'=>'Solomon Islands',
	'SO'=>'Somalia',
	'ZA'=>'South Africa',
	'GS'=>'South Georgia And South Sandwich Islands',
	'KR'=>'South Korea',
	'ES'=>'Spain',
	'LK'=>'Sri Lanka',
	'SD'=>'Sudan',
	'SR'=>'Suriname',
	'SJ'=>'Svalbard And Jan Mayen',
	'SZ'=>'Swaziland',
	'SE'=>'Sweden',
	'CH'=>'Switzerland',
	'SY'=>'Syria',
	'TW'=>'Taiwan',
	'TJ'=>'Tajikistan',
	'TZ'=>'Tanzania',
	'TH'=>'Thailand',
	'TG'=>'Togo',
	'TK'=>'Tokelau',
	'TO'=>'Tonga',
	'TT'=>'Trinidad And Tobago',
	'TN'=>'Tunisia',
	'TR'=>'Turkey',
	'TM'=>'Turkmenistan',
	'TC'=>'Turks And Caicos Islands',
	'TV'=>'Tuvalu',
	'UG'=>'Uganda',
	'UA'=>'Ukraine',
	'AE'=>'United Arab Emirates',
	'UK'=>'United Kingdom',
	'US'=>'United States',
	'UM'=>'United States Minor Outlying Islands',
	'UY'=>'Uruguay',
	'UZ'=>'Uzbekistan',
	'VU'=>'Vanuatu',
	'VA'=>'Vatican City (Holy See)',
	'VE'=>'Venezuela',
	'VN'=>'Vietnam',
	'VG'=>'Virgin Islands (British)',
	'VI'=>'Virgin Islands (US)',
	'WF'=>'Wallis And Futuna Islands',
	'EH'=>'Western Sahara',
	'WS'=>'Western Samoa',
	'YE'=>'Yemen',
	'YU'=>'Yugoslavia',
	'ZM'=>'Zambia',
	'ZW'=>'Zimbabwe'
  );
}

?>

This structure is not working, it's showing "none" as my only option within the select box. http://screencast.com/t/Kn9f8Azua1

So I'm on the search to learn how to define the proper array function in order to have values display. Any help on this issue would be appreciated.

Comments

WorldFallz’s picture

If you're just trying to populate a core list field-- you don't need a function. Just put your options into the text box as follows (one per line):

AF | Afghanistan
AL | Albania
DZ | Algeria
AS | American Samoa

etc.

jonathonbyrd’s picture

I tried adding your format to the allowed values php code textarea, like so:
http://screencast.com/t/4R3BkAabazIT

It simply removed my valued and reset itself. this is really the only textarea that I see on the settings page, am I missing something?

jonathonbyrd’s picture

WHY IS NOTHING EASY WITH THIS D@MNED CMS!?

jonathonbyrd’s picture

Ok, so I found where I need to enter the field values. It only allows you to enter the field values once, prior to the field being saved. Problem is, I need to add a single option to the select input. Drupal being as intelligently designed as it is, prevents a user from doing this, specially if any data has been saved to the database. So, instead of the possibility of the admin screwing something up by changing the available options, Drupal felt that it was better that the admin should just delete the enter select box in and create a new one. boy... that was well thought out...

Not only that, but the data is saved as the most unproductive mysql variable possible, a blob.... yea, awesome.. that means I can't even view the array structure and manually update the values... freakin gold star people.. freakin gold star...

WorldFallz’s picture

blob? What exact field type are you using? I don't see any blobs in my tables and I have several select list fields.

jonathonbyrd’s picture

What db table are you looking in? I'm looking in #__field_config and #__field_config_instance

WorldFallz’s picture

ah ok-- i thought you meant the actual values of the fields, not the config settings. Don't know why they used a blob there but I wouldn't be surprised if there isn't api function to unserialize and examine that data.

jonathonbyrd’s picture

Alright, wasted two and a half hours on this. Hopefully nobody dealing with drupal 7 will have as much bad luck as I'm having with this thing.

The solution is TO NOT DO ANY CODING of your own. Drupal will not save your "Allowed values function" or your "Allowed values PHP code" any values in these boxes will just complicate your life, it will also cause the "Allowed values list" to disappear so that you cannot manually add values either. Once saved always saved and you can never adjust which method you would like to use.

Just add your values like this to the "Allowed values list" and DEAL WITH IT.

AF|Afghanistan
AL|Albania
DZ|Algeria
AS|American Samoa
AD|Andorra
AO|Angola
AI|Anguilla
AQ|Antarctica
AG|Antigua And Barbuda
AR|Argentina
AM|Armenia
AW|Aruba
AU|Australia
AT|Austria
AZ|Azerbaijan
BS|Bahamas
BH|Bahrain
BD|Bangladesh
BB|Barbados
BY|Belarus
BE|Belgium
BZ|Belize
BJ|Benin
BM|Bermuda
BT|Bhutan
BO|Bolivia
BA|Bosnia And Herzegovina
BW|Botswana
BV|Bouvet Island
BR|Brazil
IO|British Indian Ocean Territory
BN|Brunei
BG|Bulgaria
BF|Burkina Faso
BI|Burundi
KH|Cambodia
CM|Cameroon
CA|Canada
CV|Cape Verde
KY|Cayman Islands
CF|Central African Republic
TD|Chad
CL|Chile
CN|China
CX|Christmas Island
CC|Cocos (Keeling) Islands
CO|Columbia
KM|Comoros
CG|Congo
CK|Cook Islands
CR|Costa Rica
CI|Cote D\'Ivorie (Ivory Coast)
HR|Croatia (Hrvatska)
CU|Cuba
CY|Cyprus
CZ|Czech Republic
CD|Democratic Republic Of Congo (Zaire)
DK|Denmark
DJ|Djibouti
DM|Dominica
DO|Dominican Republic
TP|East Timor
EC|Ecuador
EG|Egypt
SV|El Salvador
GQ|Equatorial Guinea
ER|Eritrea
EE|Estonia
ET|Ethiopia
FK|Falkland Islands (Malvinas)
FO|Faroe Islands
FJ|Fiji
FI|Finland
FR|France
FX|France, Metropolitan
GF|French Guinea
PF|French Polynesia
TF|French Southern Territories
GA|Gabon
GM|Gambia
GE|Georgia
DE|Germany
GH|Ghana
GI|Gibraltar
GR|Greece
GL|Greenland
GD|Grenada
GP|Guadeloupe
GU|Guam
GT|Guatemala
GN|Guinea
GW|Guinea-Bissau
GY|Guyana
HT|Haiti
HM|Heard And McDonald Islands
HN|Honduras
HK|Hong Kong
HU|Hungary
IS|Iceland
IN|India
ID|Indonesia
IR|Iran
IQ|Iraq
IE|Ireland
IL|Israel
IT|Italy
JM|Jamaica
JP|Japan
JO|Jordan
KZ|Kazakhstan
KE|Kenya
KI|Kiribati
KW|Kuwait
KG|Kyrgyzstan
LA|Laos
LV|Latvia
LB|Lebanon
LS|Lesotho
LR|Liberia
LY|Libya
LI|Liechtenstein
LT|Lithuania
LU|Luxembourg
MO|Macau
MK|Macedonia
MG|Madagascar
MW|Malawi
MY|Malaysia
MV|Maldives
ML|Mali
MT|Malta
MH|Marshall Islands
MQ|Martinique
MR|Mauritania
MU|Mauritius
YT|Mayotte
MX|Mexico
FM|Micronesia
MD|Moldova
MC|Monaco
MN|Mongolia
MS|Montserrat
MA|Morocco
MZ|Mozambique
MM|Myanmar (Burma)
NA|Namibia
NR|Nauru
NP|Nepal
NL|Netherlands
AN|Netherlands Antilles
NC|New Caledonia
NZ|New Zealand
NI|Nicaragua
NE|Niger
NG|Nigeria
NU|Niue
NF|Norfolk Island
KP|North Korea
MP|Northern Mariana Islands
NO|Norway
OM|Oman
PK|Pakistan
PW|Palau
PA|Panama
PG|Papua New Guinea
PY|Paraguay
PE|Peru
PH|Philippines
PN|Pitcairn
PL|Poland
PT|Portugal
PR|Puerto Rico
QA|Qatar
RE|Reunion
RO|Romania
RU|Russia
RW|Rwanda
SH|Saint Helena
KN|Saint Kitts And Nevis
LC|Saint Lucia
PM|Saint Pierre And Miquelon
VC|Saint Vincent And The Grenadines
SM|San Marino
ST|Sao Tome And Principe
SA|Saudi Arabia
SN|Senegal
SC|Seychelles
SL|Sierra Leone
SG|Singapore
SK|Slovak Republic
SI|Slovenia
SB|Solomon Islands
SO|Somalia
ZA|South Africa
GS|South Georgia And South Sandwich Islands
KR|South Korea
ES|Spain
LK|Sri Lanka
SD|Sudan
SR|Suriname
SJ|Svalbard And Jan Mayen
SZ|Swaziland
SE|Sweden
CH|Switzerland
SY|Syria
TW|Taiwan
TJ|Tajikistan
TZ|Tanzania
TH|Thailand
TG|Togo
TK|Tokelau
TO|Tonga
TT|Trinidad And Tobago
TN|Tunisia
TR|Turkey
TM|Turkmenistan
TC|Turks And Caicos Islands
TV|Tuvalu
UG|Uganda
UA|Ukraine
AE|United Arab Emirates
UK|United Kingdom
US|United States
UM|United States Minor Outlying Islands
UY|Uruguay
UZ|Uzbekistan
VU|Vanuatu
VA|Vatican City (Holy See)
VE|Venezuela
VN|Vietnam
VG|Virgin Islands (British)
VI|Virgin Islands (US)
WF|Wallis And Futuna Islands
EH|Western Sahara
WS|Western Samoa
YE|Yemen
YU|Yugoslavia
ZM|Zambia
ZW|Zimbabwe'
mattjbondi’s picture

... I agree with you mate. What happened to the days of programmers being able to freaking program!

mattjbondi’s picture

I had the same problem, in that I needed a select list associated with a particular content type to search a folder for images, and I have come up with this as a work around...

1. Create a normal select list in the Manage Fields for Content types, calling it whatever you need to.
1. Create a module with .module and .info files called whatever...
2. In the .module file use this to override the select list you have just created. You can do a print_r() on the $form variable to see which winding path through the arrays you need to take. This is where I got [field_about_images][und][#options] from...

function image_select_form_alter(&$form, &$form_state, $form_id){
	switch ($form_id) {
		case 'page_node_form':
		
			//List contents of folder. Output must be an array of array('value'=>'label');
			
			$pth = 'sites/default/files/pictures';
			$d = dir($pth);
			$i = 0;
			$images = array();
			$pattern = '/^[\._]/';
			
			
			while (false !== ($entry = $d->read())) {
				
				$fileMatch = fileCheck($pattern,$entry);
			
				if(($entry != "Thumbs.db") && ($fileMatch < 1)){
					$images[''.$pth.'/'.$entry.''] = $entry;
						
				}
			}
			
			$form['field_about_image']['und']['#options'] = $images;
		
		 break;
	
	}

}


function fileCheck($pattern,$entry){
	$i = 0;
	$i = preg_match($pattern,$entry);
	return $i;
}

Now, the only thing that needs to be added to this is set the default value to be what was saved... an easy task for later, but right now this works for me... Not sure if it will help someone.

RaceCorp’s picture

That was just what I needed.

Probably much easier ways to check, but here's a check to make sure the node exists and sets the default value.

if(isset($form['#node']->nid)) $form['field_about_image']['und']['#default_value'] = $form['#node']->field_about_image['und'][0]['value'];

Thanks again Matt.

jcook4now’s picture

This is slick Matt! Thanks. Just a note for others who might make the same mistake I did - you must leave the list of accepted values blank for this to work (or include all possible values in the list). When there are values in that list, Drupal does a check to make sure the selected value is in the list. . .

Jeff

tyfoo’s picture

Hello!

I did something like this but my problem now lies in the fact that none of the programmatically generated options match the list of "allowed values" for that select list! I tried replacing the allowed values in the $form_state array, but to no avail.

Any ideas?

mikeker’s picture

Just so that no one else is confused by all the gnashing of teeth, the >above post is wrong.

If you have a relatively static list you want to put in a field, use the method described by WorldFallz in the first reply. You can edit this list as much as you like as long as you don't change the keys used in the database (the part before the '|') so that your existing data isn't invalidated. If you need to add a new country with a new country code, just add it to the list. If you want to change the display name (eg: United States -> USA), then edit the part after the '|' for that line.

Just "deal with it" is not how it works.

If you have data that changes regularly (eg: based on the current date) and need to add php code to the allowed values list, then you need the CCK module -- this functionality didn't make it into core for D7. Download and enabled the module (sorry, only -dev release as of this writing, but I haven't had any problem with it) and make sure the CCK -> Use PHP input for field settings permission is set correctly.

- Mike

SanderMander’s picture

I found this in list field settings form:

$form['allowed_values_function'] = array(
    '#type' => 'value',
    '#value' => $settings['allowed_values_function'],
  );

In this case $settings['allowed_values_function'] will be always empty or may contain some function if you will use hook_field_info_alter and set this value. But then all list fields would use functions. Better to alter settings form and change allowed_values_function form field type to something more dynamic than '#value' type:

function module_name_form_alter(&$form,&$form_state,$form_id){
  if($form_id == 'field_ui_field_settings_form'){
    $form['field']['settings']['allowed_values_function'] = array(
        '#type' => 'textfield',
        '#title' => t('Allowed value function'),
        '#default_value' => $form['field']['settings']['allowed_values']['#field']['allowed_values_function']
      );
  }
}

Then you may set name of function which should return array of values per each new field. Example function may look like this:

function module_name_list_text_allowed_values($field){
  if($field['field_name'] == 'field_facility'){
    return array('first','second','third');
  }
}
Alan D.’s picture

Aside from the countries listing, where I would use the countries module, this code can be wrapped into a nice small module to provide a UI. I will have a look at the webform module tonight to see how this pulls in the option function callbacks and wrap this into a sandbox project.

Core functionality:

/**
 * Implements hook_permission().
 */
function lavf_permission() {
  return array(
    'administer lavf' => array(
      'title' => t('Alter Field List Allowed Values Function'),
      'description' => t('This give field administrators access to alter the options list source for fields.'),
    ),
  );
}
function lavf_form_field_ui_field_settings_form_alter(&$form, &$form_state){
  lavf_form_field_ui_field_edit_form_alter($form, $form_state);
}
function lavf_form_field_ui_field_edit_form_alter(&$form, &$form_state) {
  if (user_access('administer lavf')) {
    $form['field']['settings']['allowed_values_function'] = array(
      '#type' => 'select',
      '#title' => t('Allowed value function'),
      '#default_value' => $form['field']['settings']['allowed_values_function']['#value'],
      '#options' => lavf_allowed_functions_callbacks(),
      '#empty_value' => '',
      '#empty_option' => t('Allowed values list'),
    );
  }
}

function lavf_allowed_functions_callbacks() {
  $options = array(
    'node_type_get_names' => t('Node content types'),
  );
  return $options;
}

Alan Davison
Alan D.’s picture

See http://drupal.org/sandbox/aland/1615516 or http://drupalcode.org/sandbox/aland/1615516.git

And deleted

http://drupal.org/project/list_predefined_options - List field predefined options

This should resolve any of you custom code defined field list requirements.


Alan Davison
Alan D.’s picture

Maintaining lists like this is a nightmare, try the countries module, a cck-like country list out of the box and fully up to date in relation to the ISO standard (core list is outdated now), and a UI to allow you to easily overwrite any country name globally, or even to disable them globally. Per field you get continent and country filters too.


Alan Davison
geertvd’s picture

I got the allowed_values_function to work when I created my field through code.

So I just added an update_hook to my .install file, and added the field like this:

/**
 * Add allowed values funtion
 */
function my_project_update_7001() {
  $field_name = 'field_list';
  $entity_type = 'node';
  $bundle = 'article';
  $label = 'Test list';
  $weight = 0;
  $allowed_values_function = 'my_project_get_values';
  
  // Look for or add the specified status field to the requested entity bundle.
  $field = field_info_field($field_name);
  $instance = field_info_instance($entity_type, $field_name, $bundle);

  if (empty($field)) {
    $field = array(
      'field_name' => $field_name,
      'type' => 'list_text',
      'cardinality' => 1,
      'entity_types' => array($entity_type),
      'translatable' => FALSE,
      'locked' => FALSE,
      'settings' => array(
        'allowed_values_function' => $allowed_values_function,
      ),
    );
    $field = field_create_field($field);
  }

  if (empty($instance)) {
    $instance = array(
      'field_name' => $field_name,
      'entity_type' => $entity_type,
      'bundle' => $bundle,

      'label' => $label,
      'required' => TRUE,
      'settings' => array(),

      'widget' => array(
        'type' => 'options_select',
        'weight' => $weight,
      ),

      'display' => array(),
    );

    field_create_instance($instance);
  }
}

function my_project_get_values() {
  return array(
    'value1',
    'value2',
    'value3',
  );
}

Then just run update.php and your field should be there.

rsvelko’s picture

this guy solved it via raw sql manipulation - I think I might be able to black-box it a bit more...

http://drupal.org/node/1856318#comment-6811872

Alan D.’s picture

http://drupal.org/project/list_predefined_options

This should resolve any of you custom code defined field list requirements. I deleted my sandbox for this after finding this!


Alan Davison
donpwinston’s picture

From reading this post and related comments it is still not clear what the problem is.

Here it is:

Install the cck module. This has a tiny bit of code that for the reasons below is not in the core.

Make sure the permissions is set so it becomes available to an administrator (usually is by default).

go to "manage fields" for a content type the desired field is used and edit it.

go to the bottom and change the "Allowed Values Function" (cck_allowed_values_php) to your custom function that returns the proper array/value. In my case I used _bnc_reports_district_list(). this should be defined in a module somewhere.

Save it and this field will use your function. I'm getting my list from a database. But if the database is changed the allowed values will not change!.

How in the world is this useful?

(Also, if the field is used by more then one content type then this change will affect all of them)

SOLUTION: use hook_form_alter!

if (isset($form['field_district'])) {
    $form['field_district']['und']['#options'] = array('_none' => '- None -') +
			_bnc_reports_district_list();

Simpler is always better.

Alan D.’s picture

I'd still recommend http://drupal.org/project/list_predefined_options for Drupal 7, the list is generated with the widget. ;)


Alan Davison
hellolindsay’s picture

The goal: set custom list of options for a List field using PHP code only from a custom module. The list options can be static (like the list of countries) or dynamic (like a list of names). I wanted to be able to do this with hook_form_alter() only, without using a downloaded module, and I eventually figured out how. In order for this to work, the "Allowed values list" for your List field must be empty.

The hook_form_alter() code has two parts: First, you set the available list options; and then, second, you manually set which list options are selected/checked using data saved in the node. You might have assumed that Drupal would take care of the second part for you but, for Drupal 7 at least, it does not. Drupal 7 will save custom list options to the node, but it does not automatically select/check them in the form.

Here is the code:

// this is the function that returns your list options
function mymodule_get_list_options() {
	return array(
		'john'=>'John',
		'paul'=>'Paul',
		'george'=>'George',
		'ringo'=>'Ringo'
	);
}
// this is hook_form_alter
function mymodule_form_alter(&$form,$form_state,$form_id) {
	// if the list field exists for this form, alter it
	if (!empty($form['field_mylist'])) {
		// set the allowed options for the list field
		$options = mymodule_get_list_options(); // returns array of key/value pairs
		$form['field_mylist']['und']['#options'] = $options;
		// if the saved node contains saved list options, select/check them
		if (!empty($form['#node']->field_mylist['und'])) {
			$saved = $form['#node']->field_mylist['und'];
			foreach($saved as $delta=>$option) {
				$form['field_mylist']['und']['#default_value'][$delta] = $option['value']; // select/check
			}
		}
	}
}
TravisJohnston’s picture

I used your code and I was able to set the allowed values, thank you. Though I need it to go a step further and set the list of allowed values based on the value selected in another field.

Goal:
1) Select the District you belong to
2) Then based on the District you chose, choose a School available in that District

Code I am using but its not working. The numbers being used in the case are the value keys of the districts.

function ces_custom_get_list_options() {
	$field = field_info_field('field_member_districts');
	$allowed_values = list_allowed_values($field);
	switch ($allowed_values) {
		case "4450000":
			return array(
				'none'=>'None',
				'john'=>'John',
				'paul'=>'Paul',
				'george'=>'George',
				'ringo'=>'Ringo'
			);
			break;
		case "Abington":
			return array(
				'none'=>'None',
				'school1'=>'Rowe Elementary',
				'school2'=>'Shelburne Falls',
				'school3'=>'Buckland School',
				'school4'=>'Greenfield School'
			);
			break;
	}
}
// this is hook_form_alter
function ces_custom_form_alter(&$form,$form_state,$form_id) {
    // if the list field exists for this form, alter it
    if (!empty($form['field_member_schools'])) {
        // set the allowed options for the list field
        $options = ces_custom_get_list_options(); // returns array of key/value pairs
        $form['field_member_schools']['und']['#options'] = $options;
        // if the saved node contains saved list options, select/check them
        if (!empty($form['#node']->field_member_schools['und'])) {
            $saved = $form['#node']->field_member_schools['und'];
            foreach($saved as $delta=>$option) {
                $form['field_member_schools']['und']['#default_value'][$delta] = $option['value']; // select/check
            }
        }
    }
}

Thank you kindly,

Travis Johnston

Creo Coding - Let's Start Our Journey!
Owner and Web Developer
http://www.creocoding.com

Facebook - Facebook.com/CreoCoding
LinkedIn - http://lnkd.in/rQrdS7

Sagar Ramgade’s picture

Hi,

We can add allowed values function by using field_update_field in hook_update_N in your modules .install file, please find the example below :


<?php
$country_field = field_info_field('field_country'); //field_country is field machine name
unset($country_field['settings']['allowed_values']);
$country_field['settings']['allowed_values_function'] = 'yourmodulename_get_all_countries';
field_update_field($country_field);
?>

In the code above yourmodulename_get_all_countries should return an array of key and values of countries.

Regards
Sagar

Acquia certified Developer, Back end and Front specialist
Need help? Please use my contact form

purabdk’s picture

I used above code in my modulename.install file and executed the update.php file. It worked like charm.

Thanks for code.

purabdk’s picture

I used the above code in my mymodule.install file. It is working like charm.

Thanks for code.

patpluspun’s picture

If you use the Features module (using api 2), you can modify the [module_name].features.field_base.inc file to add a custom callback you define in your module:

'settings' => array(
  'allowed_values' => array(),
  'allowed_values_function' => 'module_name_custom_callback',
),
'translatable' => 0,
'type' => 'list_text',

Then it works pretty much by default like any other list field. I haven't tested it with super dynamic data, I would follow the advice given above though.

rajesh.vishwakarma’s picture

I have found one of best way to this:
Add hook_form_FORM_ID_alter to alter value for list box.

<?php
function mymodule_form_FORM_ID_alter(&$form, &$form_state)  {
     // get default status for field using machine name of field
    $default_stats_field = field_info_field('field_machine_name');
    // unset the allowed values
    unset($default_stats_field['settings']['allowed_values']); 
    // function name that provides array of values
    $default_stats_field['settings']['allowed_values_function'] = '_custom_api_state_list'; 
    // update value with new value.
    field_update_field($default_stats_field);
}
?>

Sagar Ramgade’s picture

That's the wrong way to do it, Every time the form loads it will update the filed which is wrong, you need to use https://api.drupal.org/api/drupal/modules%21system%21system.api.php/func... instead of hook_form_alter.

Acquia certified Developer, Back end and Front specialist
Need help? Please use my contact form

rajesh.vishwakarma’s picture

@Sagar Ramgade Yes it is correct form loads on every time but I am not able to find any ways to do this using hook_update_N. Kindly explain with an example.

Sagar Ramgade’s picture

In you custom module's .install file, you need to define the function below :

<?php
//Change the function name to your module name
function custom_module_update_7001() {
     // get default status for field using machine name of field
    $default_stats_field = field_info_field('field_machine_name');
    // unset the allowed values
    unset($default_stats_field['settings']['allowed_values']); 
    // function name that provides array of values
    $default_stats_field['settings']['allowed_values_function'] = '_custom_api_state_list'; 
    // update value with new value.
    field_update_field($default_stats_field);
}

Once you add the above code to the .install file, run yoursite.com/update.php using super user login.

Acquia certified Developer, Back end and Front specialist
Need help? Please use my contact form