diff --git a/src/Plugin/facets/widget/CheckboxWidget.php b/src/Plugin/facets/widget/CheckboxWidget.php
index 685ffea..27382ab 100644
--- a/src/Plugin/facets/widget/CheckboxWidget.php
+++ b/src/Plugin/facets/widget/CheckboxWidget.php
@@ -7,10 +7,13 @@
 
 namespace Drupal\facets\Plugin\facets\widget;
 
+use Drupal\Core\Form\FormInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\Core\Url;
 use Drupal\facets\FacetInterface;
 use Drupal\facets\Widget\WidgetInterface;
+use Symfony\Component\HttpFoundation\RedirectResponse;
 
 /**
  * The checkbox / radios widget.
@@ -21,19 +24,11 @@ use Drupal\facets\Widget\WidgetInterface;
  *   description = @Translation("A configurable widget that shows a list of checkboxes"),
  * )
  */
-class CheckboxWidget implements WidgetInterface {
+class CheckboxWidget implements WidgetInterface, FormInterface {
 
   use StringTranslationTrait;
 
   /**
-   * The link generator.
-   *
-   * @var \Drupal\Core\Utility\LinkGeneratorInterface $linkGenerator
-   *   The link generator.
-   */
-  protected $linkGenerator;
-
-  /**
    * {@inheritdoc}
    */
   public function execute() {
@@ -44,33 +39,14 @@ class CheckboxWidget implements WidgetInterface {
    * {@inheritdoc}
    */
   public function build(FacetInterface $facet) {
-    /** @var \Drupal\facets\Result\Result[] $results */
-    $results = $facet->getResults();
-    $items = [];
-
-    $configuration = $facet->getWidgetConfigs();
-    $show_numbers = (bool) $configuration['show_numbers'];
+    $form_builder = \Drupal::getContainer()->get('form_builder');
 
-    foreach ($results as $result) {
-      if ($result->getCount()) {
-        // Get the link.
-        $text = $result->getDisplayValue();
-        if ($show_numbers) {
-          $text .= ' (' . $result->getCount() . ')';
-        }
-        if ($result->isActive()) {
-          $text = '(-) ' . $text;
-        }
-        $link = $this->linkGenerator()->generate($text, $result->getUrl());
-        $items[] = $link;
-      }
-    }
-    $build = [
-      '#theme' => 'item_list',
-      '#items' => $items,
-    ];
+    // The form builder's getForm method accepts 1 argument in the interface,
+    // the form ID. Extra arguments get passed into the form states addBuildInfo
+    // method. This way we can pass the facet to the ::buildForm method, it uses
+    // FormState::getBuildInfo to get the facet out.
+    $build = $form_builder->getForm(static::class, $facet);
 
-    $build['#prefix'] = $this->t('Checkboxes');
     return $build;
   }
 
@@ -102,16 +78,101 @@ class CheckboxWidget implements WidgetInterface {
   }
 
   /**
-   * Gets the link generator.
-   *
-   * @return \Drupal\Core\Utility\LinkGeneratorInterface
-   *   The link generator.
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'facets_checkbox_widget';
+  }
+
+  /**
+   * {@inheritdoc}
    */
-  protected function linkGenerator() {
-    if (!isset($this->linkGenerator)) {
-      $this->linkGenerator = \Drupal::linkGenerator();
+  public function buildForm(array $form, FormStateInterface $form_state) {
+
+    /** @var \Drupal\facets\FacetInterface $facet */
+    // Get the facet form the build info, see the remark in ::build to know
+    // where this comes from.
+    $build_info = $form_state->getBuildInfo();
+    $facet = $build_info['args'][0];
+
+    /** @var \Drupal\facets\Result\Result[] $results */
+    $results = $facet->getResults();
+
+    $configuration = $facet->getWidgetConfigs();
+    $show_numbers = (bool) $configuration['show_numbers'];
+    $form[$facet->getFieldAlias()] = [
+      '#type' => 'checkboxes',
+      '#title' => $facet->getName(),
+    ];
+
+    $options = array();
+    foreach ($results as $result) {
+      $text = $result->getDisplayValue();
+      if ($show_numbers) {
+        $text .= ' (' . $result->getCount() . ')';
+      }
+
+      $options[$result->getRawValue()] = $text;
+
+      if ($result->isActive()) {
+        $form[$facet->getFieldAlias()]['#default_value'][] = $result->getRawValue();
+      }
     }
-    return $this->linkGenerator;
+
+    $form[$facet->getFieldAlias()]['#options'] = $options;
+
+    $form[$facet->id() . '_submit'] = [
+      '#type' => 'submit',
+      '#value' => 'submit',
+    ];
+
+    return $form;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, FormStateInterface $form_state) {}
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $values = $form_state->getValues();
+
+    /** @var \Drupal\facets\FacetInterface $facet */
+    $build_info = $form_state->getBuildInfo();
+    $facet = $build_info['args'][0];
+
+    $result_link = FALSE;
+    $active_items = [];
+
+    foreach ($values[$facet->getFieldAlias()] as $key => $value) {
+      if ($value !== 0) {
+        $active_items[] = $value;
+      }
+    }
+
+    foreach ($facet->getResults() as $result) {
+      if (in_array($result->getRawValue(), $active_items)) {
+        $result_link = $result->getUrl();
+      }
+    }
+
+    // We have an active item, so we redirect to the page that has that facet
+    // selected. This should be an absolute link because RedirectResponse is a
+    // symfony class that requires a full URL.
+    if ($result_link instanceof Url) {
+      $result_link->setAbsolute();
+      $form_state->setResponse(new RedirectResponse($result_link->toString()));
+      return;
+    }
+
+    // The form was submitted but nothing was active in the form, we should
+    // still redirect, but the url for the new page can't come from a result.
+    // So we're redirecting to the facet source's page.
+    $link = Url::fromUri($facet->getFacetSource()->getPath());
+    $link->setAbsolute();
+    $form_state->setResponse(new RedirectResponse($link->toString()));
+  }
 }
diff --git a/src/Tests/WidgetIntegrationTest.php b/src/Tests/WidgetIntegrationTest.php
new file mode 100644
index 0000000..5f91902
--- /dev/null
+++ b/src/Tests/WidgetIntegrationTest.php
@@ -0,0 +1,83 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\facets\Tests\WidgetIntegrationTest.
+ */
+
+namespace Drupal\facets\Tests;
+
+use \Drupal\facets\Tests\WebTestBase as FacetWebTestBase;
+
+/**
+ * Tests the overall functionality of the Facets admin UI.
+ *
+ * @group facets
+ */
+class WidgetIntegrationTest extends FacetWebTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = [
+    'views',
+    'node',
+    'search_api',
+    'search_api_test_backend',
+    'facets',
+    'search_api_test_views',
+    'block',
+    'facets_search_api_dependency',
+    'facets_query_processor',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+
+    $this->drupalLogin($this->adminUser);
+
+    $this->setUpExampleStructure();
+    $this->insertExampleContent();
+    $this->assertEqual($this->indexItems($this->indexId), 5, '5 items were indexed.');
+  }
+
+  /**
+   * Tests various url integration things.
+   */
+  public function testCheckboxWidget() {
+    $id = 't';
+    $name = 'Facet & checkbox~';
+    $facet_add_page = 'admin/config/search/facets/add-facet';
+
+    $this->drupalGet($facet_add_page);
+
+    $form_values = [
+      'id' => $id,
+      'status' => 1,
+      'url_alias' => $id,
+      'name' => $name,
+      'facet_source_id' => 'search_api_views:search_api_test_view:page_1',
+      'facet_source_configs[search_api_views:search_api_test_view:page_1][field_identifier]' => 'type',
+    ];
+    $this->drupalPostForm(NULL, ['facet_source_id' => 'search_api_views:search_api_test_view:page_1'], $this->t('Configure facet source'));
+    $this->drupalPostForm(NULL, $form_values, $this->t('Save'));
+    $this->drupalPostForm(NULL, ['widget' => 'checkbox'], $this->t('Save'));
+
+    $block_values = [
+      'plugin_id' => 'facet_block:' . $id,
+      'settings' => [
+        'region' => 'footer',
+        'id' => str_replace('_', '-', $id),
+      ]
+    ];
+    $this->drupalPlaceBlock($block_values['plugin_id'], $block_values['settings']);
+
+    $this->drupalGet('search-api-test-fulltext');
+    $this->drupalPostForm(NULL, array('type[item]' => 'item'), $this->t('submit'));
+    $this->assertFieldChecked('edit-type-item');
+  }
+
+}
diff --git a/tests/src/Unit/Plugin/widget/CheckboxWidgetTest.php b/tests/src/Unit/Plugin/widget/CheckboxWidgetTest.php
index f24ee45..187dddd 100644
--- a/tests/src/Unit/Plugin/widget/CheckboxWidgetTest.php
+++ b/tests/src/Unit/Plugin/widget/CheckboxWidgetTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Tests\facets\Unit\Plugin\widget;
 
+use Drupal\Core\Form\FormState;
 use Drupal\facets\Entity\Facet;
 use Drupal\facets\Plugin\facets\widget\CheckboxWidget;
 use Drupal\facets\Result\Result;
@@ -23,7 +24,7 @@ class CheckboxWidgetTest extends UnitTestCase {
   /**
    * The processor to be tested.
    *
-   * @var \drupal\facets\Widget\WidgetInterface
+   * @var \Drupal\facets\Plugin\facets\widget\CheckboxWidget
    */
   protected $widget;
 
@@ -53,19 +54,16 @@ class CheckboxWidgetTest extends UnitTestCase {
     }
     $this->originalResults = $original_results;
 
-    $link_generator = $this->getMockBuilder('\Drupal\Core\Utility\LinkGenerator')
+    $form_builder = $this->getMockBuilder('\Drupal\Core\Form\FormBuilder')
       ->disableOriginalConstructor()
       ->getMock();
-    $link_generator->expects($this->atLeastOnce())
-      ->method('generate')
-      ->will($this->returnArgument(0));
 
     $string_translation = $this->getMockBuilder('\Drupal\Core\StringTranslation\TranslationManager')
       ->disableOriginalConstructor()
       ->getMock();
 
     $container_builder = new ContainerBuilder();
-    $container_builder->set('link_generator', $link_generator);
+    $container_builder->set('form_builder', $form_builder);
     $container_builder->set('string_translation', $string_translation);
     \Drupal::setContainer($container_builder);
 
@@ -78,34 +76,74 @@ class CheckboxWidgetTest extends UnitTestCase {
   public function testDefaultSettings() {
     $facet = new Facet([], 'facet');
     $facet->setResults($this->originalResults);
-
-    $output = $this->widget->build($facet);
-
-    $this->assertInternalType('array', $output);
-    $this->assertCount(4, $output['#items']);
-
-    $expected_links = ['Llama', 'Badger', 'Duck', 'Alpaca'];
+    $facet->setFieldIdentifier('test_field');
+
+    $formState = new FormState();
+    $formState->addBuildInfo('args', [$facet]);
+    $form = [];
+    $built_form = $this->widget->buildForm($form, $formState);
+
+    $this->assertInternalType('array', $built_form);
+    $this->assertCount(4, $built_form['test_field']['#options']);
+    $this->assertEquals('checkboxes', $built_form['test_field']['#type']);
+
+    $expected_links = [
+      'llama' => 'Llama',
+      'badger' => 'Badger',
+      'duck' => 'Duck',
+      'alpaca' => 'Alpaca'
+    ];
     foreach ($expected_links as $index => $value) {
-      $this->assertEquals($value, $output['#items'][$index]);
+      $this->assertEquals($value, $built_form['test_field']['#options'][$index]);
     }
   }
 
   /**
-   * Test widget with show numbers enabled.
+   * Test widget, make sure hiding and showing numbers works.
    */
-  public function testShowAmount() {
+  public function testHideNumbers() {
+    $original_results = $this->originalResults;
+    $original_results[1]->setActiveState(TRUE);
+
     $facet = new Facet([], 'facet');
-    $facet->setResults($this->originalResults);
+    $facet->setResults($original_results);
+    $facet->setFieldIdentifier('test__field');
+    $facet->setWidgetConfigs(['show_numbers' => 0]);
+
+    $formState = new FormState();
+    $formState->addBuildInfo('args', [$facet]);
+    $form = [];
+    $built_form = $this->widget->buildForm($form, $formState);
+
+    $this->assertInternalType('array', $built_form);
+    $this->assertCount(4, $built_form['test__field']['#options']);
+    $expected_links = [
+      'llama' => 'Llama',
+      'badger' => 'Badger',
+      'duck' => 'Duck',
+      'alpaca' => 'Alpaca'
+    ];
+    foreach ($expected_links as $index => $value) {
+      $this->assertEquals($value, $built_form['test__field']['#options'][$index]);
+    }
+
+    // Enable the 'show_numbers' setting again to make sure that the switch
+    // between those settings works.
     $facet->setWidgetConfigs(['show_numbers' => 1]);
 
-    $output = $this->widget->build($facet);
+    $built_form = $this->widget->buildForm($form, $formState);
 
-    $this->assertInternalType('array', $output);
-    $this->assertCount(4, $output['#items']);
+    $this->assertInternalType('array', $built_form);
+    $this->assertCount(4, $built_form['test__field']['#options']);
 
-    $expected_links = ['Llama (10)', 'Badger (20)', 'Duck (15)', 'Alpaca (9)'];
+    $expected_links = [
+      'llama' => 'Llama (10)',
+      'badger' => 'Badger (20)',
+      'duck' => 'Duck (15)',
+      'alpaca' => 'Alpaca (9)',
+    ];
     foreach ($expected_links as $index => $value) {
-      $this->assertEquals($value, $output['#items'][$index]);
+      $this->assertEquals($value, $built_form['test__field']['#options'][$index]);
     }
   }
 
