Adding autocomplete in a profile

Published
2009-03-24 14:37
Written by
A quick braindump: Profile are a great way of simplifying the interface and provide more focussed forms, but some of the goodies of the normal edit form are gone. For instance, the employer isn't anymore an autocomplete field. luckily, with the REST interface and a jquery autocomplete plugin, that's a few lines to add to make it work: add on the templates/CRM/Profile/Form/Edit.tpl
{if $session->get('userID') > 0}
{literal}
  
{/literal}
{/if}
In this example, I retrieve the name of the organisation, its country and I filter them to take only the organisations that are a member of the group 4 experiment with contactUrl param, you can retrieve more or less all the fields and add extra criterias.

Comments

I don't think it's Drupal's fault. You've got to use <pre> tags or better yet use something like the GeSHi filter:

http://drupal.org/project/geshifilter

Hi Xavier,

I just tried this - I had thought I could just paste your text (minus the group criteria)
below the single existing line in edit.tpl & get the result described but the box doesn't autocomplete.

Is there something else you have configured?

Replacing this crmURL p=' with the hard coded path made it work - is it a clean urls vs non clean urls thing? (mine aren't clean)

Works:
http://localhost/classes2.2/civicrm/ajax/rest?fnName=civicrm....

Generated by your code (doesn't work)

http://localhost/classes2.2/index.php?q=civicrm/ajax/rest?fnName=civicrm...

Thanks to this post I have implemented an autocomplete based on the code. I created a separate tpl file which I call from dynamic.tpl to add the box to the new user registration and user edit screens.

A couple of differences I thought I'd point out.

1) my version is presented to an anonymous user & is based on a profile search api which I have submitted for consideration and essentially makes any information that an anonymous user could access through a profile available to an anonymous user via an api/ REST call. This also allows me to limit results to a civicrm group.

2) A check for whether the current employer field is present since this will be called by all profiles

3) mustMatch:1,matchContains:1,multipleSeparator:"~", - this sets the autocomplete field to ONLY accept values returned by the API query. - multipleSeparator = ~ because the default (comma) legitimately appeared in some of our results. (not sure if matchContains affects the outcome)

4) if ("is_error" in data) { return []}; - converts output from REST call to an empty response. (ties in with using mustMatch)

5) obviously changes around the variables that I was interested in

{literal}

jQuery(document).ready(function($)
{
var contactUrl = {/literal}"{crmURL p='civicrm/ajax/rest/profile' q='fnName=civicrm/profile/search&json=1&gid=5&sort=sort_name' h=0}"{literal};
if ($("#current_employer").length > 0){
$("#current_employer").autocomplete( contactUrl, {
dataType:"json",mustMatch:1,matchContains:1,multipleSeparator:"~",
extraParams:{organization_name:function ()
{ //extra % to force looking to the data typed anywhere in the name
return "%"+$("#current_employer").val()+"%";}
},
formatItem: function(data,i,max,value,term){
return value ; //display the organisation name
},
parse: function(data){ //reformat to something the plugin expects
if ("is_error" in data) { return []};
var acd = new Array();
for(cid in data){

acd[acd.length] = { data:data[cid], value:data[cid].sort_name, result:data[cid].organization_name };
}
return acd;
},
width: 500,
selectFirst: true
});
};
});

{/literal}

The above code doesn't work in CiviCRM 3.1.5, but with a few small changes, it does. I removed the country from the returned data, but aside from that, it works the same. One issue with the above code is that this blog by default removes <script> tags, so they got lost in the original post. To get them to stay, you must use &lt;script> Also spaces get removed, so the code is a bit ugly. :(

Yes, you just need to add this code to the template. In my case I added it to templates/CRM/Event/Form/Registration and it's working on my event registration page.

Here's the code:

{if $session->get('userID') > 0}
{literal}
<script>
jQuery(document).ready(function($) {
var contactUrl = {/literal}"{crmURL p='civicrm/ajax/rest?fnName=civicrm/contact/search&json=1&contact_type=Organization&return[sort_name]=1'}"{literal};

$("#current_employer").autocomplete( contactUrl,
{
dataType:"json",
extraParams:{'sort_name':function () {
//extra % to force looking to the data typed anywhere in the name
return "%"+$("#current_employer").val();}
},
formatItem: function(data,i,max,value,term) {
return value;
},
parse: function(data) { //reformat to something the plugin expects
var acd = new Array();
for(cid in data) {
acd[acd.length] = { data:data[cid], value:data[cid].sort_name, result:data[cid].sort_name };
}
return acd;
},
width: 500,
selectFirst: true
});

});
</script>

{/literal}
{/if}

Note also that here http://en.flossmanuals.net/CiviCRM/DevelopAPI are more details about how this will work in CiviCRM 3.2, i.e. much easier. :)