I have a node reference field set to use a view for filtering which nodes should be able to be referenced, and when I edit a node with this field, I can set the reference as I'd like without a problem.

However, if I edit a node with a reference already set, and upload a file to a file field attached to that node (using AJAX), then the form loses the reference options (that were defined by my view). If I do a dpm() on the $form both before and after I upload or remove a file, I can see that the $form['reference_field'] array becomes empty, the #default_value is set to 0/null, and the #options array is empty, showing only the '- None -' option.

I'll try to find a fix for this, but it's aggrevating, as the site now requires people to remove the reference, save the node, upload the file, save the node again, then add the reference back in and save it a third time.

Comments

geerlingguy’s picture

Stepping through code in node_reference.module, I found that the function node_reference_potential_references() returns the proper set of nodes when the form is initially loaded, but once I do an AJAX operation on the form, the array field_list_parent:contains::0 empties.

geerlingguy’s picture

Digging further, it seems the $args are not passed as I was presuming, since references_potential_references_view() isn't receiving any $args to pass to the view when retrieving the view results.

I remembered I had set up my view to use a contextual filter (argument) of the nid, and I set the argument to provide a default value of the 'Content ID from URL' when the filter value is not available.

It seems that the view grabs the node nid from the URL on the initial form load, but after that, it seems the view can't get the nid because (I'm guessing) the URL would be the /*/ajax URL, without the nid anymore. Is there a way I could preserve that nid so it could be used even after the form is refreshed via AJAX? Could #1070622: Dynamic views arguments in node reference solve this problem?

geerlingguy’s picture

Doing a quick dpm(arg(0) . '/' . arg(1)); inside references_potential_references_view(), I found that the path on the initial node form load is node/1428, and after removing a file, it is file/ajax, confirming my suspicions in #2.

geerlingguy’s picture

For my needs, I simply did some extra checking inside a hook_form_alter(), and manually set the field value in the form if it was taken away during a form submission:

  // Store the list parent value if it isn't already set. @see Issue #344.
  if (!isset($form_state['storage']['field_list_parent'])) {
    if (!empty($form['field_list_parent'][LANGUAGE_NONE]['#default_value'])) {
      $form_state['storage']['field_list_parent'] = $form['field_list_parent'];
    }
  }
  // If it is set, re-fill it as the default value if there's no default value.
  else {
    if (empty($form['field_list_parent'][LANGUAGE_NONE]['#default_value'])) {
      $form['field_list_parent'] = $form_state['storage']['field_list_parent'];
    }
  }

This helped me get a node reference reset when a user would remove or add a picture to a form using an AJAX file field form.

nrahlstr’s picture

Hi geerlingguy,

We are seeing the same error...your post here has been very helpful to work around it!

Thanks!
Nathan

Chrosoes’s picture

Issue summary: View changes

I've had the same error and would love to correct the issue. I am unsure as to where I would place the code mentioned in comment #4. Where would I put that code? I am new to Drupal and really enjoying it, this has got me stuck.

Thank you in advance for any help.

idflood’s picture

I had the a similar issue. My problem was that my view has a contextual filter 'user id from url'. As pointed in #3 during the ajax call this doesn't work.

The workaround I used look like this:

function YOURMODULE_views_pre_view(&$view, &$display_id, &$args) {
  if ($view->name == 'YOUR_VIEW_NAME' && $display_id == 'YOUR_DISPLAY_ID') {
    if (arg(0) == 'user' && is_numeric(arg(1))) {
      $_SESSION['profile_active_user'] = arg(1);
    }
    else if (isset($_SESSION['profile_active_user'])) {
      $args = array($_SESSION['profile_active_user']);
    }
  }
}