This is probably not the way to address media fields states, however it is a solution (or work around I was able to come up with).
Using hook_form_alter() the same hook I'm using to work with the media fields as conditional fields - I added a new field (input type radios) to the form to use as the controller which dictates the media fields visibility, disabled and required #states for media fields using the media library widget. That in combination with a little jquery magic and css got the job done effectively.
Here is exactly what I did (in hook_form_alter) I created and added the radios field to the forms I'm working with which will be css display none:
$form['field_media_set'] = [
'#type' => 'radios',
'#options' => [
'upload' => 'Video Upload',
'link' => 'Linked Video',
'gallery' => 'Gallery Images',
'other' => 'No Media',
],
'#atributes' => [
'name' => 'field_media_set',
],
'#default_value' => 'other',
'#weight' => 12,
];
I Didn't bother with any data storage for the field as it is just being used to control the 3 media fields using the media library widget in form display (video upload, linked video, and gallery images "which is actually 2 media fields, one for a main/poster image and the other to add up to 12 additional supporting images)
Next I created a new library and added it to the libraries.yml calling it post-library and listed a post.css and post.js file in the library like this:
post-library:
version: 1.x
js:
js/post.js: {}
dependencies:
- core/jquery
css:
theme:
css/post.css: {}
In the post.css file I added:
div#edit-field-media-set.form-radios {display: none;}
In the post.js I added:
function checkMediaFields() {
var $uploadVideo = $('input[name="field_upload_video[selection][0][target_id]"]');
var $linkVideo = $('input[name="field_link_video[selection][0][target_id]"]');
var $gallery = $('input[name="field_gallery_poster_image[selection][0][target_id]"]');
var $galImages = $('input[name="field_gallery_images[selection][0][target_id]"]');
if ($uploadVideo.length || $linkVideo.length || $gallery.length || $galImages.length) {
if ($uploadVideo.length) {
$('input[name="field_media_set"][value="upload"]').prop('checked', true).change();
}
if ($linkVideo.length) {
$('input[name="field_media_set"][value="link"]').prop('checked', true).change();
}
if ($gallery.length || $galImages.length) {
$('input[name="field_media_set"][value="gallery"]').prop('checked', true).change();
}
} else {
$('input[name="field_media_set"][value="other"]').prop('checked', true).change();
}
}
$(document).ajaxComplete(function() {
checkMediaFields();
});
As you can see from the js/jQuery there are 4 inputs (what's important to note here is those are the inputs that get added to the form once a media item has been added through the media library widget - "If no media is added those inputs DO NOT EXIST", and that is why those alone cannot be used as the control condition because if you remove the added media those inputs also get removed from the form.
Also note in the js/jQuery the use of "ajaxComplete" function, this is required to trigger the checkMediaFields functions which you can see checks for the existence of the inputs that get added to the form when media is added with a media field. Having that run after ajax completes is key because the media library form display widgets use ajax to upload or add the media in question to the form, without that the function to check for any media related inputs won't get triggered when a media field using media library widget adds new media to the form.
Next in the node-add and node-edit twig templates (example: page--node--add--contenttype-post.html.twig) I added the library I created above:
{{ attach_library('custom_module_name/post-library') }}
Now back in hook_form_alter() here is how I set up the conditional states for the media fields:
$form['field_upload_video']['#states'] = [
'visible' => [
[
'input[name="field_media_set"]' => ['value' => 'other'],
],
'or',
[
'input[name="field_media_set"]' => ['value' => 'upload'],
],
],
'disabled' => [
[
'input[name="field_media_set"]' => ['value' => 'link'],
],
'or',
[
'input[name="field_media_set"]' => ['value' => 'gallery'],
],
],
];
$form['field_link_video']['#states'] = [
'visible' => [
[
'input[name="field_media_set"]' => ['value' => 'other'],
],
'or',
[
'input[name="field_media_set"]' => ['value' => 'link'],
],
],
'disabled' => [
[
'input[name="field_media_set"]' => ['value' => 'upload'],
],
'or',
[
'input[name="field_media_set"]' => ['value' => 'gallery'],
],
],
];
$form['field_gallery_poster_image']['#states'] = [
'visible' => [
[
'input[name="field_media_set"]' => ['value' => 'other'],
],
'or',
[
'input[name="field_media_set"]' => ['value' => 'gallery'],
],
],
'required' => [
[
'input[name="field_media_set"]' => ['value' => 'gallery'],
],
],
'disabled' => [
[
'input[name="field_media_set"]' => ['value' => 'upload'],
],
'or',
[
'input[name="field_media_set"]' => ['value' => 'link'],
],
],
];
$form['field_gallery_images']['#states'] = [
'visible' => [
[
'input[name="field_media_set"]' => ['value' => 'other'],
],
'or',
[
'input[name="field_media_set"]' => ['value' => 'gallery'],
],
],
'required' => [
[
'input[name="field_media_set"]' => ['value' => 'gallery'],
],
],
'disabled' => [
[
'input[name="field_media_set"]' => ['value' => 'upload'],
],
'or',
[
'input[name="field_media_set"]' => ['value' => 'link'],
],
],
];
All of that combined "gets the job done!"
Things worth mentioning:
Before using the created radios field "field_media_set" I tried a few other field types to use as the controller like a dropdown select field and a set of number input fields (which were intended to be used like the radios field - however those alternate form fields would only work once. What I mean by that is even tho the jQuery would update the fields in the event a previously added media element was "removed" the hidden media fields would not show again. Even when using .change() or .keyup()
when jQuery made any changes to the controlling fields. For whatever reason only radio checkboxes works 100% of the time for this type of scenario.
There may be a better way (but with the limited documentation concerning the use of media fields using the media library widget as a conditional controller) this is what I came up with.
Hopefully this will help others in a similar situation.