This is probably really basic, but I have Googled a lot and still can't find a good anwser.

When the user submits a node form for node type A, a second node of type B is programmatically created in a custom validation function. Now I want to set a node reference field in the node to be created (of type A) to point to the newly created node (of type B). What is the best way to do this?


otmoroz095’s picture

hi, may be it must be module "node reference create"? if i remember correct, this module have to create new node, if you didn't reference any another node.

Jaypan’s picture

Usually the node would be created in the submit function, not the validation function. Otherwise, you will get a new node being created multiple times if validation fails. Is there some reason why you are creating your node in the validation function and not the submission function?

Checkout my Japan podcasts.
oskarg’s picture

During validation of the submitted form, a credit check is performed based on a VAT identification number that is entered in the node form. If the corresponding company's credit rating is too low, validation fails. Otherwise, credit check information is stored in a node (of type B) for use later.

(This is part of a process where anonymous users can post content and get an account created for them at the same time.)

Jaypan’s picture

In that case, I would do something like the following. In the form, I would use this:

function my_form($form, &$form_state)
  // The form definition has been left out, with the exception of the element below
  $form['my_container'] = array
    '#type' = 'value',
    '#value' => FALSE,
  // Actual form definition would continue from here

The container will be filled in the next section:

function my_form_validate($form, &$form_state)
  if($new_node = my_custom_node_builder($form, $form_state)
    // The new node was created, so it's assigned to the container created in the form definition 
    form_set_value($form['my_container'], $new_node, $form_state);
    // The new node was not created, so there is an error
    form_set_error($form['some_field'], t('There was an error with this field'));

The above calls a custom node builder function:

function my_custom_node_builder($form, $form_state)
  // The code that builds the node is not shown. It would go here.
  // When complete, $node should either be a $node object, or be FALSE
  return $node;

The validation function will attempt to build the node. If the node is not properly created, an error is set on whichever field caused the problem, and the user gets sent back to the form with a validation error. If the node is properly created, the created node is inserted into the empty container created in the form definition. It can then be used in the submit function as follows:

function my_form_submit($form, &$form_state)
  $new_node = $form_state['values']['my_container'];
  $new_node_nid = $new_node->nid;

You now have the NID of the created node, which can be used in the submit function and attached to the original node. Since you are using nodes, the functions will likely be node functions rather than form definitions you are creating from scratch, but the idea is all the same.

Checkout my Japan podcasts.
oskarg’s picture

Thanks a lot! I have modified my code to reflect your advice. There is only one thing I can't wrap my head around, and that is how to actually set the node reference field in my _form_submit function.

I have tried something like

function yoodo_workflow_project_node_form_submit(&$form, &$form_state) {
	$cc_nid = $form_state['values']['credit_check_nid'];
	if($cc_nid !== FALSE) {
		// $form_state['node']->field_proj_creditcheck[$form_state['node']->language][0]['nid'] = $cc_nid;  // Not working
		form_set_value($form['field_proj_creditcheck'], $cc_nid, $form_state);   // Not working either

But this has no effect on the newly created node, i.e. the field value of field_proj_creditcheck is not set. At first I thought it was a permissions problem, but it was not.

I managed to set the field value using the following in the validation function

		$form_state['values']['field_proj_creditcheck'][LANGUAGE_NONE][0]['nid'] = $cc_nid;
		$form_state['input']['field_proj_creditcheck'][LANGUAGE_NONE] = $cc_nid;

Thanks again!

mikedotexe’s picture

^ That last code snippet after your EDIT worked for me. Thank you.

Hakuna Matata