ExpressionEngine Docs

# CP/Modal Service

- Simple example
- Delete confirmation modals
- CP/Modal Service Methods

The Modal service organizes various modal views for presentation upon a trigger you specify.

## Simple example

Let’s say we want to create a modal that says “Hello, world!”. First, we need to construct the markup that displays the modal. We can either start with the Modal Wrap markup in the style guide, or we can use our shared modal view. We’ll just use our shared modal view and pass in our content so we don’t have to worry about maintaining markup:

    $modal_vars = array(
      'name' => 'hello',
      'contents' => '<p>Hello, world!</p>'
    );
    $modal_html = ee('View')->make('ee:_shared/modal')->render($modal_vars);

We had to specify two view variables: `name` and `contents`. `name` is just a unique identifier for the modal, we’ll reference this later when we decide to show it. `contents` is the HTML content for the modal.

Great, we’ve got our modal markup, let’s hand it off to the Modal service:

    ee('CP/Modal')->addModal('hello', $modal_html);

Now, the modal will be present in our page’s DOM next time we load it, but will be hidden. How do we show it? A simple way is a link that looks like this:

    <a href="" class="m-link" rel="hello">Say hello</a>

What makes this link special is the `m-link` class, and then the following `rel=` attribute where we specify the unique name of our modal we created earlier. If we click the link, and we should see our modal!

## Delete confirmation modals

Probably the most common use case for a modal is a delete confirmation modal. There are two kinds of deletion in the CP: clicking a delete link next to the item to start the deletion process (common in folder lists in the sidebar), and bulk deletion, mostly-commonly used with a table UI where the user can select multiple items from a table, select “Remove” in the bulk action selector, then click “Submit” to display the modal. We’ll cover how to do each.

### Single item deletion

Our code will look similar to our simple example, except we’ll set up a placeholder hidden input for the content ID we’ll be deleting, and we’ll use another shared view file specifically for delete confirmations:

    $modal_vars = array(
      'name'    => 'modal-confirm-remove',
      'form_url'  => ee('CP/URL')->make('addons/myaddon/remove'),
      'hidden'  => array(
        'content_id' => ''
      )
    );
    $modal_html = ee('View')->make('ee:_shared/modal_confirm_remove')->render($modal_vars);
    ee('CP/Modal')->addModal('remove', $modal_html);

Constructing our link to display the modal will require a little bit more data than before, because we may have more than one delete link on a page, and we want our modal to say what is about to be deleted. Here’s what our delete link will look like:

    <a class="m-link"
       rel="modal-confirm-remove"
       href=""
       data-confirm="Content Item: <b>My Entry</b>"
       data-content_id="23">Delete</a>

Warning: The `m-link` class is essential. You can add other classes to your link, but you must have the `m-link` class for the modal to work properly.

Finally, we need some JavaScript to tie it all together. We want to accomplish two goals: show the name of the item being deleted, and pass along relevant data to the form inside the modal so that our controller code knows which item is being deleted:

    $(document).ready(function () {
      $('a.m-link').click(function (e) {
        var modalIs = $('.' + $(this).attr('rel'));

        $('.checklist', modalIs)
          .html('') // Reset it
          .append('<li>' + $(this).data('confirm') + '</li>');
        $('input[name="content_id"]', modalIs).val($(this).data('content_id'));

        e.preventDefault();
      })
    });

With that, when we click our link, a modal should appear asking us to confirm we want to delete “My Entry”, and when we submit the form, it will `POST` to our specified `form_url` with the `content_id` we passed along.

### Bulk item deletion

Bulk item deletion is assumed to be used with a table listing of content. Since that’s how it’s consistently used in ExpressionEngine’s interface, these instructions will be based in that context. Our modal markup generation will look similar to our previous example, except we don’t need to define any hidden inputs:

    $modal_vars = array(
      'name'    => 'modal-confirm-remove',
      'form_url'  => ee('CP/URL')->make('addons/myaddon/remove')
    );
    $modal_html = ee('View')->make('ee:_shared/modal_confirm_remove')->render($modal_vars);
    ee('CP/Modal')->addModal('remove', $modal_html);

Generating table listings is easiest with the CP/Table Service, so we’ll use that and add a column of type `Table::COL_CHECKBOX` so that users can select data they want to delete. Defining that column will look like this for us:

    $columns[] = array(
      'name' => 'content_ids[]',
      'value' => $content->getId(),
      'data'  => array(
        'confirm' => lang('content') . ': <b>' . htmlentities($content->title, ENT_QUOTES, 'UTF-8') . '</b>'
      )
    );

We give the checkboxes an input name of `content_ids[]`, which will then carry over to the modal automatically, so that when we submit the form in our modal, the `$_POST` key we’ll grab the content IDs from will be `content_ids`. But we need JavaScript to facilitate this for us, and luckily, it’s already written. Just include this in your controller:

    ee()->cp->add_js_script(array(
      'file' => array('cp/confirm_remove'),
    ));

Finally, we need to create our Bulk Action Controls with some special data attributes that know when to trigger the modal. Here’s what we’ll add below our table markup:

    <fieldset class="tbl-bulk-act hidden">
      <select>
        <option>-- <?=lang('with_selected')?> --</option>
        <option value="remove" data-confirm-trigger="selected" rel="modal-confirm-remove"><?=lang('remove')?></option>
      </select>
      <input class="btn submit" data-conditional-modal="confirm-trigger" type="submit" value="<?=lang('submit')?>">
    </fieldset>

Now when a user selects some content in the table, the bulk action controls should appear, and when “Remove” is selected and submitted, a modal will appear showing a list of content about to be deleted, where they can then confirm the deletion and your `POST` handler will be fired.

## CP/Modal Service Methods

class `EllisLab\ExpressionEngine\Service\Modal\ModalCollection`

- `addModal($name, $data)`
- `startModal()`
- `endModal()`
- `getModal($name)`
- `getAllModals()`

### `addModal($name, $data)`

Adds a named modal to the collection

Parameter | Type | Description
--- | --- | ---
$name | `String` | The name of the modal
$data | `String` | The contents of the modal
Returns | `ModalCollection` | $this

### `startModal()`

This will start a new modal overwriting any previously defined modal of the same name.

Parameter | Type | Description
--- | --- | ---
$name | `String` | The name of the modal
Returns | `Void` |

### `endModal()`

Ends the modal adding the modal to the collection based on the most recently specified name via startModal.

Parameter | Type | Description
--- | --- | ---
Returns | `Void` |

### `getModal($name)`

Gets a named modal from the collection

Parameter | Type | Description
--- | --- | ---
$name | `String` | The name of the modal
Returns | `Mixed` | The data stored for the named modal

### `getAllModals()`

Gets all the modals stored in this collection

Parameter | Type | Description
--- | --- | ---
Returns | `Array` | An array of stored modal data