I presume you've fixed this already but (in a blatant attempt to snaffle the bounty and) as mentioned in the comments there's a simple fix, in your myplugin_meta_box_callback() function change the line
$mime_types = array( 'application/pdf' );
to
$mime_types = 'application/pdf';
The library.type option to wp.media expects a string (which can be comma-separated with additional types) not an array.
This actually threw up a bug in the media.model.Attachments because if you look at where it was failing, the validator type() filter (line 997 in "media-models.js")
type: function( attachment ) { var type = this.props.get('type'); return ! type || -1 !== type.indexOf( attachment.get('type') ); },
then what this isn't taking account of is that an attachment type like application/pdf is split into type and subtype by wp_prepare_attachment_for_js() in "media.php", and this is only validating type, ie application (and validating in a pretty sloppy way too with no delimiters).
Anyway all that's moot if you add the upload validator given by @Bainternet - here's a variation of it:
add_action( 'admin_init', function () { add_filter( 'wp_handle_upload_prefilter', function ( $file ) { if ( empty( $_POST['allowed_mime_types'] ) || empty( $file['type'] ) ) { return $file; } $allowed_mime_types = explode( ',', $_POST['allowed_mime_types'] ); if ( in_array( $file['type'], $allowed_mime_types ) ) { return $file; } // Cater for "group" allowed mime types eg "image", "audio" etc. to match // files of type "image/png", "audio/mp3" etc. if ( ( $slash_pos = strpos( $file['type'], '/' ) ) > 0 ) { if ( in_array( substr( $file['type'], 0, $slash_pos ), $allowed_mime_types ) ) { return $file; } } $file['error'] = __( 'Sorry, you cannot upload this file type for this field.' ); return $file; } ); add_filter( 'media_view_settings', function ( $settings, $post ) { $settings['mimeTypes']['application/pdf'] = __( 'All PDF items' ); return $settings; }, 10, 2 ); } );
(The additional media_view_settings filter just changes the select filter text from "All media items" to "All PDF items".) You can then set the allowed_mime_types param (in the new way mentioned by @estepix) in your openModal() function directly after calling wp.media()
this.modal = wp.media.frames.file_frame = wp.media(options); if (options.library && options.library.type && this.modal.uploader) { this.modal.uploader.options.uploader.params.allowed_mime_types = options.library.type; }
and non-PDF files won't be allowed to be uploaded.