4

I have a select box named field_ee_project . I want to add the select box options dynamically on hook_form_alter .

What i have tried


    function gamodule_form_alter(&$form, FormStateInterface $form_state, $form_id) {
       //check whether the form is effort estimation
        if($form_id = 'node_effordestimation_form'){
            $form['field_ee_project']['und']['#options'] = effort_estimation_project_autoload();
        }
     }

    /*
     * Effort estimation project field select box
     */
    function effort_estimation_project_autoload(){
            $matches = array();
            $result = db_query("SELECT ga_id,name FROM ga_projects");
            $row = $result->fetchAll();
            $row = json_decode(json_encode($row), True);
            foreach ($row as $key => $value) {
                $matches[$value['name']] = $value['name'];
             }
            return $matches;
    }

But it is not working . Any idea ?

  • foreach ($row as $key => $value) { $matches[$key] = $value['name']; } Try this – Shreya Shetty Mar 7 '17 at 11:06
  • did you print $matches if yes what is the output – Shreya Shetty Mar 7 '17 at 11:16
  • 1
    What's the purpose of the json_encode() and json_decode()? – Jaypan Mar 7 '17 at 11:21
  • @Jaypan need to convert to an arry from object ,Actually this wont need i think – Crazyrubixfan Mar 7 '17 at 11:26
  • And what do you mean by 'not working'? What is happening? And finally, you're selecting two values in your query, ga_id and name. Is ga_id the key, and name the human-readable value? – Jaypan Mar 7 '17 at 11:27
2

Try this it should work.

 function gamodule_form_alter(&$form, FormStateInterface $form_state, $form_id) {
   //check whether the form is effort estimation
    if($form_id = 'node_effordestimation_form'){
        $form['field_ee_project']['widget']['#options']  = effort_estimation_project_autoload();
    }
 }

function effort_estimation_project_autoload(){
                $matches = array();
                $result = db_query("SELECT ga_id,name FROM ga_projects");
                $row = $result->fetchAll();
                $row = json_decode(json_encode($row), True);
                foreach ($row as $key => $value) {
                    $matches[$key] = $value['name'];
                 }
                return $matches;
        }
  • Unfortunately not working – Crazyrubixfan Mar 7 '17 at 11:15
  • updated my answer – Shreya Shetty Mar 7 '17 at 11:20
  • There is a problem when saving this value . As my field is a content type field and its matching the values against 'allowed values' of that field . Else it throws an error as ''The value you selected is not a valid choice" . – Crazyrubixfan Mar 7 '17 at 13:26
  • 1
    Yep, this isn't going to work in Drupal 8 with the way that Field Types have been decoupled from Field Widgets. This was possible with Drupal 7, but the move to API First and Headless requires list fields to be strict about validation. See drupal.org/node/2643308. This, in my opinion as I noted in the issue, was a regression, and the alternatives I outlined have their own drawbacks. However for options_allowed_values in that issue you could probably work around that if the select_or_other bug was fixed. Edit: I'll write up an answer with those details. – mradcliffe Mar 7 '17 at 14:16
  • I also forgot about callback_allowed_values_callback which could be set on the field. – mradcliffe Mar 7 '17 at 14:48
4

The Field Type API are more strict in Drupal 8 so that Web Services and Forms follow the same validation path. This is not always the behavior that we want.

Looking at your question again, I think that using an allowed values callback on the field would work as well.

I provided some alternatives based on the restrictions that core places on list fields below #1 as well in case the following doesn't work as intended. These could be useful for other people doing similar things.

#1: Try to use allowed values callback for the field instead

Set an allowed_values_callback for the list field.

function gamodule_allowed_values_callback(FieldStorageDefinitionInterface $definition, FieldableEntityInterface $entity = NULL, &$cacheable = TRUE) {
  // @todo make this a bit more conditional based on the parameters above.
  $result = db_query("SELECT ga_id,name FROM ga_projects");
  $row = $result->fetchAll();
  $row = json_decode(json_encode($row), True);
  foreach ($row as $key => $value) {
    $matches[$key] = $value['name'];
  }
  return $matches;
}

Note that the documentation for callback_allowed_values_callback mentions using opt groups, but this functionality has a bug and is broken in 8.

#2: Migrate list field to text field

Make a Select list Field Widget for text fields. Migrate your data over.

Risks
  • A lot of work to re-architect.
  • May confuse a development team inheriting the site.

#3: Override the AllowedValues constraint plugin

Use hook_validation_constraint_alter to provide your own Constraint plugin (see Symfony 2 Constraint documentation).

Risks
  • Site is incompatible with a couple of contrib modules doing the same thing (select_or_other, cck_select_other).

#4: Make sure all possible allowed values are in the list field

Don't use a custom table to store allowed values. Set the allowed values in list field configuration. Write a field widget plugin.

Write your own Field Widget that restricts options based on some other parameter like your query.

#5: Override Core handling of list field plugins with your own implementation

Use hook_field_info_alter to not use Core code at all. Write your own List Field Type plugin with a better Options or Allowed Values implementation.

Risks
  • May confuse a development team inheriting the site.
  • All list fields now behave this way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.