The use of third party settings could really use better documentation and I'd be happy to help with that but first I need to understand it myself. :) So I'm posting my findings in the hopes of getting some clarification of how this all works.
In this comment , yched says:
It should be the entity form's responsibility to create the container for the "third party settings" entry, and place it in the form (weight, etc...). Then, having 3rd party modules add their elements in that container with a simple form_alter() is fine.
It seems like this has been implemented but possibly only for fields. If I form alter a field, I can add my own data to the form under "$form['field']['third_party_settings']['module_name']['data_name']" and it is automatically saved along with the field configuration.
From what I can tell, though, this only works for fields. In trying to make it work with the contact form, I noticed there is no existing third_party_settings element in the $form array. I tried adding it to the $form array in various places but it does not automatically save with the other form data.
The core content translation module uses "$form['field']['third_party_settings']['content_translation']['translation_sync'] = $element;" to do the autosaving of third party data on fields but then it uses "$config->setThirdPartySetting('content_translation', 'enabled', $value)->save();" when it wants to add third party settings to something that is not a field.
I have been trying to figure out what makes fields different but keep getting in over my head. Is this actually implemented differently for fields or am I just missing something? If it is different, was that intentional or is it unfinished or an oversight that the others don't have the automatic saving?
Comments
Comment #1
larowlanThere is a test in core that does exactly what you're after to a contact form, that should be a good reference point
Comment #2
MichelleThat test looks a lot like your lightening talk. ;)
Ok, so I got it working adding TPS to the contact form so that solves my problem (thanks!) but there's still the larger issue of documenting this and why it is different for fields than for other config entities. Any idea? I could document it as is but I'd like to understand why the difference.
Also, is there a reason for using #entity_builders for saving the TPS rather than #submit? I hadn't seen #entity_builders before your talk and I could find very little info on it. Content translation is doing it in the submit.
Comment #3
MichelleAdding a third thing that needs documenting: third party settings on base fields. I think I found the issue that allows it but I'm a long way from understanding enough to document how to use it and am especially confused by the lack of a UI to attach to.
Comment #4
larowlanYep I think I wrote it over in #2342551: Implement ThirdPartySettingsInterface in contact module for contact form config entity
Comment #5
jhodgdonI'm a bit confused here. Where is this documentation proposed to be added/improved?
If it's pages on drupal.org, then please go ahead and edit them, or else move the issue to the Documentation project. You can tag with "d8 docs" and "developer".
If it's stuff in Drupal Core files, the issue should remain here.
Comment #6
MichelleI was looking for some help from devs that have worked on core to understand this better so that I had the knowledge to document it. I guess there isn't going to be any more of that forthcoming so I'll go ahead and move the issue. I still intend to document this but I still don't understand all the pieces. I've moved away from this at work so will need to wait until I can scrounge up some of my own time to finish digging into this.
Comment #7
jhodgdonNo one but me really looks at issues in the documentation component, so. You'll be better off pinging people directly in IRC. Not sure who to ask, but you can ping one of the people in the know to figure that out.
Comment #8
larowlanfwiw the phrase "the core devs" creates barriers and implies there are different classes of contributors. We are all Drupal contributors. Please avoid it.
Can we work to turn the example in the contact module tests 'send me a pony' into documentation?
Comment #9
MichelleSorry for being old school. I changed my comment to be politically correct. ;)
As for the example, that's a good start but that's only one of the 3 ways that TPS works. And is also the one I understand the best. I'll write up a skeleton doc with everything I know and mark what I don't and see about finding some help for the stuff I don't. It might not be until this weekend, though. Work owns my brain this week.
Comment #10
mikejw CreditAttribution: mikejw at University of Adelaide commentedHi,
just wondering if this was ever completed - I am looking for some help on using TPS.
Cheers.
Comment #11
mikejw CreditAttribution: mikejw at University of Adelaide commentedOk in my case I wanted to add in the TPS into the field settings form... this is how it is done:
Obviously you will need a way to check that it is the right field in my case I just name them in particular way and I query the field_name.
Comment #12
MichelleI'm sorry, I haven't done this yet. The D8 project I was on launched and that was the last I worked on D8. :( I still want to do this but TPS aren't fresh in my mind anymore so it will take me time to really dive into it again and I don't know when I'll be able to do that. If I can turn it into a blog post, I can get some work time for it. That's not ideal as documentation, I realize, but it would at least get it all out there and could be turned into documentation from that.
Comment #13
mikejw CreditAttribution: mikejw at University of Adelaide commentedI am currently on a D8 project so it may be feasible for me to have a shot at writing the documentation. As far as I can see the previousnext lightning talk covers one part of it and what I have done above covers another part.
Comment #14
mikeryan+1 for actually documenting this, as I deal with #2613336: Convert migration_group to a third party setting.
Comment #15
geek-merlinComment #16
stanoreke CreditAttribution: stanoreke commentedPlease how do i retrieve the value the user selects? I want to be able to make some comparison based on the value selected in my template.twig file. I have set this in a custom module
E.g, {% set value = $block->getThirdPartySetting('helper_module', 'collapse') %}
Comment #17
MichelleUnassigning myself since I never got to this and it's been so long I don't remember how it works anymore. :(
Comment #18
geek-merlinHmm, puzzling with this too. As far as i can see,
@Michelle asked in the summary:
* core.entity_view_display.*.*.*::third_party_settings are a builtin of any config entity, defined in core.config_entity schema in drupal/core/config/schema/core.data_types.schema.yml and supported by builtin \Drupal\Core\Config\Entity\ConfigEntityBase::getThirdPartySettings
* OTOH core.entity_view_display.*.*.*::content.*.third_party_settings is defined in core.entity_view_display.*.*.* schema in drupal/core/config/schema/core.entity.schema.yml and *not* supported by a builtin config entity method
@Michelle asked in #2:
I think it is just more natural to
* prepare the entity content in #entity_builders
* store tne entity content in #submit
If this is not documented, it really should.
Hope this helpz.
Comment #19
AnybodyHi @axel.rutz and all others,
thank you very much for the discussion.
I still couldn't find any general documentation in TPS yet. Only this issue. What I'd need is first of all general information about TPS and what to (not) use it for.
General questions could be:
And perhaps others...
Who could answer that for a first documentation? I only recognized TPC in kint so far and I'm afraid of misuing them...
If there is a documentation page already, please link it here and close the issue.
Comment #20
nightlife2008 CreditAttribution: nightlife2008 commentedDaniel Sipos wrote an excellent tutorial on this:
https://www.sitepoint.com/drupal-8-third-party-settings-and-pseudo-fields/
Perhaps parts can be taken over for Drupal-Docs.
Comment #21
Pasquallehttps://www.heididev.com/how-alter-configuration-entity-data-drupal-8-or...
Comment #22
mandclu CreditAttribution: mandclu at Northern Commerce commentedI agree 100% that the third party settings system needs to be better documented. Some feedback on the most recently post links:
- The post in #20 took a very long time to get to the actual usage of TPS, it seemed to be focused on a very narrow case using entirely custom forms. The page was so loaded with ads that I had trouble scrolling through, and Chrome warned me of two separate embedded ad page that had crashed the browser
- The post in #21 was much more succinct, but specified the definition and use of a save handler, which isn't really necessary if you're just adding something into a field's config
The reference in #11 was perfect for me. When I needed to retrieve the setting with the code for my custom field, I only needed to do this:
Comment #23
stefan.kornI totally agree with @mandclu, especially in that #21 is an absolutely helpful (working) documentation that's straight up to the point and would surely make a good candidate for documentation on drupal.org as well, maybe additionally sorting out in which case it's necessary to use the entity_builders callback.
Comment #24
rick.kowal CreditAttribution: rick.kowal commentedThanks @mandclu for the TLDR; version.
In D8.9.1 for a content type form (ie /admin/structure/types/manage/*), I needed to add a submit handler to save the value:
function my_module_form_alter(&$form, &$form_state, $form_id) {
if ($form_id === 'node_type_edit_form') {
$entity = $form_state->getFormObject()->getEntity();
$form['third_party_settings']['my_module']['my_field'] = array(
'#type' => 'textfield',
'#title' => t('My Field'),
'#default_value' => $entity->getThirdPartySetting('my_module', 'my_field'),
);
$form['actions']['submit']['#submit'][] = 'my_module_submit_node_type_form';
}
}
function my_module_submit_node_type_form(&$form, FormStateInterface $form_state) {
$entity = $form_state->getFormObject()->getEntity();
$entity->setThirdPartySetting('my_module', 'my_field', $form_state->getValue('my_field'));
$entity->save(); //didn't work without saving here
}
To get the value in my twig:
function my_module_preprocess_node(&$variables) {
$type = $variables['node']->getType();
$node_type = \Drupal::entityManager()->getStorage('node_type')->load($type);
$variables['my_field'] = $node_type->getThirdPartySetting('my_module', 'my_field');
}
Comment #25
stefan.korn@rick.kowal: You should probably better use the "entity_builders" callback in form_alter
$form['#entity_builders'][] = 'your_module_node_type_builder'; (naming is up to you)
see link from #21: https://www.heididev.com/how-alter-configuration-entity-data-drupal-8-or...
That way no entity->save() should be necessary (which imho can lead to serious problems if used during the regular entity processing).
Comment #26
Anybodyas of #25
Comment #27
ebeyrent CreditAttribution: ebeyrent commentedThe part I'm struggling with is base fields on a custom entity type. I'm not using the Drupal UI; instead I'm using vuejs and need to set third party settings on base fields. Since form api isn't used, form_alter hooks doesn't help me much.
I would have thought something like this would work, but it doesn't:
Comment #28
BerdirThere are no third party settings for base fields. But you can still expose the field ui admin route for your entity type and then manage the third party settings there for the form display.