4

I have a D8 site on which I would like to require an image field to be completed only when a node is published; if the publish box is not checked, the field should not be required. I was able to do this with a custom module in D7, but since D8 has decoupled entity validation from form validation, I'm at a loss.

I've tried doing this with the Rules module, with no luck.

3

Simply add a validation on the entity level, then you have easy access to the whole entity.

You can see an example in content_translation_entity_type_alter():

$entity_type->addConstraint('ContentTranslationSynchronizedFields');

You register a constraint like any plugin, the only special thing is that there are two classes, the plugin class itself doesn't really have anything except the messages usually while the validator has the logic, in the validate method::

ContentTranslationSynchronizedFieldsConstraint ContentTranslationSynchronizedFieldsConstraintValidator::validate

Once you have that, writing the actual logic is often much easier, because you have a fully built entity object to work with and don't have to wory about getting the raw values from the form values. And as a bonus, it will also automatically work for REST/json_api and any other module that uses the validate() method to ensure that created entities are valid before saving them.

For example, verifying that an image field is not empty when the entity is published:

if ($entity->isPublished() && $entity->hasField('field_image') && $entity->get('field_image')->isEmpty()) {
  // add a violation...
}
0

You can do that by adding custom validation for the form

function custom_form_node_form_alter(&$form, FormStateInterface $form_state) {
  $form['#validate'][] = 'mycustom_node_form_validate';
}

Then you need to implement your custom validator:

function mycustom_node_form_validate($form, FormStateInterface $form_state) {
  $node = $form_state->getFormObject()->getEntity();

  if ($node->getType() == 'node_type') {
    // Get status and image values.
    $status = $form_state->getValue('status');
    $image_field = $form_state->getValue('field_my_image_field');
    // Check if image is empty and status is published.
    if (empty($image_field['fids']) && $status['value']) {
      $form_state->setErrorByName('field_my_image_field', t('Image missing.'));
    }
  }
}

Another way to accomplish that can be by using Conditional Fields This is a really great module which let you control the visibility of the fields based on values of another field.

Just enable it and under the content type operations, you can find Dependencies option where you can map the dependency.

0

I know this question was answered, but if anybody else is looking for a less custom solution I wrote a module that adds this functionality: https://www.drupal.org/project/require_on_publish.

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.