Conditional Form Fields

Hi!
I’m making a custom module to try to understand how to work with farmOS. It’s a simple extension of the equipment module, adds a “Powered” Flag and a Config Entity to select the “Power source” from a list.
I would like to show the list of power sources if the powered flag is checked, and hide it if not.

The drupal form API has a way of doing it (Conditional Form Fields | Form API | Drupal Wiki guide on Drupal.org) but I don’t find any form controller (only quickforms) in farmOS.

Is there a way of doing this?
The module can be find at GitHub - c4ndel4/farm_equipment_power: Provides Power Sources to farmOS equipment

Later I would like to add a different asset reference in every log that has powered equipment selected (combustion->material, animal->animal, human->well, maybe I need a Worker asset related to the user). But all this module is for learning purposes, not a real case or something needed, so I don’t mind the things the module can do at the end, but the things I learned in the process of doing it.
Thanks

2 Likes

Hi @c4ndel4 you might check out the “Is Fixed” checkbox in Asset forms - this will conditionally display the “Intrinsic Geometry” field if it is checked (allowing an asset’s fixed geometry to be defined on the asset, rather than via movement logs).

Here is the logic for that - inside a hook_form_alter() in farm_location.module: farmOS/farm_location.module at 11cc36accf9590426d846fa9cc766de26892e84a · farmOS/farmOS · GitHub

Hope that helps!

1 Like

Thanks, I’ll try

1 Like

Well… I tried and failed…
I changed the “powered” flag by a “is_powered” boolean field in the bundle (I copied the “is_fixed” field in location). After some tries I found the correct _hook_form_alter function to override and inserted the code to manage this conditional behavior.
It worked, but not totally. The required state didn’t work, but I found a fix and resolved this problem.
But the “is_powered” boolean field don’t show the saved value when I edit the asset. Therefore power source list is not visible (but when you change the “is_powered” the list appears with the saved value selected).
The “is_fixed” field on location has some modifiers that I omitted in the “is_powered” field (‘default_value_callback’ => ‘farm_location_is_fixed_default_value’, ‘view_display_options’ => []). Maybe (surely) the problem has to relate with this, but I can’t find why.

The code is in this PR: Toggle power sources by c4ndel4 · Pull Request #3 · c4ndel4/farm_equipment_power · GitHub

If you are not busy with something important, please take a look. Thanks

1 Like

@c4ndel4 I’m not sure I follow entirely. I skimmed your code but it seems like there are a number of different things happening, so it might help if you walk me through it.

It helps for me if each Git commit represents a distinct change with a single purpose. Then we can look at each one independently and figure out why that particular piece isn’t working. If you would be willing to go through this a step at a time, I’d be happy to take another look.

I’m not used to work with git, at my workplace we use svn and only commit all changes at once at the very end. It’s also one of the things that I want to learn to use better, so I understand you ask me to do things as it’s suposed to be done.

I created a new branch and a new PR: Toggle powersources by c4ndel4 · Pull Request #4 · c4ndel4/farm_equipment_power · GitHub

Hope this time it’s easier to follow.

1 Like

Thanks @c4ndel4!

Which commit is not working as expected?

Some thoughts:

I think you can combine your two hooks into one in the “Add hooks to manage the visibility of the power source field” commit. Instead of separate hooks for “add” and “edit” forms (farm_equipment_power_form_asset_equipment_add_form_alter and farm_equipment_power_form_asset_equipment_edit_form_alter) you should be able to just use a single hook that covers both: farm_equipment_power_form_asset_form_alter, like we do in the farm_location module (farmOS/farm_location.module at 11cc36accf9590426d846fa9cc766de26892e84a · farmOS/farmOS · GitHub). You may want to add an additional condition to check that it’s an equipment asset type, although maybe not strictly necessary (because you’re already checking for your custom fields, which will only be on equipment anyway).

Can you explain these two a bit more?

I haven’t used this technique to change “required” state of fields myself - so I’m curious what you learned. I know above you stated:

The required state didn’t work, but I found a fix and resolved this problem.

Starting by the end:

If you define the field as “required” in hook_farm_entity_bundle_field_info, when you make it not visible and save you get an error from the server side php validation (you can define a default value and no problems). So we need to remove the required property on the definition and check the value on the client side.
The Drupal Forms API has the #states property that allows to play with the form elements in client side. All states (visible, required, checked, collapsed) should work the same way, but required wasn’t working and I was having a headache to solve the problem. Googling around found a Stackexchange post that helps 8 - How add conditional required field - Drupal Answers
The next commit is a copy-paste-adapt from that post. :slight_smile:
And it works!!! Well, it kinda works (as the field is “not required” the system ads a “N/A” option that I should remove/disable/make invisible). But when “is_powered” is false and the power source list is invisible you can save and pass the server validation and when is true and you don’t select any option you will get a validation message pre-post.

I understand what you say about the hooks, maybe the BASE_FORM was better, but the problem that remains is the reason to choose the other hooks.

The problem is with commit #2 Toggle powersources by c4ndel4 · Pull Request #4 · c4ndel4/farm_equipment_power · GitHub

The field “is_powered” is not showing or not saving the correct value when editing the asset. The field is always “off”. I used the edit_form hook to “echo serialize($form)” and see what data is processing and the “is_powered” field is saving a boolean 1 value when checked, but the control is not showing it. I think that I must transform that 1 into a TRUE at some point, but don’t know where. In the location example that you passed at the first time, there is a function farm_location_is_fixed_default_value that I thougth was only to initialize the value but must be doing other things… Or maybe is there another hook I’m mising…

1 Like

Thanks for sharing this! I imagine someone else may run into the same thing - so having it documented here may help. :slight_smile:

The problem is with commit #2 Toggle powersources by c4ndel4 · Pull Request #4 · c4ndel4/farm_equipment_power · GitHub

The code in that commit actually looks perfect to me. So maybe the problem is elsewhere…

The field “is_powered” is not showing or not saving the correct value when editing the asset.

Hmm - can you check to confirm if the value is being saved to the database?

In the location example that you passed at the first time, there is a function farm_location_is_fixed_default_value that I thougth was only to initialize the value but must be doing other things… Or maybe is there another hook I’m mising…

This shouldn’t make any difference. farm_location_is_fixed_default_value is only used because we want a bit of extra logic in determining the default value.

Ok, when I added the “is_powered” field I didn’t uninstall and reinstall the module, so the “is_powered” field is not created in the database … And now, I get an error when uninstalling because is trying to delete and inexisting field.

Thanks @mstenta, I think next time it will work.

1 Like

Ah ha! Great!

Yea that’s one of the “gotchas” with modules that provide fields - some code only runs when the module is initially installed.

Related: if this were a contrib module you were sharing with the community, the best practice is to create an update hook that will install new fields via update.php.

Well, first part is working. I extended an asset, now I want to extend a log, and then create a quickform and finally a report.
For this last step I didn’t find any documentation. How are farmos reports made? Is there a module that provide some report I can look at?
And talking about documentation, I think that in the farmos docs, in the section Development->Enviroment->Getting Started could fit a new Optional section on DISABLING THE CACHE (Disable Drupal (>=8.0) caching during development | Drupal.org). :exploding_head:

1 Like

farmOS doesn’t provide any standard tooling for building reports (yet), aside from core Drupal stuff like Views etc. The only thing farmOS provides currently is a farm_report that adds a “Reports” menu item to the sidebar. Your module can depend on that module and place it’s report pages under that menu item for consistency.

Beyond that you can do whatever you want! You’ll basically be building a custom Drupal page controller - so you have full freedom within that. Here is the Drupal.org documentation for controllers:

That’s not a bad idea. Although I might put it under a different path to keep the “Getting started” page as simple as possible. Not every form of development requires disabling caches… and there are a lot of different types of caches… so if we really wanted to cover it in the docs we should try to explain things in detail so folks can make the right decision based on their needs. Or we could just link to Drupal.org docs… :slight_smile:

2 Likes