diff --git a/modules/cart/commerce_cart.info b/modules/cart/commerce_cart.info
index d7195fc..a59be05 100644
--- a/modules/cart/commerce_cart.info
+++ b/modules/cart/commerce_cart.info
@@ -15,6 +15,7 @@ core = 7.x
 
 ; Views handlers
 files[] = includes/views/handlers/commerce_cart_handler_field_add_to_cart_form.inc
+files[] = includes/views/handlers/commerce_cart_handler_field_edit_attributes.inc
 files[] = includes/views/handlers/commerce_cart_plugin_argument_default_current_cart_order_id.inc
 files[] = includes/views/handlers/commerce_cart_handler_area_empty_text.inc
 
diff --git a/modules/cart/commerce_cart.module b/modules/cart/commerce_cart.module
index 77c90f8..93b2e11 100644
--- a/modules/cart/commerce_cart.module
+++ b/modules/cart/commerce_cart.module
@@ -2369,6 +2369,16 @@ function commerce_cart_add_to_cart_form_attributes_refresh($form, $form_state) {
 }
 
 /**
+ * Ajax callback: returns AJAX commands when an attribute widget is changed on
+ * the Views powered shopping cart form.
+ */
+function commerce_cart_add_to_cart_views_form_refresh($form, $form_state) {
+  $commands[] = array();
+  $commands[] = ajax_command_replace('.' . drupal_html_class('commerce-line-item-views-form'), drupal_render($form));
+  return array('#type' => 'ajax', '#commands' => $commands);
+}
+
+/**
  * Form submit handler: add the selected product to the cart.
  */
 function commerce_cart_add_to_cart_form_submit($form, &$form_state) {
diff --git a/modules/cart/includes/views/commerce_cart.views.inc b/modules/cart/includes/views/commerce_cart.views.inc
index 4ced3f0..8d4b909 100644
--- a/modules/cart/includes/views/commerce_cart.views.inc
+++ b/modules/cart/includes/views/commerce_cart.views.inc
@@ -29,6 +29,15 @@ function commerce_cart_views_data_alter(&$data) {
       'handler' => 'commerce_cart_handler_area_empty_text',
     ),
   );
+
+  // Add an edit handler for cart line item attributes.
+  $data['commerce_line_item']['edit_attributes'] = array(
+    'field' => array(
+      'title' => t('Attribute field widgets'),
+      'help' => t('Renders attribute field widgets for customers to edit from the View.'),
+      'handler' => 'commerce_cart_handler_field_edit_attributes',
+    ),
+  );
 }
 
 /**
diff --git a/modules/cart/includes/views/handlers/commerce_cart_handler_field_edit_attributes.inc b/modules/cart/includes/views/handlers/commerce_cart_handler_field_edit_attributes.inc
new file mode 100644
index 0000000..9e39c7b
--- /dev/null
+++ b/modules/cart/includes/views/handlers/commerce_cart_handler_field_edit_attributes.inc
@@ -0,0 +1,107 @@
+<?php
+
+/**
+ * @file
+ * Field handler to render attribute widgets to select a different product for
+ * the line item.
+ */
+
+class commerce_cart_handler_field_edit_attributes extends views_handler_field {
+
+  function construct() {
+    parent::construct();
+    $this->additional_fields['line_item_id'] = 'line_item_id';
+
+    // Set real_field in order to make it generate a field_alias.
+    $this->real_field = 'line_item_id';
+  }
+
+  function render($values) {
+    return '<!--form-item-' . $this->options['id'] . '--' . $this->view->row_index . '-->';
+  }
+
+  /**
+   * Returns the form which replaces the placeholder from render().
+   */
+  function views_form(&$form, &$form_state) {
+    // The view is empty, abort.
+    if (empty($this->view->result)) {
+      return;
+    }
+
+    $form[$this->options['id']] = array(
+      '#tree' => TRUE,
+    );
+
+    // At this point, the query has already been run, so we can access the
+    // results in order to get the base key value (for example, nid for nodes).
+    foreach ($this->view->result as $row_id => $row) {
+      // Load the line item and generate a form ID based on its context data.
+      $line_item = commerce_line_item_load($this->get_value($row, 'line_item_id'));
+      $product_ids = commerce_cart_add_to_cart_form_product_ids($line_item);
+      $form_id = commerce_cart_add_to_cart_form_id($product_ids);
+
+      // Fetch the Add to Cart form and put the attributes section into this
+      // field's part of the form if it exists.
+      $subform_state = $form_state;
+      $subform_state['build_info'] = array(
+        'form_id' => $form_id,
+        'base_form_id' => 'commerce_cart_add_to_cart_form',
+        'args' => array($line_item),
+      );
+
+      // If the form has been submitted, copy the attributes values from the
+      // edit_attributes sub-array to the top level of the submitted values
+      // array so the selected product can be properly matched when the Add to
+      // Cart form builds itself.
+      if (!empty($form_state['values']['edit_attributes'][$row_id])) {
+        $subform_state['values'] += $form_state['values']['edit_attributes'][$row_id];
+      }
+
+      $subform = array();
+      $subform = commerce_cart_add_to_cart_form($subform, $subform_state, $line_item);
+
+      // If an Ajax refresh resulted in an updated product ID, update the line
+      // item accordingly and rebuild the subform.
+      $line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
+
+      if(isset($subform['product_id']['#value'])) {
+        if ($subform['product_id']['#value'] != $line_item_wrapper->commerce_product->raw()) {
+          $line_item_wrapper->commerce_product = $subform['product_id']['#value'];
+          $line_item_wrapper->save();
+          $form_state['rebuild'] = TRUE;
+
+          $subform_state = $form_state;
+          $subform_state['build_info'] = array(
+            'form_id' => $form_id,
+            'base_form_id' => 'commerce_cart_add_to_cart_form',
+            'args' => array($line_item),
+          );
+
+          $subform = array();
+          $subform = commerce_cart_add_to_cart_form($subform, $subform_state, $line_item);
+        }
+      }
+
+      // Initialize the element representing the attribute fields in the form.
+      $form[$this->options['id']][$row_id] = array();
+      $element = &$form[$this->options['id']][$row_id];
+
+      foreach (array('attributes', 'unchanged_attributes', 'product_id') as $name) {
+        if (!empty($subform[$name])) {
+          $element[$name] = $subform[$name];
+
+          if (!empty($element[$name]['#ajax']['callback'])) {
+            $element[$name]['#ajax']['callback'] = 'commerce_cart_add_to_cart_views_form_refresh';
+          }
+
+          foreach (element_children($element[$name]) as $key) {
+            if (!empty($element[$name][$key]['#ajax']['callback'])) {
+              $element[$name][$key]['#ajax']['callback'] = 'commerce_cart_add_to_cart_views_form_refresh';
+            }
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
