There are a lot of demos and tutorials about incorporating the image uploader and selector, but not much about the other parts of the library. is a blank modal view, which the media modal uses as its default container.

This view is demo’d in the Media Guide, but it’s not really discussed elsewhere.

Modal displays the large white box that contains the media manager. Within,
it’s used only two times. One is when the media manager needs to display in a modal
(it can display outside of a modal, as well), and second is EditAttachments, which
throws up a modal.

    var modal = new{
        // A controller object is expected, but let's just pass
        // a fake one to illustrate this proof of concept without
        // getting console errors.
        controller: { trigger: function() {} }

EditAttachments shows one way to write the controller, as an extension
of Frames. A Frame is a view with state management. Unfortunately,
it’s pretty complex, so I couldn’t make sense of it.

So, instead, I dug into the code for wp.Backbone.View.


wp.Backbone.View, the base class for Views, expands upon Backbone’s idea
of view by adding the following:

constructor(options) – adds views, a collection of Subviews.

abstract method ready(), called when constructor() is called.

remove() – recursively removes child views

render() – you no longer define render. Instead you override prepare()

prepare() – the return value of prepare() is passed as the input into the template().
defined when you extend wp.Backbone.View

template() – defined when you extends wp.Backbone.View

Backbone Views don’t have controllers. Instead, you have a Model that is rendered
to a view. The view has an events mapping object that’s used to attach event
handlers to elements. When fields are edited, or buttons clicked, handlers
can then read the UI, and copy values into the model. The model, in turn, emits
events that force a redraw of the view. goes whole-hog and has features for managing
collections of objects. That’s necessary for the media manager, but not really
necessary for a less elaborate use.

This minimal example below is enough:

    var formname = 'foo-form';
    var FooView ={
            events: {
                'change #foo-form--foo': 'formupdate'
            template: wp.template( formname ),
            prepare: function() {
                return this.model.toJSON();
            formupdate: function() {
                this.model.set({foo: $('#foo-form--foo').val());

    var modal = new{
            controller: { 
                trigger: function(id) {
                    // events can be caught here

    var FooModel =;
    var m = new FooModel({foo:1}); 
    modal.content( new FooView({ model: m }) );;

And the foo form looks like this:

<script id="tmpl-foo-form" type="text/template">
    <input id="foo-form--foo" value="{{ }}" />

Note that the value of foo is called “”, not
simply “foo”. This is a wp.template convention.

So, from the top, let’s see what’s going on.

First, there are some naming conventions. wp.template’s
naming convention for templates is that they are all named
“tmpl-*”. We ask for wp.template(‘foo-form’), and it will
look for “tmpl-foo-form”.

Also, not that I suffix forms with “-form”. Not required,
but it makes things easier. I also use the BEM-like
naming convention of “foo-form–foo”. The form name
followed by — and then by the element. This naming
convention makes it easy to come up with unique names.

Note that when we extend wp.Backbone.View, our options
have events and template, but lacks a “render” method.
Instead, we have a “prepare” method that prepares the
data input for the template function. We just pass
the model’s properties.

wp.Backbone.View has its own render() method, and we
should not override it.

The event handler, formupdate, is like a regular
Backbone view event handler.

This example can’t do anything useful, but it’s
something to study and build on.