Jul 14, 2014

Building a delete confirmation form with a wildcard in its path

When the user clicks on a link to delete an Optimizely project, a confirmation form is returned with buttons to Delete or to Cancel.

The url for this delete confirmation form has a parameter as the last part of the path, which is the unique integer id for the project. So it's structurally very similar to the update form that was documented in the previous post  http://optimizely-to-drupal-8.blogspot.com/2014/06/take-two-building-form-using-route-path.html

Unlike the update form, I was able to implement the delete confirmation in a simpler way. It was not necessary to define an intermediate method to accept the project id as a parameter and then pass the id along as part of a further call.

(1)  Defined a route in the optimizely.routing.yml file:

optimizely.delete.oid:
  path: /admin/config/system/optimizely/delete/{oid}
  defaults:
    _form: \Drupal\optimizely\DeleteForm
    _title: Optimizely Delete Project
  requirements:
    _permission: administer optimizely


Note the use of the {oid} wildcard in the path, which represents the project id.

For this route I was able to use the _form property rather than the _content property. For reasons not apparent to me, because class DeleteForm is derived from ConfirmFormBase rather than FormBase, passing the value of {oid} is done as I would hope. See buildForm() below and its optional third parameter.


(2)  Defined class DeleteForm (with comments removed here; other abbreviations also made).

namespace Drupal\optimizely;

use Drupal\Core\Form\ConfirmFormBase;

class DeleteForm extends ConfirmFormBase {

  private $oid = NULL;

  public function getFormId() {
    return 'optimizely-delete-page-confirm';
  }

  public function getQuestion() {
    return $this->t('Delete');  // Actually, a heading.
  }

  public function getDescription() {
    return $this->t('Are you sure ...');
  }

  public function getConfirmText() {
    return $this->t('Delete');
  }

  public function getCancelRoute() {
    return array('route_name' => 'optimizely.listing');
  }

  public function buildForm(array $form, array &$form_state, 

                            $oid = NULL) {
    $this->oid = $oid;
    return parent::buildForm($form, $form_state);
  }

  public function submitForm(array &$form, array &$form_state) {

    // Use $this->oid to update the database, etc. ...

    // Return to project listing page
    $form_state['redirect_route']['route_name'] = 

        'optimizely.listing';

  }
}


Some of these methods have default implementations. For example, getConfirmText() defaults to returning 'Confirm' for the confirmation button.

There is also a default implementation of buildForm() but in this scenario I implemented it in order to receive the value of the project id as a param and to save the id in an instance variable. Then the method calls buildForm() of the parent class to do the actual form building. Note that that third parameter must have a default value declared, otherwise you get a syntax error because the signature of the method will not match that in FormInterface.

At the end of submitForm() the reference parameter $form_state is altered in order to redirect to a particular path after processing the form. For a little more discussion about redirection, see this other post on drupal_goto()  http://optimizely-to-drupal-8.blogspot.com/2014/06/function-drupalgoto-has-been-removed.html

Updates for Drupal 8, alpha 13 and 14:  The name of method getCancelRoute() has been changed to getCancelUrl(), and it has a different type of return value. The signatures for methods buildForm() and submitForm() have changed to use FormStateInterface. Redirection is implemented differently.
See  http://optimizely-to-drupal-8.blogspot.com/2014/08/drupal-8-alpha11-alpha13.html  and   http://optimizely-to-drupal-8.blogspot.com/2014/08/drupal-8-alpha-13-alpha-14.html

  use Drupal\Core\Form\FormStateInterface;
  use Drupal\Core\Url;


  public function getCancelUrl() {
    return new Url('optimizely.listing');
  }


  public function buildForm(array $form, 

                            FormStateInterface $form_state, 
                            $oid = NULL) { ... }

  public function submitForm(array &$form, 

                             FormStateInterface $form_state) {
    // ...

    // Return to project listing page
    $form_state->setRedirect('optimizely.setting');
  }

Sources:

Drupal 8: Forms, OOP style, August 12, 2013
http://effulgentsia.drupalgardens.com/content/drupal-8-forms-oop-style

Form API in Drupal 8
https://www.drupal.org/node/2117411

abstract class ConfirmFormBase
https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Form!ConfirmFormBase.php/class/ConfirmFormBase/8

No comments:

Post a Comment