Posted by RyanPrice on April 26, 2012 at 5:52pm
36 followers
| Project: | Field collection |
| Version: | 7.x-1.x-dev |
| Component: | Code |
| Category: | bug report |
| Priority: | normal |
| Assigned: | kscheirer |
| Status: | needs work |
Issue Summary
I have a few field collections that are included in a content type. When I create the a node of that content type, the data from the field collection areas do not save. There is no data in the database for them either. It's like they're skipped.
If I add them in after the initial creation, they show up fine.
Comments
#1
Anyone else have this issue? I'm a little surprised this isn't happening to others as well.
#2
I have the same issue. Very strange, it occurs only for one content type.
#3
@RyanPriceDotCa Do you have conditional_fields module ?
The issue I have is related to a required field that is normally handled by conditional_fields.
For me it is not a bug in field_collection but a problem of compatibility with conditional_fields.
#4
See #1582094: Incompatibility with Field collection for the explanation of my problem...
#5
I do have conditional_fields installed, but none of my field collections are dependent or dependee. I'll investigate this a bit further as well and leave a comment on your other ticket.
Thanks for posting here to let me know.
#6
You do not need to have a direct link between your field collection fields and the dependents or dependees. The problem is that when there is an error in the form, the field collection is not saved even if the error is not related to the field collection.
In function field_collection_field_widget_embed_validate (see code snippet below), it tests if there are errors in the form and not only the error coming from the validation of the field collection field. As we can have errors coming from required field hidden using conditional field, then the field collection is not saved. The trick is that conditional field module will manage (and clean) the errors relative to the dependents or the dependees but it is called at the end of the form validation process.
<?php
function field_collection_field_widget_embed_validate($element, &$form_state, $complete_form) {
// ....
// Only if the form is being submitted, finish the collection entity and
// prepare it for saving.
if ($form_state['submitted'] && !form_get_errors()) { // <---- HERE IS THE ISSUE
//...
}
}
?>
So I rewrite this function in order to check only the errors coming from the field collection validation. I'm really sorry but I am not familiar with the patch process and I unfortunatly do not have time before the end of the week so here is the code I use now (and that solves my problem...)
<?php
function field_collection_field_widget_embed_validate($element, &$form_state, $complete_form) {
$instance = field_widget_instance($element, $form_state);
$field = field_widget_field($element, $form_state);
$field_parents = $element['#field_parents'];
$field_name = $element['#field_name'];
$language = $element['#language'];
$field_state = field_form_get_state($field_parents, $field_name, $language, $form_state);
$field_collection_item = $field_state['entity'][$element['#delta']];
// Attach field API validation of the embedded form.
field_attach_form_validate('field_collection_item', $field_collection_item, $element, $form_state);
// Variable to store the validation errors for the field collection
// Errors are not directly set on the form to avoid compatibility issue with other modules
// such as conditional_fields
$field_collection_errors = array();
// Now validate required elements if the entity is not empty.
if (!field_collection_item_is_empty($field_collection_item) && !empty($element['#field_collection_required_elements'])) {
foreach ($element['#field_collection_required_elements'] as &$elements) {
// Copied from _form_validate().
if (isset($elements['#needs_validation'])) {
$is_empty_multiple = (!count($elements['#value']));
$is_empty_string = (is_string($elements['#value']) && drupal_strlen(trim($elements['#value'])) == 0);
$is_empty_value = ($elements['#value'] === 0);
if ($is_empty_multiple || $is_empty_string || $is_empty_value) {
if (isset($elements['#title'])) {
$field_collection_errors[] = array('elements' => $elements,
'message' => t('!name field is required.', array('!name' => $elements['#title'])),
);
}
else {
$field_collection_errors[] = array('elements' => $elements,
'message' => '',
);
}
}
}
}
}
// Only if the form is being submitted, finish the collection entity and
// prepare it for saving.
if ($form_state['submitted'] && sizeof($field_collection_errors) == 0) {
field_attach_submit('field_collection_item', $field_collection_item, $element, $form_state);
// Set the _weight if it is a multiple field.
if (isset($element['_weight']) && ($field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED)) {
$item['_weight'] = $element['_weight']['#value'];
}
// Put the field collection item in $item['entity'], so it is saved with
// the host entity via hook_field_presave() / field API if it is not empty.
// @see field_collection_field_presave()
$item['entity'] = $field_collection_item;
form_set_value($element, $item, $form_state);
}
// Add the errors to the form
foreach ($field_collection_errors as $field_collection_error) {
form_error($field_collection_error['elements'], $field_collection_error['message']);
}
}
?>
#7
My conditional fields are not saved though I don't have "Field collection" on my website.
1. For testing I disabled **all** the contrib modules, still not working.
2. I use conditional fields on profile and content type. On profile it is working ok, but not on content type.
3. Only one field is get saved from 10. I attached a picture of all the dependencies for you to see. The difference between those are their type. Field which works has a BOOLEAN type, whereas not working fields all has LIST(TEXT) type.
All fields are wrapped with very popular fieldgruop module, but now it is disabled.
#8
tested even more.
1. Tried the same thing on a different content type - not working.
2. if condition is "HAS value" and field is "LIST(TEXT) type, when things don't work. If I choose a different type, for example "checked", when things work.
But still not found a solution. I still need "has value" condition type. I guess I provided everything which is needed to reproduce a problem.
#9
Sorry, I thought this is a "conditional fields" issue queue :) I will create a seperate issue.
#10
Okay, so #6 needs to be turned into a patch. Not major though, since conditional_fields doesn't even have a release yet.
#11
I have a problem which is very simliar. If I save the initial node with the filled field collection data is not saved (but on another field collection it is). I even cannot save the data of this field collection on another update of the node.
EDIT: I think it is a conditional fields issue because the values are not saved if my fields have certain conditional fields state.
#12
This worked for me, thank you, herewith a patch as per #6.
#13
Thanks mckeen... I'm sorry I really did not find time to do it.
#14
Works for me. Let's roll this into a release please maintainers.
#15
The last submitted patch, field_collection_conditional_fields_save.patch, failed testing.
#16
Attempted the patch myself. This patch should be applied from 7.x-1.x-dev
#17
Thanks RyanPriceDotCa, works fine!
#18
Hello,
The patch appears to save the field collection but throws notice: Undefined variable: field_collection_errors in field_collection_field_widget_embed_validate() (line 1323
Thanks
EDIT: FWIW there appear to be times where $element['#field_collection_required_elements'] is undefined, which then cause field_collection_errors to not be initialized. I'm working with collections including dates, entity references, and text fields, all required fields in the collection. Field validation in collections is definitely problematic, and compounded with conditional fields.
#19
I don't think that's a good way to proceed, we really should set general form errors *and* we should only update the field-collection entity if the complete form passes validation.
I think we should be using another step in the process to set the field-collection item, e.g. use hook_field_attach_submit() instead and move the code from
if ($form_state['submitted'] && !form_get_errors()) {to it.
#20
I applied patch#16 to module, but it did not work. Is there any other solution?
I use field collection with conditional fields module.
thank you.
#21
Did this come to a resolution? I checked the latest dev code and do not see this patch implemented. Is this the direction that the developers are going with for the fix or is there a better way to address this?
#22
@SuperHoman:
See fago's comment in #19
#23
Well still seems unresolved, an issue which makes such a great module dysfunctional.
#24
#16 was essential for allowing field collections to save on our profile2 entities. Thank you!
#25
Problem persists with the save_draft module also!
#26
As of Field Collection version 7.x-1.0-beta4, the problem persists.
Patch #16 by RyanPriceDotCa works.
Thanks
#27
I have the same problem as well and can reproduce it at will. Patch #16 seems to work.
By the way this bug can even silently delete all existing field collection values from a node when using the edit form
#28
Patch #16 worked for me, thanks! Need a solution for core module though...
#29
I have also face the same issue. On add another field collection, the check box data is not save on first save. But work fine on next save. Any body have a solution ?
#30
I also had this same problem and comment #6 explained it well.
In my case, I am using the save draft module, content lock, and the conditional field modules. My field collections were not saving. I realized there was a problem when I would go to edit a node, and then click cancel. The Content Lock module would kick in and unlock the node, but it also spit out some errors about particular required fields in my form that I never saw when submitting a form. Once I fixed these required fields in my form on my node, then the field collection was correctly saving again. I am using Field Collection 7.x-1.0-beta5 and did not apply any patches.
So in summary, there is basically a (silent) error happening somewhere on your form and you need to fix it before field collection will save.
Hope this helps others, and maybe that patch above works.
#31
I must agree the current validation does create consistency issues, at least with the conditional_fields module which hides fields and those should not be validated.
The "field_collection_field_widget_embed_validate" function, however, does fire before "conditional_fields_form_validate" which results in this issue.
I tried to follow the suggestion in #19 but I failed to retrieve some variables used in the other function. I am not a good coder.
#32
@kunago #31: the plan to go is probably implementing #1781190: Field Collection saved on presave. i'm not perfectly sure which the best hook to use is NOR do i have much time. but feel free to pm me for assistance.
#33
I don't think the _presave issue has to do with this one - that's node operations, this form submit. I agree with fago in #19 - this code belongs in a _submit hook, not a _validate hook for forms. We should leave the real form errors alone - it's only field_collection's code that is saving data at the wrong stage.
Attached is a patch based on #19, moving the data saving code to a submit hook, not tested.
#34
The last submitted patch, 1549364-widget-validate-submit-33.patch, failed testing.
#35
After applying the patch in #33 the node with field collection is trying to get saved and after a while I get error.
Fatal error: Maximum execution time of 60 seconds exceeded in.
Uncaught exception thrown in session handler.
PDOException: SQLSTATE[08S01]: Communication link failure: 1153 Got a packet bigger than 'max_allowed_packet' bytes: UPDATE {sessions} SET ...
Sorry forgot to mention that I've got the conditional fields active with DEPENDENT and DEPENDEES.
#36
My patch clearly does not work - but I'm looking for suggestions and improvements :) I'll take another crack at it when I have a chance. You can set max_allowed_packet to a larger value (usually 16M is good) in your my.cnf file, but I don't think that will resolve the problem you experienced.
#37
#7 worked for me. I don't really get Fago's suggestion in #19 though. Why is the double step needed?