SugarCRM: relate field passing default values to pop-up select form

Note: This article needs some pictures, which I will do in good time.

These are notes on how to set up a pop-up select form on a relate field in SugarCRM 6.5 to default to a value from the parent form.

So for example, you have a module Job Applications, and each application is made by a Contact. The contact has a number of CVs uploaded in the CV module. In the application, a relate field allows one of the CVs to be selected as relevant to the application. That relate field will pop up a search form for CVs, and by default will list all CVs on the system. What I would like it to do, is to limit the CVs to just those connected with the Contact who is connected with the Job Application being entered.

In the Job Application edit form we have a Contact selection field (this is a relationship – each Job Application has one Contact). A similar relationship exists for CVs – each CV has one Contact, an each Contact can have many CVs. We don’t have a full relationship between the CVs and the Job Applications – a simple relate field is good enough for our purposes.

So, you edit a Job Application for a Contact, click on the “selected CV” button on the form, and then will get a popup form giving you a list of CVs for that Contact, to choose from.

Now, a few notes on how far we want to go with this. Firstly, we just want this to be quick and efficient for the users. We are not trying to limit the CVs only to those of the job applicant. Yes, that would be nice, but is another level of customisation for another day. It is also worth noting that I am dealing with custom modules under development here, so I am editing the core files of those modules. Applying this solution to any of the standard modules would involve putting the changes into the custom/Extensions area of the CRM.

The Approach

When a pop-up search form is used in SugarCRM, it can be be passed initial values to go into the form fields. These are passed as GET parameters of the form {field-name}_advanced. The field name could be something simple like contact_name, assuming it is a simple field. It could be a more complex name if it is part of a relationship, as it is in this case (the Contact for a CV is in the relationship between the CV and the Contacts modules – the Contact is not stored in the CV module main tables at all).

Whatever the field name is, you will need it. Take a look at the source of the pop-up search form and the field name will be in there. Put “_advanced” onto the end of the name, and that will be the GET parameter that needs to be passed into the pop-up form when it is invoked.

So, where does the value for this parameter come from, and how do we get it into the pop-up form URL?

This is all done in the edit form metadata for the relate field. In my Job Application module, this metadata is defined in:

modules/ACAD_JobApplications/metadata/editviewdefs.php

If you have edited the module using Studio or are dealing with a standard module, then you will need to locate the appropriate upgrade-safe metadata file. Here is my definition for the related field:

array (
0 =>
array (
'name' => 'selected_cv',
'studio' => 'visible',
'label' => 'LBL_SELECTED_CV',
),
},

What we can do is add some new display parameters to this field. The parameter we add is called “initial_filter”, and SugarCRM will add the value of that to the URL when the pop-up search form is invoked. This is what it looks like in its basic form:

array (
0 =>
array (
'name' => 'selected_cv',
'studio' => 'visible',
'label' => 'LBL_SELECTED_CV',
'displayParams' => array(
'initial_filter' => '&my_field_advanced=some_default_value',
),
),
},

Adding that will pass “some_default_value” into a field called “my_field” on the pop-up search form. In the main edit page, that intial_filter string will be quoted (“) then passed to the pop-up form function as a parameter. It is possible to insert JavaScript into that string by closing the quotes, and that is a technique we will take advantage of.

First it is worth looking at where some_default_value is going to come from. In the main edit form we have a field that has the data in that we want to pass on to the pop-up search form. There are two ways to get at this data:

  1. At the time the edit page is generated.
  2. At the time the “select CV” button is pressed.

In the first instance, the value will be the value that comes out of the database. So in this case it will be the contact name when you first edit the job application. If this is a new job application, then there will be no contact name, and so the pop-up will not start with an specific contact by default. Even if you then select a contact in the main edit form, until you save the record, the pop-up search form will not know about that contact.

To get at the contact name (or the value of any other field) in the form, we take advantage of Smarty syntax. The string passed to initial_filter is treated as a Smarty template, and so you use Smarty code within it. To set my_field in the pop-up to the value of the field contact_name, you would use this:

'initial_filter' => '&my_field_advanced={$fields.contact_name.value}',

However, we do need to be a little cleverer than that. Since that contact name will passed as the value of a GET parameter, we need to ensure it is URL-safe, so special URL characters are appropriately escaped. This is done in Smarty like this:

'initial_filter' => '&my_field_advanced={$fields.contact_name.value|escape:'url'}',

Alternatively (or perhaps more correctly):

'initial_filter' => '&my_field_advanced={$fields.contact_name.value|urlencode}',

There is more escaping to be done. Because this string will appear on the edit form page as a JavaScript string that is quoted with “double-quotes”, we must make sure it is escaped for JavaScript too:

'initial_filter' => '&my_field_advanced={$fields.contact_name.value|escape:'url|escape:'jacascript'}',

Now, there is a problem here – or perhaps it’s not. The value of $fields.contact_name.value is automatically HTML encoded. That means quotes are converted to " entities and some other special characters are converted to entities too. Since this string is appearing in JavaScript and going out to a URL, we really don’t want it to be HTML encoded. However, the pop-up search form seems to cope with that HTML encoded data; I suspect it does a html_decode() on its parameters “just in case”. Personally I would prefer not to have encoding or escaping that is not appropriate, and there may be a way to tell this mini-Smarty template not to do that encoding, but I don’t know how that would would work.

The other approach to obtaining the field data to pass to the pop-up form, is to pick it off the current page using JavaScript right at the last moment. One advantage of this, is that the contact name can be set or changed in the Job Application edit form, and the pop-up CV search form will see that name every time.

Adding JavaScript to extract a field value from the current edit form is done like this:

'initial_filter' => '&my_field_advanced="+document.getElementById("contact_name").value+"',

Note we break out of the quoted string with a “, then append the JavaScript, then drop back into the quoted string with a final ” at the end.

We also need to think about URL escaping here:

'initial_filter' => '&my_field_advanced="+encodeURIComponent(document.getElementById("contact_name").value)+"',

However, JavaScript escaping is not needed, as we are not creating any quoted JavaScript strings in the page containing data; the JavaSscript that is generated only contains instructions.

So that’s it. We went for the second method as it was more flexible and made sense when new Job Applications were created from the start. Taking all the above, the full field that appears in our edit form metadata is:

array (
0 =>
array (
'name' => 'selected_cv',
'studio' => 'visible',
'label' => 'LBL_SELECTED_CV',
'displayParams' => array(
'initial_filter' => '&contact_name_advanced="+encodeURIComponent(document.getElementById("contact_name").value)+"',
),
),
},

So the CV search pop-up form now has the job applicant contact name in it by default. You still need to hit the search button to bring back the list of CVs for that contact, but at least you don’t need to be copying and pasting or typing up names between forms.

Special thanks to Marian Dobre for the final pieces to the puzzle in solving this little problem.

12 Responses to SugarCRM: relate field passing default values to pop-up select form

  1. Marian Dobre 2013-03-28 at 13:44 #

    Congratulations for this complete and useful tutorial.

    It is an inspiration for me 🙂

  2. jasonjudge 2013-03-29 at 14:46 #

    Thank *you* 🙂 Your blog has been very useful over the years. All I am doing here, is trying to document what I have done, so that I can remember next time I need to do it. Hopefully it will be useful to others, and hopefully people will point out its flaws, limitations, and inevitable improvements.

  3. Maybray Digital 2013-08-01 at 00:03 #

    Very good article. However, isn’t it easy to just define a “relate” field in “Studio”?

    • Jason Judge 2013-08-01 at 00:23 #

      There are so many different places to create the same, or similar, properties in SugarCRM. Each have their downside, in particular when making changes to modules.

      The module builder will blindly delete most custom changes to try to make to a module through the code. Studio will delete *some* of the changes you make manually. What gets obliterated when you save a change in Studio can be difficult to tell in advance.

      From what I remember (and I could be wrong), this was the case here. Making changes in the code (that cannot be done through studio) resulted in those changes be lost when going into Studio to make other changes. It is all rather a mess IMO, but it’s a mess we have to live with and work around.

  4. Andy 2013-09-27 at 14:05 #

    Most excellent post!

  5. Stephen 2013-11-19 at 14:21 #

    This article seems like exactly what I am looking for, but it refers to the pop-up for a ‘relate field’. Is there a way to apply this approach on the details screen when clicking the ‘select’ option from a drop-down on a sub-panel. For example, if I want to relate a contact to an account but want to filter the contacts that pop-up in the list to just a particular state or country (for example)?

    Also, does your example apply to 6.5+ or to an earlier version?

    • Jason Judge 2013-11-19 at 14:40 #

      This is working on a 6.5 instance.

      The technique aught to work in the way you describe. I can’t tell you off-hand which metadata scripts you need to change, or which front-end element selector you will need to use to fetch the state or country. The innards of SugarCRM has grown into a right tangled mess over the years, and finding what needs to be changed tends to turn into a trial-and-error search.

      But the technique is there, essentially add JS to the “select” button so that when the button is pushed, it reads a form element from the page and adds it to the popup window as a parameter to restrict the initial selection.

  6. Bob Caverly 2015-11-06 at 23:25 #

    I like the filtering you describe – nice article! I have related problem which you might be able to help with or suggest options.

    I want to add a relate field on a custom module that points to the Documents module – that much is easy. 🙂 (Though I do want to use you technique to apply filtering!) My problem is that the Document to be “related” may not have been created yet! I need a way to add a “New Document” button either on the Search pop-up – or on the Edit view where the relate field is located, that would then open a pop-up or quick create style form to create/upload a document and then on save populate the relate field accordingly.

    To make it more interesting – I need to repeat this pattern about a dozen times (for different documents) within the same module/Edit page.

    Any help you can provide will be greatly appreciated!

    • Jason Judge 2015-11-07 at 09:35 #

      I’ve not touched this stuff for a few years (I try to avoid it, because the SugarCRM code base is fragile and frustrating to extend, especially when not working on it full time) so I’m probably not the best person to ask about how to create a child record while editing a parent.

      Maybe someone else reading this can help?

  7. Rob 2019-08-08 at 16:14 #

    I know it’s been ages but big thank you for this detailed write up, will use for the suitecrm, hopefully it will work

  8. om kumar 2020-02-20 at 06:03 #

    Hi Guys, I have a question
    I have multiple values for the same field

    array (
    0 =>
    array (
    ‘name’ =>’csr_c’,
    ‘studio’ => ‘visible’,
    ‘label’ => ‘LBL_CSR’,
    ‘displayParams’ =>
    array (

    ‘initial_filter’ => ‘&id_advanced=’.$id,
    ),
    ),
    1 => ”,
    ),

    Here $id contain multiple value which is coming in the array.
    If $id has only 1 value then it’s working perfectly but when it contains more then one value then it is not working.
    Any advice will be greatly appreciated!

Leave a Reply