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
Comment #1
BerdirRenderable 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.
Comment #2
r_honey CreditAttribution: r_honey commentedYou 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"?
Comment #3
BerdirA $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.
Comment #4
r_honey CreditAttribution: r_honey commentedIt 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:
So,
1) isn't this a renderable array:
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.
Comment #5
BerdirWell, 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.
Comment #6
r_honey CreditAttribution: r_honey commentedWell, 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