According to hook_node_view API docs:

The module may add elements to $node->content prior to rendering. This hook will be called after hook_view(). The structure of $node->content is a renderable array as expected by drupal_render().

In my understanding, a form field defined as:
$form['myelement'] = array('#type'=>'textfield);
is an element that can be added to $node->content.

This works for textfields, trying to add custom fields in hook_node_view, but does NOT work for 'text_format'. I have spent hours debugging and stepping into Drupal to find that 'filter_process_format' (which is the default #process for 'text'_format', never gets called, and hence the 'text'_format' field does NOT show up on the rendered node.

e.g. in the following code:

function mymodule_node_view($node, $view_mode, $lang_code){	
	$node->content['eb_event_news_title'] = array(
									'#type' => 'textfield',
									'#title' => 'Message'
									);
	$node->content['eb_event_news_desc'] = array(
									'#type' => 'text_format',
									'#base_type' => 'textarea', // #base_type is optional.
									'#title' => 'Description',
									'#format' => filter_default_format(),
									);
}

The textfield renders fine on the node, but text_format is completely missing (due to #process not being called as said above).

My current workaround is to move these fields to a function:

function mymodule_mini_form($form_state){	
	$form['eb_event_news_title'] = array(
									'#type' => 'textfield',
									'#title' => 'Message'
									);
	$form['eb_event_news_desc'] = array(
									'#type' => 'text_format',
									'#base_type' => 'textarea', // #base_type is optional.
									'#title' => 'Description',
									'#format' => filter_default_format(),
									);
	return($form);
}

and then use drupal_get_form to get the fields and render them on the node:

//In hook_node_view
	$form = drupal_get_form('mymodule_mini_form', NULL);
	$node->content['eb_event_news_title'] = $form['eb_event_news_title'];
	$node->content['eb_event_news_desc'] = $form['eb_event_news_desc'];

I found a page on drupal.org API which said that my understanding of "renderable element" is correct, but I can no longer search that page out again.

Comments

Berdir’s picture

Renderable arrays and forms are not necessarly the same thing.

$node->content is not a form, it imho doesn't make much sense to place form elements inside it.

Not sure if it a bug, I guess at least the documentation should be improved.

r_honey’s picture

You might be correct, but doing a print_r on $node->content shows up CCK fields (i.e. Fields from D7 core) that are in a $form format. And stepping through Drupal while debugging this issue, drupal_render uses many of the properties (#pre_render etc.) from forms.

In any case, if a difference exists, it would be much useful to document how a $form array is different from a "renderable array" (Extensive Google search did not threw up anything).
And how to convert a $form field array to a "renderable array"?

Berdir’s picture

A $form array is a "renderable array". But not the other way round. Only forms are submitted, processed and validated.

So, the formatted fields are displayed as a renderable array, but they are not a form. Adding text_format thing to it therefore does not make sense (without doing it through drupal_get_form()) because there is nothing to which it can be submitted. In short, there is no < form > tag anywhere unless you use drupal_get_form().

I am not sure if there is good documentation about this.

r_honey’s picture

It still is murky ("renderable array" vs $form array field).
A $form array is a renderable array, that's fine, a renderable array is not a $form, that's also fine.

But hook_node_view docs say:

The module may add elements to $node->content prior to rendering....
The structure of $node->content is a renderable array as expected by drupal_render().

So,
1) isn't this a renderable array:

$node->content['eb_event_news_desc'] = array(
                                    '#type' => 'text_format',
                                    '#base_type' => 'textarea', // #base_type is optional.
                                    '#title' => 'Description',
                                    '#format' => filter_default_format(),
                                    );

2) What exactly is an "element" in the above docs extract? What's the difference between a "renderable array" and an "element".
3) The element in $node->content when printed appear as above $form arrays. Isn't this correct?
4) How come '#type'=>'textfield' work when added to $node->content, but not '#type' => 'text_format'?

I am not trying to say that formatted fields are a form. I am saying they are renderable arrays, so why don't they work with $node->content??
As for the submission is concerned, I am adding it to node, and its contents are Ajax submitted to the server, so explicit POST submission is not something I am worried about.

I have also mentioned my workaround in the first post, but clearing this up would surely avoid grief at a later critical time.

Berdir’s picture

Well, what can I say :)

4) Exactly because of what you said in the initial post. text_format relies on #process to work but #process is only called for forms. And it's only a form when it goes through drupal_get_form().

Forms are using the renderable array structure, but they add additional features on top of that. So it's really not a either/or question.

There is no clear, official distinction between these two terms at least not that I know of. And yes, it obviously needs better documentation and maybe this is even a bug. I don't know.

But then again, even if you are using ajax, you should still make it a real form because then you can rely on #ajax, this will also automatically give you a fallback for those without javascript.

r_honey’s picture

Well, maybe then, it looks like a bug with docs and not Drupal core. In any case, the work-around for using text_format from drupal_get_form works well....

I think this needs to be mentioned here too:
http://drupal.org/update/modules/6/7

Version: 7.0 » 7.x-dev

Core issues are now filed against the dev versions where changes will be made. Document the specific release you are using in your issue comment. More information about choosing a version.