Customising CiviCRM - Auto-complete for organisation_name in a Profile form

Published
2010-01-06 01:52
Written by

Recently someone asked about setting up an autocomplete in a profile where the person completing the form would be offered the name of existing organisations in the database. We have implemented this with a couple of different variations and I did promise to provide some information on this so here goes. I’ll try to explain a whole lot of ‘customising civicrm’ concepts but this isn’t a step-by-step recipe you’ll have to add a fair bit of technical know-how/ extra reading to flesh this out for your own purposes. I have added a recipe-type summary at the end just to sum up. Areas I will touch on are:

 

UPDATE - THIS BLOG IS OVER A YEAR OLD. AT THE TIME IT WAS ANTICIPATED THE PATCH WOULD GO INTO CORE. THIS HAS NOT HAPPENED AND IS NOT ACTIVELY BEING LOOKED AT. THE BLOG IS STILL VALID IN MANY AREAS BUT PROCEED WITH CAUTION

 

  • Customising a template
  • creating an autofill
  • REST calls & the API
  • Permissions & autofills/ API calls
  • creating an autofill using my custom API (note this is out-of date now - there are no immediate plans to introduce it into core)
  • Adding a ‘menu item’ (url) using a module (Drupal)
  • Quicksteps

An example of the Autofill is the team field here (please don’t fill in the form – it’s a live site!) where it can autofill entries from this profile Customising a template To modify the appearance or fields on a particular CiviCRM page you create a custom template (or tpl file) and put it in your over-ride directory. Generally you can identify which tpl file you need to edit by viewing the page source and searching for “.tpl” but in this case I was trying to edit the register page (ie. a page similar to this one ) and the relevant tpl file isn’t revealed in the code. After some effort to figure it out I resorted to asking on the IRC and found out the relevant tpl was Dynamic.tpl so I added a call to add in my custom tpl at the start of the file and added my autofill customisation to this file {include file="CRM/Profile/Form/Custom.tpl"} creating an autofill Xavier provided the clues as to how to use JQuery in a tpl file to create an autofill in this blog . The autofill needs a url that will return data formatted in JSON format. If you log into the CiviCRM sandbox and go to http://sandbox.civicrm.org/civicrm/ajax/rest?fnName=civicrm/contact/search&json=1&contact_type=Organization&return[sort_name]=1 you will get a JSON formatted list of the companies in the sandbox database. You can construct this URL within a tmpl file using the custom CiviCRM Smarty function crmURL as below where p=’the bit before the question mark’ and q=’the bit after the question mark’ and h=’the link text’ {crmURL p='civicrm/ajax/rest' q='fnName=civicrm/contact/search&json=1&contact_type=Organization&return[sort_name]=1' h=0} There’s a bit more syntax in Xavier’s blog & my comment at the bottom of it but that is the guts of adding an autofill to a template. More about autocompletes here REST calls & the API So how do you know what URLs you can feed in & get a JSON response? The API is written so that you can call any of the functions in any of the files in this directory from a URL and if the user has permission and the function array the response will be formatted as JSON. So, for example http://sandbox.civicrm.org/civicrm/ajax/rest?fnName=civicrm/membership_type/get&json=1 Returns all the membership types. If you remove the ‘json=1’ you will see an array is returned http://sandbox.civicrm.org/civicrm/ajax/rest?fnName=civicrm/membership_type/get (of course I picked an easy one – I can’t figure out how to call civicrm_contribution_get as neither of these work: http://sandbox.civicrm.org/civicrm/ajax/rest?fnName=civicrm/contribute/get http://sandbox.civicrm.org/civicrm/ajax/rest?fnName=civicrm/contribution/get) I suspect the filename / function name is not in line with the rules). You can even write a custom function, pop it in that folder and as long as it returns an array it will work like the standard ones … which is pretty much what I did. Permissions & autofills/ API calls You may have noticed before a couple of references to permissions and logging into the sandbox to see the URL. There are two levels of permissions. One is access to the API and the other is permissions within the functions themselves (e.g. the contribute_get function would check for ‘access civicontribute’) permissions. The other is the path related permission. CiviCRM defines paths & path related permissions in a bunch of xml files located here If you look down the bottom of this file: you will see civicrm/ajax/rest CRM_Utils_REST::ajax access CiviCRM In other words if you go to url http://sandbox.civicrm.org/civicrm/ajax/rest it will call the ajax function in CRM_Utils_REST if you have ‘access CiviCRM permission’ – ay, there's the rub. I can’t give my anonymous user access to view CiviCRM and they can’t see anything returned from the API / Rest call without it. Creating an autofill using a custom API So, what I did was write my own API and give anonymous users access to it. I added a function to CRM_Utils_REST that was exactly the same as the ajax one but I changed the permissions to allow anyone who could access profile listings and forms to access it. civicrm/ajax/rest/profile CRM_Utils_REST::ajaxProfile profile listings and forms I wrote the API to leverage the same code that determines whether the user has permission to view a given search profile. The logic was that if people could see information via this URL: then they could safely be allowed to view it through the API (if you don’t know how to expose data through a search profile read up on it under Sharing information here ) So, I created a Search Profile that was limited to a Smart Group of Organisations based on criteria that was important to us and used the API here (saved in my custom_php directory) along with the code here in my custom.tpl file to add the autocomplete. Note my profile gid is 5 {crmURL p='civicrm/ajax/rest/profile' q='fnName=civicrm/profile/search&json=1&gid=5&sort=sort_name' h=0} I put the autocomplete in the current_employer field and organization_name was returned from my profile. On a different site for a different customer I used the same code to autofill using values from a custom field which I exposed in the profile. Adding a ‘menu item’ (url) using a module (Drupal) In order to make my new URL ‘upgrade proof’ I created a Drupal module to add my URL to the civicrm_menu table whenever the table is re-built. Information on writing Drupal modules is here: but basically you need a .info file and a .module file (and to enable the module). I used the xml_menu hook Here is the content fuzion_api_profile/fuzion_api_profile.info (the info file just registers the module) ; $Id$ name = Fuzion Modules - API profile description = Adds a profile search api. Profiles available to search are available to be accessed by API package = CiviCRM dependencies[] = civicrm core = 6.x fuzion_api_profile/fuzion_api_profile.module <?php // $Id$ function fuzion_api_profile_civicrm_xmlMenu( &$files ) { $files[]=dirname(__FILE__)."//fuzion_api_profile.xml"; } ?> fuzion_api_profile/fuzion_api_profile.xml <?xml version="1.0" encoding="iso-8859-1" ?>

civicrm/ajax/rest/profile CRM_Utils_REST::ajaxProfile profile listings and forms

Summary Well that was a mission! I suspect the person who asked the question may have gotten more than he bargained for so here’s the quick steps

  1. customise the relevant tpl file. Call your own tpl with a javascript function similar to the one by Xavier.
  2. download the two files from here that are still current http://issues.civicrm.org/jira/browse/CRM-4637 into your custom php directory.
  3. Drupal users: create three files in your sites/all/modules directory in a folder called fuzion_api_profile. Name and content as per above. Make sure you enable the module
  4. Joomla users: create the three files & ask Brian what to do with them

Hopefully there is something in that lot that will be helpful to someone. Feel free to comment with all the quicker / easier ways I should have done it :-)

Filed under

Comments

Anonymous (not verified)
2010-01-08 - 00:07

Thanks Eileen,
This excellent write-up explains perfectly how to get the job done!

To have nicely sum up all the steps, and very much thank you from the lazy one that should have written it better in the first place ;)

X+

to write it all out properly so sometimes doing what you did - a quick braindump - is the best approach. Otherwise the information might not be available for a long time.

There is now (as of 3.2) a new plugin $('#current_employer').crmAutocomplete();

That should do that directly.
And a new chapter on the book on APIs
http://en.flossmanuals.net/CiviCRM/DevelopAPI