I had the same error because I forgot to add:
wp_enqueue_media();
Then I found this how to and solved the problem like this:
1: You have to enqueue WP JavaScript library for media and your own JS file:
public function enqueue_scripts() {
//WP library
wp_enqueue_media();
//Your JS file
wp_register_script(\'name-of-your-script\', plugin_dir_url( __FILE__ ) . \'js/path-to-your.js\', array( \'jquery\'), $this->version, true);
wp_enqueue_script($this->plugin_name);
}
add_action(\'admin_enqueue_scripts\', \'enqueue_scripts\');
2: Create html for the form parts
<input class="img-01" type="text" name="img-01" size="100" />
<input type="button" class="button wk-button" data="img-01" value="<?php _e(\'Select image\', \'your-text-domain\');?>" />
<div><img src="" class="img-01"/></div>
3: Add code to your JS file (js/path-to-your.js)
jQuery(function ($) {
$(document).ready(function () {
$(".wk-button").click(function (e) {
var wkMedia;
// Using dynamic selector is useful if you want to use media selection/upload more then once within a single page (this value is populated from data attribute of the button
var selector = $(this).attr("data");
// Title is populated from value of the button to make it ready for localization
var title = $(this).attr("value");
e.preventDefault();
// If the upload object has already been created, reopen the dialog
if (wkMedia) {
wkMedia.open();
return;
}
// Extend the wp.media object
wkMedia = wp.media.frames.file_frame = wp.media({
title: title,
button: {
text: title,
},
multiple: false,
});
// When a file is selected, grab the URL and set it as the text field\'s value
wkMedia.on("select", function () {
var attachment = wkMedia.state().get("selection").first().toJSON();
$("input." + selector).val(attachment.url);
$("img." + selector).attr("src",attachment.url);
});
// Open the upload dialog
wkMedia.open();
});
});
});