Answers.Body: <p>Make the field required all the time. Add another choice to the radio called "Not Required". In your validate hook check if the contact subtype is AA and if they chose Not Required set the $errors variable on your radio field to show your error. Since you made it a required field it will be in the fields array.</p>
  
  <p>For inline edit the formName is CRM_Contact_Form_Inline_CustomData and you will need to look up the contact subtype using the api, e.g. civicrm_api3('Contact', 'get'...). Use the contact id from $fields['cid']. (Go to /civicrm/api in your browser - it's very handy for getting the api syntax correct.)</p>
  
  <p>Also note your custom field in edit mode will have a different name. It won't be custom_70-1 it will be custom_70-3838 or something like that, so you'll need to either look it up from $form first (e.g. in the groupTree element) or do something like loop through the $fields keys and compare substr($key, 0, 9) == 'custom_70'.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-02-20T15:12:06.227Z
Answers.Text: thank you for tips. Finally I found a workaround in civicrm-core
Answers.UserDisplayName: Scardinius
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-02-20T15:16:30.400Z
Answers.Text: "Not Required" choice is not an option to me. I can't modify data structure.
Answers.UserDisplayName: Scardinius
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-02-20T15:29:35.657Z
Answers.Text: Huh? You can not add an option value to your option group? That is weird :-) And certainly not a reason to change core code IMO
Answers.UserDisplayName: ErikH - CiviCooP
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-02-20T13:11:33.053Z
Answers.LastActivityDate: 2019-02-20T13:11:33.053Z
Answers.UserDisplayName: Demerit
Body: <p>I have a custom field on contact in radio type format, not required field. I'd like to set up custom error on this field by using <code>hook_civicrm_validateForm</code> when the field is null.</p>
  
  <pre><code>// hook in extension
  function hook_civicrm_validateForm($formName, &amp;$fields, &amp;$files, &amp;$form, &amp;$errors) {}
  </code></pre>
  
  <p><code>$fields</code> array doesn't contain a key for this custom field. After setting <code>$error['custom_xx']</code> the form is reloaded without displaying the error.</p>
  
  <p>What I found:</p>
  
  <p><code>$form-&gt;_elementIndex</code> contains all needed keys, including this for radio. So I suppose this is not a problem.</p>
  
  <p>I think that problem is caused by using <code>_submitValues[]</code> as a list of fields because _submitValues doesn't contain null radio custom fields:</p>
  
  
  
  <pre><code>// CRM_Core_Form-&gt;validate():
  CRM_Utils_Hook::validateForm(
    get_class($this),
    $this-&gt;_submitValues,
    $this-&gt;_submitFiles,
    $this,
    $hookErrors
  );
  
  // my hook
  function example_civicrm_validateForm($formName, &amp;$fields, &amp;$files, &amp;$form, &amp;$errors) {
    if ($formName == 'CRM_Contact_Form_Contact') {
      if (in_array('AA', $fields['contact_sub_type'])) {
        $fieldIndex = 'custom_70-1';
        if (!in_array($fieldIndex, array_keys($fields)) || !$fields[$fieldIndex]) {
          $errors[$fieldIndex] = 'For AA contact type this field is required';
        }
      }
    }
  }
  </code></pre>
  
  <p><strong>Edit:</strong></p>
  
  <p>Here is my workaround - add missing keys to _submitValues[] array
  <a href="https://github.com/caltha-eu/civicrm-core/commit/b4ee607334f3f091bffc2c32a87d862e4a3d7493" rel="nofollow noreferrer">https://github.com/caltha-eu/civicrm-core/commit/b4ee607334f3f091bffc2c32a87d862e4a3d7493</a></p>
  
  <pre><code>foreach ($this-&gt;_elementIndex as $elementIndex =&gt; $index) {
    if (!in_array($elementIndex, array_keys($this-&gt;_submitValues))) {
      $this-&gt;_submitValues[$elementIndex] = NULL;
    }
  }
  </code></pre>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-02-19T15:24:01.187Z
Comments.Text: If I understand this correctly you do get a value in fields if the radio is checked? So if it is not required, what are you actually checking?
Comments.UserDisplayName: ErikH - CiviCooP
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-02-19T15:30:34.470Z
Comments.Text: This field is not required in general but in some cases (like one of contact type AA) it is required. I checked contact type and I'd like to set error when this is my AA type.
Comments.UserDisplayName: Scardinius
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-02-19T15:39:27.087Z
Comments.Text: I added code of my hook.
Comments.UserDisplayName: Scardinius
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-02-19T16:23:17.240Z
Comments.Text: A workaround, which is not ideal but should work, is just use a different field name in the $errors array, one that does exist. It will visually hilite the wrong field, but your wording will say the right thing. Use contact_sub_type for example, since then the context here will still make sense.
Comments.UserDisplayName: Demerit
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-02-19T16:30:46.567Z
Comments.Text: Thanks @Demerit, it could be useful. I'll try this workaround.
Comments.UserDisplayName: Scardinius
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-02-19T18:36:29.383Z
Comments.Text: Another workaround is to make the field required all the time, but have one of the radio choices' text be "Not Required".
Comments.UserDisplayName: Demerit
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-02-20T11:06:29.940Z
Comments.Text: @Demerit the first workaround works for editing whole contact, I mean "CRM_Contact_Form_Contact". It doesn't work for editing custom fields inline "CRM_Contact_Form_Inline_CustomData". On inline mode I don't have contact_sub_type field :[   It's necessary to find workaround to previous workaround :D
Comments.UserDisplayName: Scardinius
Tags: <custom-fields><hooks>
Title: Validation radio custom fields on civicrm_validateForm hook does not work
ThreadText: # Validation radio custom fields on civicrm_validateForm hook does not work
  
  (Asked by: username_0 on 2019-02-19)
  
  I have a custom field on contact in radio type format, not required field. I'd like to set up custom error on this field by using hook_civicrm_validateForm when the field is null.
  // hook in extension
  function hook_civicrm_validateForm($formName, &$fields, &$files, &$form, &$errors) {}
  
  $fields array doesn't contain a key for this custom field. After setting $error['custom_xx'] the form is reloaded without displaying the error.
  What I found:
  $form->_elementIndex contains all needed keys, including this for radio. So I suppose this is not a problem.
  I think that problem is caused by using _submitValues[] as a list of fields because _submitValues doesn't contain null radio custom fields:
  // CRM_Core_Form->validate():
  CRM_Utils_Hook::validateForm(
    get_class($this),
    $this->_submitValues,
    $this->_submitFiles,
    $this,
    $hookErrors
  );
  
  // my hook
  function example_civicrm_validateForm($formName, &$fields, &$files, &$form, &$errors) {
    if ($formName == 'CRM_Contact_Form_Contact') {
      if (in_array('AA', $fields['contact_sub_type'])) {
        $fieldIndex = 'custom_70-1';
        if (!in_array($fieldIndex, array_keys($fields)) || !$fields[$fieldIndex]) {
          $errors[$fieldIndex] = 'For AA contact type this field is required';
        }
      }
    }
  }
  
  Edit:
  Here is my workaround - add missing keys to _submitValues[] array
  https://github.com/caltha-eu/civicrm-core/commit/b4ee607334f3f091bffc2c32a87d862e4a3d7493
  foreach ($this->_elementIndex as $elementIndex => $index) {
    if (!in_array($elementIndex, array_keys($this->_submitValues))) {
      $this->_submitValues[$elementIndex] = NULL;
    }
  }
  
  **Tags:** custom-fields, hooks
  
  > **Comments:**
  > **username_1**: If I understand this correctly you do get a value in fields if the radio is checked? So if it is not required, what are you actually checking?  
  > **username_0**: This field is not required in general but in some cases (like one of contact type AA) it is required. I checked contact type and I'd like to set error when this is my AA type.  
  > **username_0**: I added code of my hook.  
  > **username_2**: A workaround, which is not ideal but should work, is just use a different field name in the $errors array, one that does exist. It will visually hilite the wrong field, but your wording will say the right thing. Use contact_sub_type for example, since then the context here will still make sense.  
  > **username_0**: Thanks @username_2, it could be useful. I'll try this workaround.  
  > **username_2**: Another workaround is to make the field required all the time, but have one of the radio choices' text be "Not Required".  
  > **username_0**: @username_2 the first workaround works for editing whole contact, I mean "CRM_Contact_Form_Contact". It doesn't work for editing custom fields inline "CRM_Contact_Form_Inline_CustomData". On inline mode I don't have contact_sub_type field :[   It's necessary to find workaround to previous workaround :D  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_2 on 2019-02-20. Score: 1
  
  Make the field required all the time. Add another choice to the radio called "Not Required". In your validate hook check if the contact subtype is AA and if they chose Not Required set the $errors variable on your radio field to show your error. Since you made it a required field it will be in the fields array.
  
  For inline edit the formName is CRM\_Contact\_Form\_Inline\_CustomData and you will need to look up the contact subtype using the api, e.g. civicrm\_api3('Contact', 'get'...). Use the contact id from $fields['cid']. (Go to /civicrm/api in your browser - it's very handy for getting the api syntax correct.)
  
  Also note your custom field in edit mode will have a different name. It won't be custom\_70-1 it will be custom\_70-3838 or something like that, so you'll need to either look it up from $form first (e.g. in the groupTree element) or do something like loop through the $fields keys and compare substr($key, 0, 9) == 'custom\_70'.
  
  > **Comments:**
  > **username_0**: thank you for tips. Finally I found a workaround in civicrm-core  
  > **username_0**: "Not Required" choice is not an option to me. I can't modify data structure.  
  > **username_1**: Huh? You can not add an option value to your option group? That is weird :-) And certainly not a reason to change core code IMO  
  
  ---
  
  