Change record status: 
Project: 
Introduced in branch: 
8.x
Description: 

Configurable plugins (see ConfigurablePluginInterface) often need their own form elements added to their parent form.
To accomplish that, there is \Drupal\Core\Plugin\PluginFormInterface:

public function buildConfigurationForm(array $form, FormStateInterface $form_state);
public function validateConfigurationForm(array &$form, FormStateInterface $form_state);
public function submitConfigurationForm(array &$form, FormStateInterface $form_state);

These methods are exactly like their corresponding methods on \Drupal\Core\Form\FormInterface.

The buildConfigurationForm() and validateConfigurationForm() methods behave normally.
When used in conjunction with ConfigurablePluginInterface, the submitConfigurationForm() method should not explicitly save any values, but just update its own configuration:

namespace Drupal\mymodule;

use Drupal\Component\Plugin\ConfigurablePluginInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\PluginBase;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\Core\Utility\Url;

class MyModulePlugin extends PluginBase implements ConfigurablePluginInterface, PluginFormInterface {

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, array $plugin_definition) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);

    $this->configuration += $this->defaultConfiguration();
  }

  /**
   * {@inheritdoc}
   */
  public function getConfiguration() {
    return $this->configuration;
  }

  /**
   * {@inheritdoc}
   */
  public function setConfiguration(array $configuration) {
    $this->configuration = $configuration;
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return array(
      'url' => '',
    );
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $form['url'] = array(
      '#type' => 'textfield',
      '#title' => $this->t('URL'),
      '#description' => $this->t('The URL for this plugin instance')),
      '#default_value' => $this->configuration['url'],
      '#required' => TRUE,
    );
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
    if (!Url::isValid($form_state['values']['url'])) {
      $form_state->setErrorByName('url', $form_state);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    $this->configuration['url'] = $form_state['values']['url'];
  }

}

Impacts: 
Module developers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Other updates done