diff --git a/reference_option_limit.info b/reference_option_limit.info
index f83f112..1271c22 100644
--- a/reference_option_limit.info
+++ b/reference_option_limit.info
@@ -8,3 +8,4 @@ files[] = reference_option_limit_handler_filter_limited_options_term_reference.i
 files[] = tests/reference_option_limit.test
 
 test_dependencies[] = entityreference
+test_dependencies[] = profile2
diff --git a/reference_option_limit.module b/reference_option_limit.module
index 271cadc..d2beed2 100644
--- a/reference_option_limit.module
+++ b/reference_option_limit.module
@@ -237,6 +237,9 @@ function reference_option_limit_field_widget_form_alter(&$element, &$form_state,
   // When in ajax, these are already here!!!!
   $settings = array(
     'field'         => $field_name,
+    // We may not be at the top level of the form; this tells us where we
+    // actually are.
+    'field_parents' => $element['#field_parents'],
     'fields_match'  => $fields_match,
     // If there's a better way for hook_form_alter() to get these values than
     // stashing them here, file a patch! ;)
@@ -301,20 +304,28 @@ function reference_option_limit_form_alter(&$form, &$form_state, $form_id) {
     $field_option_limited = field_info_field($field_name_option_limited);
     $field_instance_option_limited = field_info_instance($settings['entity_type'], $field_name_option_limited, $settings['entity_bundle']);
 
+    // Get the form element to act on.
+    $parents = $settings['field_parents'];
+    $parents[] = $field_name_option_limited;
+    $element_limited =& drupal_array_get_nested_value($form, $parents);
+
     // Add a wrapper div to the limited field for the ajax to work on.
     $settings['ajax_wrapper'] = 'reference-options-limit-' . str_replace('_', '-', $field_name_option_limited);
-    $form[$field_name_option_limited]['#prefix'] = '<div id="' . $settings['ajax_wrapper'] . '">';
-    $form[$field_name_option_limited]['#suffix'] = '</div>';
-    //dsm($settings, 'settings');
+    $element_limited['#prefix'] = '<div id="' . $settings['ajax_wrapper'] . '">';
+    $element_limited['#suffix'] = '</div>';
 
     $match_columns = array();
     $match_values = array();
     $matching_field_labels = array();
     // Iterate over each matching field, ie, those we match values with.
     foreach ($settings['fields_match'] as $field_name_matching) {
+      $parents = $settings['field_parents'];
+      $parents[] = $field_name_matching;
+      $element_matching =& drupal_array_get_nested_value($form, $parents);
       // Make each matchable field ajaxy so its changes cause the limited
       // field to update itself.
-      $form[$field_name_matching][LANGUAGE_NONE]['#ajax'] = array(
+
+      $element_matching[LANGUAGE_NONE]['#ajax'] = array(
         'callback' => 'reference_option_limit_js',
         'wrapper' => $settings['ajax_wrapper'],
         'method' => 'replace',
@@ -339,7 +350,9 @@ function reference_option_limit_form_alter(&$form, &$form_state, $form_id) {
       if (isset($form_state['values'])) {
         // @todo: Figure out what on earth should happen when we have more than one column!
         $column = $match_columns[$field_name_matching][0];
-        foreach ($form_state['values'][$field_name_matching][LANGUAGE_NONE] as $delta => $item) {
+        $values_field_matching = drupal_array_get_nested_value($form_state['values'], $parents);
+
+        foreach ($values_field_matching[LANGUAGE_NONE] as $delta => $item) {
           $match_values[$field_name_matching][$delta] = $item[$column];
         }
       }
@@ -347,8 +360,8 @@ function reference_option_limit_form_alter(&$form, &$form_state, $form_id) {
         // Urgh, for taxonomy term reference fields the default value is an
         // array!
         // @todo: other field types probably have other quirks :(
-        if (is_array($form[$field_name_matching][LANGUAGE_NONE]['#default_value'])) {
-          $default_value_array = $form[$field_name_matching][LANGUAGE_NONE]['#default_value'];
+        if (is_array($element_matching[LANGUAGE_NONE]['#default_value'])) {
+          $default_value_array = $element_matching[LANGUAGE_NONE]['#default_value'];
           if (count($default_value_array)) {
             $match_values[$field_name_matching][] = $default_value_array;
           }
@@ -357,7 +370,7 @@ function reference_option_limit_form_alter(&$form, &$form_state, $form_id) {
           }
         }
         else {
-          $match_values[$field_name_matching][] = $form[$field_name_matching][LANGUAGE_NONE]['#default_value'];
+          $match_values[$field_name_matching][] = $element_matching[LANGUAGE_NONE]['#default_value'];
         }
       }
     }
@@ -447,7 +460,7 @@ function reference_option_limit_form_alter(&$form, &$form_state, $form_id) {
     // to get a properties array to pass to _options_prepare_options().
     $type = str_replace('options_', '', $field_instance_option_limited['widget']['type']);
     $multiple = $field_option_limited['cardinality'] > 1 || $field_option_limited['cardinality'] == FIELD_CARDINALITY_UNLIMITED;
-    $required = $form[$field_name_option_limited][LANGUAGE_NONE]['#required'];
+    $required = $element_limited[LANGUAGE_NONE]['#required'];
     $has_value = TRUE; // isset($items[0][$value_key]); ?????
     $properties = _options_properties($type, $multiple, $required, $has_value);
 
@@ -467,13 +480,13 @@ function reference_option_limit_form_alter(&$form, &$form_state, $form_id) {
 
     // Add an explanation if there are no options to select at all.
     if ($options_limited_empty) {
-      $form[$field_name_option_limited][LANGUAGE_NONE]['#description'] .= ' ' . t('No options are available for the current form values. Try selecting different values for the following fields: @fields.', array(
+      $element_limited[LANGUAGE_NONE]['#description'] .= ' ' . t('<b>No options are available for the current form values. Try selecting different values for the following fields: @fields.</b>', array(
         '@fields' => implode(', ', $matching_field_labels),
       ));
     }
 
     // Set the new options into the form element.
-    $form[$field_name_option_limited][LANGUAGE_NONE]['#options'] = $options_limited;
+    $element_limited[LANGUAGE_NONE]['#options'] = $options_limited;
   } // foreach settings
 }
 
@@ -507,7 +520,11 @@ function reference_option_limit_get_match_columns($field) {
 function reference_option_limit_js($form, $form_state) {
   // Deduce the field the triggering element belongs to.
   // @todo: not sure how robust this is.
-  $field_name_triggering = $form_state['triggering_element']['#parents'][0];
+
+  // Field matching is the penultimate item of the parents array.
+  $count = count($form_state['triggering_element']['#parents']);
+  $delta = $count - 2;
+  $field_name_triggering = $form_state['triggering_element']['#parents'][$delta];
 
   // Find which option limited field we should be returning the element for.
   // @todo: I have no idea how to make this work if the triggering field affects
@@ -515,16 +532,32 @@ function reference_option_limit_js($form, $form_state) {
   foreach ($form_state['reference_option_limit'] as $settings) {
     if (isset($settings['fields_match'][$field_name_triggering])) {
       $field_name_dependent = $settings['field'];
+      // @todo - limited to only one parent !
+      if (isset($settings['field_parents'][0])) {
+        $field_parent = $settings['field_parents'][0];
+      }
     }
   }
 
   if ($messages = theme('status_messages')) {
-    $form[$field_name_dependent]['messages'] = array(
-      '#markup' => '<div class="views-messages">' . $messages . '</div>',
-    );
+    if (isset($field_parent)) {
+      $form[$field_parent][$field_name_dependent]['messages'] = array(
+        '#markup' => '<div class="views-messages">' . $messages . '</div>',
+      );
+    }
+    else {
+      $form[$field_name_dependent]['messages'] = array(
+        '#markup' => '<div class="views-messages">' . $messages . '</div>',
+      );
+    }
   }
 
-  return $form[$field_name_dependent];
+  if (isset($field_parent)) {
+    return $form[$field_parent][$field_name_dependent];
+  }
+  else {
+    return $form[$field_name_dependent];
+  }
 }
 
 /**
diff --git a/tests/reference_option_limit.test b/tests/reference_option_limit.test
index 08fbf44..b7000b2 100644
--- a/tests/reference_option_limit.test
+++ b/tests/reference_option_limit.test
@@ -320,3 +320,105 @@ class ReferenceOptionLimitEntityreferenceTestCase extends ReferenceOptionLimitEn
   }
 
 }
+
+/**
+ * Test use of the module on a Profile2 entity.
+ */
+class ReferenceOptionLimitProfile2TestCase extends ReferenceOptionLimitEntityreferenceTestCaseBase {
+
+  /**
+   * Implements getInfo().
+   */
+  public static function getInfo() {
+    return array(
+      'name' => t('Profile2 entity form'),
+      'description' => t('Tests behaviour on Profile2 entities with entityreference fields.'),
+      'group' => t('Reference Option Limit'),
+    );
+  }
+
+  /**
+   * Implements setUp().
+   */
+  function setUp() {
+    parent::setUp(array(
+      'reference_option_limit',
+      'reference_option_limit_test_entityreference',
+      'profile2',
+      'reference_option_limit_test_profile2',
+    ));
+
+    // Create our creator user.
+    $this->user = $this->drupalCreateUser(array(
+      'edit own test_rol profile',
+    ));
+    $this->drupalLogin($this->user);
+  }
+
+  /**
+   * Test the functionality on a node create form.
+   */
+  function testProfile2Form() {
+    $user_id = $this->user->uid;
+
+    $this->drupalGet("user/$user_id/edit/test_rol");
+
+    // Get a country node.
+    $country_node = $this->getNodeByTitle('France');
+
+    $edit = array(
+      'profile_test_rol[test_rol_er_country][und]' => $country_node->nid,
+    );
+
+    $this->drupalPostAJAX(NULL, $edit, 'profile_test_rol[test_rol_er_country][und]');
+
+    // The AJAX post updates the content our assertions test against.
+    // Check each term: all the cities in France should be present; all the
+    // others should not.
+    foreach (reference_option_limit_test_entityreference_cities() as $city_name => $country_name) {
+      if ($country_name == 'France') {
+        $this->assertText($city_name, "The $city_name node was found in the form.");
+      }
+      else {
+        $this->assertNoText($city_name, "The $city_name node was not found in the form.");
+      }
+    }
+
+    // Get a country node.
+    $country_node = $this->getNodeByTitle('Italy');
+
+    $edit = array(
+      'profile_test_rol[test_rol_er_country][und]' => $country_node->nid,
+    );
+
+    // Change the country we have selected.
+    $this->drupalPostAJAX(NULL, $edit, 'profile_test_rol[test_rol_er_country][und]');
+
+    foreach (reference_option_limit_test_entityreference_cities() as $city_name => $country_name) {
+      if ($country_name == 'Italy') {
+        $this->assertText($city_name, "The $city_name node was found in the form.");
+      }
+      else {
+        $this->assertNoText($city_name, "The $city_name node was not found in the form.");
+      }
+    }
+
+    // Pick a city and save the entity.
+    $city_node = $this->getNodeByTitle('Firenze');
+
+    $edit = array(
+      // Use the most recent country node.
+      'profile_test_rol[test_rol_er_country][und]' => $country_node->nid,
+      "profile_test_rol[test_rol_er_city][und][{$city_node->nid}]" => 1,
+    );
+
+    $this->drupalPost(NULL, $edit, t('Save'));
+
+    // Load the profile.
+    $profile = profile2_load_by_user($this->user, 'test_rol');
+
+    $this->assertEqual($profile->test_rol_er_country[LANGUAGE_NONE][0]['target_id'], $country_node->nid, "The node has its country field value set.");
+    $this->assertEqual($profile->test_rol_er_city[LANGUAGE_NONE][0]['target_id'], $city_node->nid, "The node has its city field value set.");
+  }
+
+}
diff --git a/tests/reference_option_limit_test_profile2/reference_option_limit_test_profile2.info b/tests/reference_option_limit_test_profile2/reference_option_limit_test_profile2.info
new file mode 100644
index 0000000..3a241af
--- /dev/null
+++ b/tests/reference_option_limit_test_profile2/reference_option_limit_test_profile2.info
@@ -0,0 +1,9 @@
+name = Reference Option Limit Profile2 Test
+description = Test module for Reference Option Limit on Profile2 entities, using entityreference fields.
+core = 7.x
+
+dependencies[] = reference_option_limit
+dependencies[] = entityreference
+dependencies[] = node
+
+hidden = TRUE
diff --git a/tests/reference_option_limit_test_profile2/reference_option_limit_test_profile2.install b/tests/reference_option_limit_test_profile2/reference_option_limit_test_profile2.install
new file mode 100644
index 0000000..e7e462c
--- /dev/null
+++ b/tests/reference_option_limit_test_profile2/reference_option_limit_test_profile2.install
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * @file reference_option_limit_test_profile2.install
+ * Contains install hooks.
+ */
+
+/**
+ * Implements hook_install().
+ */
+function reference_option_limit_test_profile2_install() {
+  // Create a new Profile2 type.
+  profile2_type_save(new ProfileType(array(
+    'type' => 'test_rol',
+    'label' => 'Test ROL',
+    'weight' => 0,
+  )));
+
+  // Add both fields on the test_rol Profile2 type.
+  $instance = array(
+    'field_name'  => 'test_rol_er_country',
+    'entity_type' => 'profile2',
+    'bundle'      => 'test_rol',
+    'label'       => 'Country',
+    'widget'      => array(
+      'type'      => 'options_select',
+    ),
+    'display' => array(
+      'default' => array(
+        'label' => 'above',
+        'type' => 'entityreference_entity_id',
+      ),
+    ),
+  );
+  field_create_instance($instance);
+
+  $instance = array(
+    'field_name'  => 'test_rol_er_city',
+    'entity_type' => 'profile2',
+    'bundle'      => 'test_rol',
+    'label'       => 'Cities',
+    'options_limit' => TRUE,
+    'options_limit_fields' => array(
+      'test_rol_er_country' => 'test_rol_er_country',
+    ),
+    'widget'      => array(
+      'type'      => 'options_buttons',
+    ),
+    'display' => array(
+      'default' => array(
+        'label' => 'above',
+        'type' => 'entityreference_entity_id',
+      ),
+    ),
+  );
+  field_create_instance($instance);
+}
+
+/**
+ * Implements hook_uninstall().
+ *
+ * This is not necessary for tests, but it makes development of tests easier by
+ * allowing use of Devel module's reinstall tool to obtain a clean slate.
+ */
+function reference_option_limit_test_profile2_uninstall() {
+  profile2_type_delete(profile2_get_types('test_rol'));
+}
diff --git a/tests/reference_option_limit_test_profile2/reference_option_limit_test_profile2.module b/tests/reference_option_limit_test_profile2/reference_option_limit_test_profile2.module
new file mode 100644
index 0000000..2723f07
--- /dev/null
+++ b/tests/reference_option_limit_test_profile2/reference_option_limit_test_profile2.module
@@ -0,0 +1,8 @@
+<?php
+
+/**
+ * @file reference_option_limit_test_profile2.module
+ * Test module for Reference Option Limit tests with Profile2.
+ */
+
+// Drupal needs this blank file.
