reverted:
--- b/clients/gplan.inc
+++ a/clients/gplan.inc
@@ -86,18 +86,6 @@
     return $this->products;
   }
 
-  /**
-   * This gives the product list.
-   *
-   * This function is used by the wa_product component.
-   * You can apply filtering in this function.
-   * The fallback will be all products.
-   */
-  public function get_filtered_available_products() {
-    $products = $this->get_available_products();
-    return $products;
-  }
-
   public function get_product_details($product_id) {
     $productDetails = $this->call('getGovProductDetails', array(
       'productID' => $product_id
diff -u b/clients/gplan_multiple.inc b/clients/gplan_multiple.inc
--- b/clients/gplan_multiple.inc
+++ b/clients/gplan_multiple.inc
@@ -4,7 +4,6 @@
 
   protected $location_id;
   protected $products;
-  protected $locations;
   protected $api_method= 'soap';
 
   const APPOINTMENT_STATUS_BOOKED                      =  0;
@@ -58,6 +57,9 @@
     return $form;
   }
 
+  /**
+   * @inheritdoc
+   */
   public function get_available_products() {
     if ($this->products) {
       return $this->products;
@@ -95,11 +97,7 @@
   }
 
   /**
-   * This gives the product list.
-   *
-   * This function is used by the wa_product component.
-   * You can apply filtering in this function.
-   * The fallback will be all products.
+   * @inheritdoc
    */
   public function get_filtered_available_products() {
     $products = $this->get_available_products();
@@ -115,7 +113,7 @@
   }
 
   /**
-   * This returns the locations.
+   * @inheritdoc
    */
   public function get_gov_locations() {
     if ($this->locations) {
@@ -141,11 +139,9 @@
   }
 
   /**
-   * This gives the location list.
+   * @inheritdoc
    *
-   * This function is used by the wa_location component.
-   * You can apply filtering in this function.
-   * The fallback will be all locations.
+   * @todo needs refactoring.
    */
   public function get_filtered_locations($products = FALSE) {
     $locations = $this->get_gov_locations();
@@ -185,33 +181,6 @@
     return $locations;
   }
 
-  /**
-   * This returns locations details.
-   *
-   * @param $location_id
-   *
-   * @return mixed location
-   */
-  public function get_location_details($location_id) {
-    $this->get_gov_locations();
-
-    if ($this->locations[$location_id]) {
-      return $this->locations[$location_id];
-    }
-
-    return FALSE;
-  }
-
-  /**
-   * This function is used to override the location.
-   * By default it will use location set in the constructor.
-   *
-   * @param $location_id
-   */
-  public function set_location($location_id) {
-    $this->location_id = $location_id;
-  }
-
   public function get_product_details($product_id) {
     $productDetails = $this->call('getGovProductDetails', array(
       'productID' => $product_id
reverted:
--- b/clients/orchestra.inc
+++ a/clients/orchestra.inc
@@ -64,32 +64,6 @@
     return $products;
   }
 
-  /**
-   * This gives the product list.
-   *
-   * This function is used by the wa_product component.
-   * You can apply filtering in this function.
-   * The fallback will be all products.
-   */
-  public function get_filtered_available_products() {
-    $products = $this->get_available_products();
-    return $products;
-  }
-
-  /**
-   * This returns the locations.
-   */
-  public abstract function get_gov_locations();
-
-  /**
-   * This can not be implemented.
-   *
-   * @param $location_id
-   *
-   * @return bool location
-   */
-  public abstract function get_location_details($location_id);
-
   protected function get_available_appointment_days($product_id, $count) {
     $rest_url_parameters['numberOfCustomers'] = $count;
     $available_appointment_days = $this->call('getAvailableAppointmentDays', array(
@@ -136,17 +110,17 @@
   public function get_times_by_date($product_ids, $durations, $persons, $date) {
     $dates_all = array();
     foreach ($product_ids as $product_link_id) {
+        $date = substr($date, 0, strpos($date, 'T')) . 'T00:00:00';
+        $time = $this->get_available_appointment_times($product_link_id, $persons[$product_link_id], $date);
+        if (!isset($dates_all[$product_link_id])) {
+          $dates_all[$product_link_id] = array();
+          $dates_all[$product_link_id]['dates'] = array();
+          $dates_all[$product_link_id]['product_id'] = $product_link_id;
+          $dates_all[$product_link_id]['duration'] = $durations[$product_link_id];
+        }
+        if (!isset($dates_all[$product_link_id]['dates'][$date])) {
+          $dates_all[$product_link_id]['dates'][$date] = is_array($time) ? $time : array($time);
+        }
-      $date = substr($date, 0, strpos($date, 'T')) . 'T00:00:00';
-      $time = $this->get_available_appointment_times($product_link_id, $persons[$product_link_id], $date);
-      if (!isset($dates_all[$product_link_id])) {
-        $dates_all[$product_link_id] = array();
-        $dates_all[$product_link_id]['dates'] = array();
-        $dates_all[$product_link_id]['product_id'] = $product_link_id;
-        $dates_all[$product_link_id]['duration'] = $durations[$product_link_id];
-      }
-      if (!isset($dates_all[$product_link_id]['dates'][$date])) {
-        $dates_all[$product_link_id]['dates'][$date] = is_array($time) ? $time : array($time);
-      }
     }
 
     $right_dates_time = $this->_check_consecutive_appointments($dates_all);
diff -u b/components/wa_location.inc b/components/wa_location.inc
--- b/components/wa_location.inc
+++ b/components/wa_location.inc
@@ -46,20 +46,18 @@
  * Implements _webform_render_COMPONENT().
  */
 function _webform_render_wa_location($component, $value = NULL, $filter = TRUE) {
-
   $form_item = array(
     '#type' => 'wa_location',
     '#title' => $filter ? webform_filter_xss($component['name']) : $component['name'],
     '#required' => $component['required'],
     '#weight' => $component['weight'],
     '#description'   => $filter ? webform_filter_descriptions($component['extra']['description']) : $component['extra']['description'],
-    '#default_value' => $filter ? webform_replace_tokens($component['value']) : $component['value'],
     '#prefix' => '<div class="webform-component-wa-location" id="webform-component-' . $component['form_key'] . '">',
     '#suffix' => '</div>',
   );
 
-  if (!empty($value)) {
-    $form_item['#default_value'] = $value;
+  if (!empty($value[0])) {
+    $form_item['#default_value'] = $value[0];
   }
 
   return $form_item;
@@ -69,7 +67,7 @@
  * Implements _webform_display_COMPONENT().
  */
 function _webform_display_wa_location($component, $value, $format = 'html') {
-  $location = dvg_appointments_get_location_information($value['location']);
+  $location = dvg_appointments_get_location_information($value[0]);
   return array(
     '#title' => $component['name'],
     '#weight' => $component['weight'],
@@ -101,53 +99,54 @@
   $available_locations = $client->get_filtered_locations($selected_products);
-
+  $location_options = array();
   foreach ($available_locations as $location) {
-    if (count($selected_products) == count($location['available_products']) && !array_key_exists('unavailable_products', $location)) {
+    // The 'available_products' index might not exist in the location array if there is no location for the selected product.
+    // Thus, check if the 'available_products' index exist in the location array to prevent "Undefined index" error.
+    if (array_key_exists('available_products', $location) && count($selected_products) == count($location['available_products'])) {
       $location_options[$location['id']] = $location['detail']->locationDesc;
     }
   }
 
-  if (count($location_options) < 0) {
-    drupal_set_message(t("This combination can't be planned on one location. Create an appointment for each product."), 'warning');
-  }
-
-  if (count($available_locations) > count($location_options)) {
-    drupal_set_message(t("Not every location is available for your appointment. You're appointment can only be made with the following location(s)."), 'info');
-  }
+  if ($count_location = count($location_options)) {
+    if (count($available_locations) > $count_location) {
+      $element['error_message'] = [
+        '#markup' => t("Some products are not available at all locations. Your appointment can only be made with the following location(s)."),
+      ];
+    }
 
-  if (count($location_options) > 5) {
-    $location_options = array_unshift($location_options, array('' => t('Select a location')));
-    $element['location'] = array(
-      '#type' => 'select',
-      '#title' => t('Location'),
-      '#required' => TRUE,
-      '#options' => $location_options,
-      '#attributes' => array('class' => array('wa-location')),
-    );
-  }
-  else {
     $element['location'] = array(
       '#type' => 'radios',
-      '#title' => t('Location'),
-      '#required' => TRUE,
+      '#title' => $element['#title'],
       '#options' => $location_options,
       '#attributes' => array('class' => array('wa-location')),
     );
+    if ($count_location > 5) {
+      $element['location']['#type'] = 'select';
+      // Prepend empty option while preserving keys.
+      $element['location']['#options'] =  array('' => t('Select a location')) + $element['location']['#options'];
+    }
+
+    if (!empty($element['#default_value'])) {
+      $element['location']['#default_value'] = $element['#default_value'];
+    }
   }
+  else {
+    $element['error_message'] = [
+      '#markup' => t("The selected products are not available at any location. Try making separate appointments for each product."),
+    ];
 
-  if (!empty($element['#default_value']['location'])) {
-    $element['location']['#default_value'] = $element['#default_value']['location'];
+    $form_state['complete form']['actions']['next']['#attributes']['disabled'] = 'disabled';
+    $form_state['complete form']['actions']['next']['#attributes']['title'] = t('Location needs to be selected to be able to proceed.');
   }
 
   return $element;
 }
 
 /**
- * Element validate callback for the wa_location elements.
+ * Implements _webform_submit_COMPONENT().
  */
-function dvg_appointments_location_element_validate($element, &$form_state) {
-  $form_key = $element['#webform_component']['form_key'];
-
-  if (empty($form_state['values']['submitted'][$form_key]['location'])) {
-    form_error($element['location'], t("You haven't filled in the location."));
+function _webform_submit_wa_location($component, $value) {
+  if (isset($value['location'])) {
+    return $value['location'];
   }
+  return array();
 }
diff -u b/dvg_appointments.client.inc b/dvg_appointments.client.inc
--- b/dvg_appointments.client.inc
+++ b/dvg_appointments.client.inc
@@ -4,6 +4,7 @@
 
   protected $soap_client;
   protected $timezone;
+  protected $locations;
   protected $max_persons = 10;
 
   abstract function __construct();
@@ -115,24 +116,66 @@
     return $this->max_persons;
   }
 
+  /**
+   * @return array
+   *   List of products available for appointments.
+   */
   abstract public function get_available_products();
 
-  abstract public function get_filtered_available_products();
+  /**
+   * Filtered version of get_available_products().
+   * If a location is used any products not available at any locations are removed.
+   *
+   * @return array
+   *   List of products available for appointments.
+   */
+  public function get_filtered_available_products() {
+    // Default implementation.
+    return $this->get_available_products();
+  }
 
+  /**
+   * @return array
+   *   List of locations available for appointments.
+   */
   public function get_gov_locations() {
     return array();
   }
 
+  /**
+   * Filter the available locations by the given products.
+   *
+   * @param $products array
+   *   List of products used for filtering.
+   *
+   * @return array
+   *   List of locations combined with available
+   *   and unavailable products for each location.
+   */
   public function get_filtered_locations($products) {
     return array();
   }
 
+  /**
+   * @param $location_id int
+   *   ID of the location to get details about.
+   *
+   * @return bool|array
+   *   FALSE if not available.
+   *   Array with the location object.
+   */
   public function get_location_details($location_id) {
+    if ($this->get_gov_locations()) {
+      if (isset($this->locations[$location_id])) {
+        return $this->locations[$location_id];
+      }
+    }
+
     return FALSE;
   }
 
   public function set_location($location_id) {
-    return FALSE;
+    $this->location_id = $location_id;
   }
 
   public function get_product_details($product_id) {
diff -u b/dvg_appointments.module b/dvg_appointments.module
--- b/dvg_appointments.module
+++ b/dvg_appointments.module
@@ -946,8 +946,8 @@
   $location = FALSE;
 
   $cid = dvg_appointments_get_cid($form['#node'], 'wa_location');
-  if ($cid && !empty($form_state['storage']['submitted'][$cid])) {
-    $location = $form_state['storage']['submitted'][$cid]['location'];
+  if ($cid && !empty($form_state['storage']['submitted'][$cid][0])) {
+    $location = $form_state['storage']['submitted'][$cid][0];
   }
 
   return $location;
@@ -1099,7 +1099,7 @@
   $client_api = dvg_appointments_get_client_api();
   $overrides = module_invoke_all('appointment_date_overrides');
 
-  // Location has been set and the location should be overridden in the client.
+  // Location has been set and the location should be used in the client.
   if ($location) {
     $client_api->set_location($location);
   }
@@ -1791,7 +1791,7 @@
   );
 
   $location = dvg_appointments_get_selected_location($form_state, $form);
-  // Location has been set and the location should be overridden in the client.
+  // Location has been set and the location should be used in the client.
   if ($location) {
     $client_api->set_location($location);
   }
@@ -2005,7 +2005,7 @@
       $appointment = $submission->data[$wa_appointment_cid]['appointment'];
       // Add Location to the appointment.
       if ($wa_location = dvg_appointments_get_cid($node, 'wa_location')) {
-        $location_id = $submission->data[$wa_location]['location'];
+        $location_id = $submission->data[$wa_location][0];
         if ($location = dvg_appointments_get_location_information($location_id)) {
           $appointment->setLocation($location);
         }
@@ -2086,7 +2086,7 @@
     $components = array(
       '' => t('Select a component'),
     );
-    $component_type_blacklist = array('wa_product', 'wa_date_time', 'wa_appointment', 'pagebreak', 'markup', 'fieldset');
+    $component_type_blacklist = array('wa_product', 'wa_date_time', 'wa_appointment', 'wa_location', 'pagebreak', 'markup', 'fieldset');
     foreach ($node->webform['components'] as $cid => $component) {
       if (!in_array($component['type'], $component_type_blacklist)) {
         $components[$cid] = $component['name'];
@@ -2210,7 +2210,7 @@
             // Add Location to the appointment.
             if ($wa_location = dvg_appointments_get_cid($node, 'wa_location')) {
               if ($wa_location) {
-                $location_id = $submission->data[$wa_location]['location'];
+                $location_id = $submission->data[$wa_location][0];
                 if ($location = dvg_appointments_get_location_information($location_id)) {
                   $appointment->setLocation($location);
                 }
@@ -2259,7 +2259,7 @@
 
         case 'dvg_appointments_location':
           if ($wa_location = dvg_appointments_get_cid($node, 'wa_location')) {
-            $location_id = $submission->data[$wa_location]['location'];
+            $location_id = $submission->data[$wa_location][0];
             $location = dvg_appointments_get_location_information($location_id);
           }
           // Check for location.
