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.
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
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).
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.
@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 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 (https://github.com/farmOS/farmOS/blob/11cc36accf9590426d846fa9cc766de26892e84a/modules/core/location/farm_location.module#L14). 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).
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.
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 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…
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.
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).
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…