On a *_node_form with location collection turned on (non-cck field), the full location form array does not appear in the $form variable, which makes it impossible to alter. For instance, if I want to edit "Street" to say "Full Street Address" I can't seem to alter this. The $form['locations'] variable only contains information about what to hide or display and the weight.

From what I can tell the hook_locationapi returns the form elements for this array which is then in turn called in various other places, but for some reason the end result is that I cannot seem to modify the location form elements.

Perhaps I am just missing something obvious? Anybody else encounter this?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Dave Cohen’s picture

I'm struggling with this, too. As far as I can tell, this is on purpose. Instead, there's a hook_locationapi. This gets called with $op == 'field_expand', which gives you a chance to change some things. Not nearly as powerful as form_alter, though. I'm interested to hear what the developers had in mind for form_alter.

greg.harvey’s picture

Component: Code » Documentation

+1

Can't get hook_locationapi to work in my module and been unable to find any documentation. Not sure why this works this way - it seems a bizarre choice.

Any documentation forthcoming so we can change labels on Location forms in Drupal 6.x?? Just a few lines in this issue explaining how to do it would be great. =)

bob.hinrichs’s picture

We are encountering the same problems and I can't seem to find any info on how to make changes to the location fields. For one thing it seems to be impossible to get rid of that Additional field or the delete box from the cck location field, and it is not in reach of form_alter. I tried the API to no avail. Any pointers would be appreciated. Thanks for the (otherwise) great module, BTW.

YesCT’s picture

I think this issue was originally about the (non-cck) node locations, not about the cck locations. It's probably better to open separate issues that relate to the cck locations. Unless you can show how both have the same root cause. We can link to the new issue from here.

YesCT’s picture

greg.harvey’s picture

I think the fact that Location doesn't seem to use forms in the "normal" way is likely to be a problem across the board. =(

YesCT’s picture

I dont know much about forms, perhaps someone who does can propose a patch that identifies and corrects forms in location? Or, even just patches small instances of the problem?

I'm trying to find related issues and group them together.. I have a few tags that start "location them..."

greg.harvey’s picture

Sadly it will be nowhere near that simple. I think the module will need a re-write, not a patch, which I don't expect to happen. That's why I'm just asking for some developer support rather than reporting this as a bug (though someone changed it to a bug report) because I'm *hoping* they can suggest an alternative way to theme these forms.

There is another trick I haven't tried, and I've just remembered. There is a way to alter the rendered order of a form from template.php. This is worth a try, if someone gets a chance:

http://drupal.org/node/112358

YesCT’s picture

Issue tags: +Location theming

I see. Kind of. :)

Maybe if someone could post a small sample of the kind of things that would need a re-write, it might spur some more interest in this. (themable edit forms)

If a larger rewrite of much is needed in general, we should also open an issue for that. If anyone sees an issue like that already, link to it from here please. I'll tag this one too with general theming.

Dave Cohen’s picture

I worked around this problem with this change: http://drupal.org/node/381458#comment-1287362

Also to YesCT, I do not consider this a theming issue. Form alters are often more about functionality than theming, and they are done in modules, where changes apply to all themes.

YesCT’s picture

Dave, thanks. I tagged the example you posted #381458: remove Delete checkbox from user location form with the location theme edit form tag for now. Maybe someone can think of a better tag name. I was just trying to clean up the issue queue and link together related issues, that were not exactly duplicates. It seemed like people were asking for code changes that would allow them to theme things. Maybe allow alter forms would be a more accurate tag to describe these types of issues? Or another tag?

Thanks for your help.

YesCT’s picture

marked #323411: Gather Location info in new content as a duplicate of this issue [edit: fixed [#] notation]

ac00perw’s picture

This is definitely a bummer. I was hoping to make 'location name' an autocomplete field based on a table full of geographical places. My work-around was to create a new field with hook_form_alter() and populate the contents of location module's fields with it (name, add, city, state, zip, lat, long).

It would certainly be cleaner if I had access to location.

YesCT’s picture

ac00perw: can you post the code you used?

rc2020’s picture

On Drupal 6 version, line 1686, there's this code:

  // Tidy up the form in the single location case.
  if ($numforms == 1) {
    $form[0]['#title'] = t('Location');
    // If the user had configured the form for a single location, inherit
    // the collapsible / collapsed settings.
    $form[0]['#collapsible'] = $form['#collapsible'];
    $form[0]['#collapsed'] = $form['#collapsed'];
    //**HACK**//
    $form[0]['#prefix'] = '<div class="location_wrapper">';
    $form[0]['#suffix'] = '</div>';
  }

After the //**HACK**// I added this code to get a wrapper around the location box, allowing for extra theming. You can use this class (or make it ID) to force lengths and colors of form items. There are individual form items which you can add these attributes to. The http://api.drupal.org/api/file/developer/topics/forms_api.html/5 form helps out with alot of the things you can do with forms.

greg.harvey’s picture

Version: 6.x-3.0 » 6.x-3.x-dev
Component: Documentation » Code
Category: bug » feature

I've a feeling this should be moved to a Feature Request against Code. Also moving it to "dev" cos it is a feature request, after all. I'll do it. If anyone objects, switch it back.

@corona ronin, thanks for contributing but that's not really relevant to this issue. I think another issue should be started, with your code as a first patch for review, asking for a wrapper around location form data for easier theming. But it is not related to the re-write being discussed in *this* thread to facilitate using hook_form_alter() with the Location forms. (See #10 for why.)

I'd encourage you to start that issue. That would be cool. =)

greg.harvey’s picture

Title: Location fields not available for form alter » Make Location form fields available to hook_form_alter()

Hmmph, should've re-titled too. =)

rc2020’s picture

I don't know if anyone has gone to the workaround at #10, but Dave Cohen did find an effective solution to this problem, and I have gotten the fields to be themeable in a module file. Thanks Dave!

zmove’s picture

Hmmm,

I use CCK location, and I don't know how to alter the forum too. I need to change the province autocomplete field for a dropdown.

Using hook_form_alter, there is no way to alter the form, it's a "location_element" type form and I don't know how to alter it.

Any help / documentation would be appreciated.

geerlingguy’s picture

I'm trying to simply make the fieldset collapsible... unfortunately there's no option for that in the field settings through CCK, and I can't figure out how to do so through _form_alter()

greg.harvey’s picture

You can't currently! That's the point of this thread... =/

minhtao’s picture

I just share this in case someone is still looking for an answer.

As many, I could not alter directly the location form. What I did was to alter the "#after_built" property:
$form['field_profilelocation'][0]['#after_build'][] = 'after_built_function';

then I can alter the element:
function after_built_function($element, &$form_state){
$element['postal_code']['#required'] = true;
}

I hoped that helps. This solution helped me for what I had to do.

rc2020’s picture

Status: Active » Fixed

Found a solution:

You can use form_alter if the module invoking form_alter is called after location.module, meaning if your modulename is alphabetically after L.

So if your module calls alpha_form_alter() - it will have no effect on $form['location'] and subsequent fields.

However, if your module is called M or lower, it will.

So if your module is called tango_form_alter() - you'll see the $form['location'] object in the $form array. Just pass $form through devel's dsm() function dsm($form); and you'll see it there, can theme and modify to your heart's content.

It is my understanding the alphabetical title of the module affects form weight. Thus, if you use a module and set the weight to be higher than location.module, this could also work - but I'm not 100% sure of this as I just did it by title.

Happy theming!

Making as fixed.

YesCT’s picture

I think there is also a way of just changing the weight (without changing the name of the module)... for example on a different project, I needed my module to be able to "go after" the organic groups module, so I used this code in mymodule.install

function mymodule_enable() {
  // Get the weight of the og module.
  $weight = db_result(db_query("SELECT weight FROM {system} WHERE name = 'og' AND type = 'module'"));

  // Set this module's weight to the og's module's + 1 to make sure its hooks
  // are invoked in the right order.
  db_query("UPDATE {system} SET weight = %d WHERE name = 'mymodule' AND type = 'module'", $weight + 1);
}

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

greg.harvey’s picture

Status: Closed (fixed) » Active

Wait a second... this isn't "fixed"... it's hacked around. The issue still stands to make Location properly use the form API so hook_form_alter can behave normally, surely? =/

rc2020’s picture

@grev.harvey -

How is this a hack? Changing module weight and or using alphabetized custom module titles after L for location makes them available to form_alter().

I mean, I guess the ideal would be for the location object to always be accessible in the $form array...but this solves the problem without having to hack contrib modules or perform any type of additional work.

Just create a module with a name further down the alphabet than "L."

I mean, perhaps that's not good enough for everyone but it's a clear, simple, solution that works...no?

greg.harvey’s picture

It's a hack because you have to hack at the system table to make it work. It's not a bad hack, but a hack it is, nevertheless! ;-)

I'm not against it at all, it's a good interim solution, but it absolutely is not a "fix" for the issue title.

I mean, I guess the ideal would be for the location object to always be accessible in the $form array

Exactly! This issue should be fixed and closed once a patch allowing that is committed, IMHO. Though your solution is an excellent stop-gap.

EDIT: Thinking about it, it wouldn't be a hack if a patch to location_install() was supplied changing the weight of Location in the system table to something like -1000. If we pull Location down in the process order on installation, and it has no other nasty side-effects, that would be a fix I think. Worth a try! If that works, it's a clever solution to an otherwise ugly problem.

greg.harvey’s picture

Status: Active » Needs review
FileSize
1.03 KB

To that end, here's a patch which should apply to 6.x-3.x-dev. I think this will need EXTENSIVE testing before it can be committed, as there could potentially be all sorts of issues - but if it plays out that there are none, this would serve as a fix. =)

Dave Cohen’s picture

I think the point of this issue is...

Location fields are difficult to alter in hook_form_alter, because the 'location' element expands into many other elements when the form is built.

And the solution is...

Use the form api "#after_build" feature. This way your callback can alter the location fields, after they are expanded.

In short, use "#after_build" and not hook_form_alter, for location elements.

I'm not sure why this issue was brought back from closed status.

YesCT’s picture

I dont know that changing the weight to -1000 is a good idea... wouldn't all modules try and do that?

lhernon’s picture

subscribe

greg.harvey’s picture

@Dave - it was never closed, it was marked fixed in a post that didn't fix anything. =/

If someone wants to explain this fully, explain why no change to the Location module is required (maybe point to some docs or something) and mark this "by design", then I'm fine with that - but please can we have a real and clear resolution to this, in this thread, so people don't open new ones!

YesCT’s picture

perhaps we close this one, and open a new issue: "document using #after_build and not hook_form_alter, for location elements" ?

John Carbone’s picture

Got that afterbuild thing going. I needed to alter the country list for a very simple change. Note that this change simply overrides the name of "NOT LISTED" to something else, nothing more; but you could use this to make other changes as well, I would imagine.

function MYMODULE_form_alter(&$form, $form_state, $form_id) {
  if ($form_id == 'MYNODETYPE_node_form') {
    $form['#after_build'][] = 'MYMODULE_SOMETHING_MEANINGFUL';
  }
}

function MYMODULE_SOMETHING_MEANINGFUL($form_element, &$form_state) {
  //note that I only have one location on this node type
  $form_element['locations'][0]['country']['#options']['xx'] = 'International';
  return $form_element;
}
johnnybgoode’s picture

This worked for me, I was able to add and autocomplete_path for a textfield and change another textfield to a select list with options.

Posted by minhtao on March 25, 2010 at 8:58pm

I just share this in case someone is still looking for an answer.

As many, I could not alter directly the location form. What I did was to alter the "#after_built" property:
$form['field_profilelocation'][0]['#after_build'][] = 'after_built_function';

then I can alter the element:
function after_built_function($element, &$form_state){
$element['postal_code']['#required'] = true;
}

I hoped that helps. This solution helped me for what I had to do.

_randy’s picture

This works to set something in the form elements -- However I can't disable the elements using #disabled.

Example:
$element['postal_code']['#disabled'] = true;

This does not work. Any ideas?

EDIT:

Found the solution:

$form_element['locations'][0]['city']['#attributes'] = array('disabled' => 'disabled');

alexverb’s picture

I'm trying to use the "#after_build" feature to add "#ahah" to a location_element. With a form_alter it works out of the box. Through after_build it doesn't seem to react to a change. Can anyone verify that #ahah doesn't work through after_build?

John Carbone’s picture

Just some thoughts on #38. I'd look at how location is doing that sort of thing now with switching the options for states based on country. I think it's all javascript if I remember correctly. AHAH is notoriously a pain, in my opinion. I'd look for other options rather than trying to use it for this.

podarok’s picture

Version: 6.x-3.x-dev » 7.x-3.x-dev

all feature requests should be rolled against latest 7.x-3.x-dev and after commit can be backported to 6.x branch

Status: Needs review » Needs work

The last submitted patch, 378622-location_system_weight.patch, failed testing.

mexicoder’s picture

Think there has been a lot of other relevant discussion on altering the location form on this thread. Unless there is full hook_form_alter access, using #after_build or hook_location_element_alter as discussed in that thread seems a lot more elegant than modifying the location module weight IMO. They have worked well in my use cases anyway.
I'd also suggest that if we were to be looking at altering module weights on the 7.x-3.x-dev release it would make much more sense to alter the custom module through an install file rather than the main location module.

coolestdude1’s picture

Component: Code » Documentation

Why not just use hook_module_implements_alter.
This function allows you to reorder hook implementations after they are loaded from the cache table.

We can either implement the hook_module_implements_alter inside of the location module and make it the very first implementation (ugly) or just document within this issue that modules seeking to alter location after the hook_form_alter in location_node.module need to be the last available alter

Like this

function MODULENAME_module_implements_alter(&$implementations, $hook) {
  if ($hook === 'form_alter') {
      $implementation_copy = $implementations['MODULENAME'];
      unset($implementations['MODULENAME']);
      
      // Insert the implementation after all other implementations.
      $implementations['MODULENAME'] = $implementation_copy;

      // you can also use this function to reorder implementations based off of other modules
      // be sure to add proper if statements to detect your module is available for reordering unless you like watchdog statements :P
    }
  }
}
Lukas von Blarer’s picture

Issue summary: View changes

Would be nice to get this working...

mexicoder’s picture

@Lukas von Blarer did you try using #after_build?

DrCord’s picture

#35 worked for me, using #after_build. I was using profile2 and the location field was buried in that, so this seemed to be the only way to get at it. I had previously tried adjusting the weight of my custom module to higher than the location module, with no success.