Applying Initial Filter For Relate Fields and Relationship fields In Sugar 7.x

In this article I will be explaining how to add Initial filters for Relate fields in Sugar 7.x.
Initial Filters are used to set a filter automatically whenever you open a Look-up Search to select a record in Sugar.This will make the job of selecting the record(s) more easier to the user as the system will automatically filter out the records which are not required.

Note: Here is the documentation provided by Sugar for creating initial filter for look up search.But this approach will work only for standard relationship relate field (eg. Filtering contacts based on selected account) and the filter populate option can be used only with hard-coded values.But the following approach will help you to pass dynamic value to filter_populate parameter and you will be able to use the same for custom relationship relate fields also.And this approach will work for record,list and sub-panel list views.

Applying Initial Filter for Relate fields and Relationship fields
Let’s start with an example.Imagine you are going to provide SugarCRM for a an Educational Institute.They have multiple branches and each branch has separate predefined set of courses.A new student is coming to join for a course at one of their branches.Let’s call this activity as Student Enrollment.So here while creating an Enrollment the user will first select a Branch (Standard Accounts Module) then a Course.While selecting the course he/she would like to see only the courses which are offered by the selected branch.This we can achieve very easily with the help of initial filters.

Step 1
First we need to create a filter template for courses which will filter out only the courses of selected branch.To do this we will create a new file in the following path.Let’s name this template as FilterCoursesTemplate.
relate_fields

custom/Extension/modules/Courses/Ext/clients/base/filters/basic/FilterCoursesTemplate.php

Now add the following line of code to the file FilterCoursesTemplate.php

<?php
$viewdefs['Courses']['base']['filter']['basic']['filters'][] = array(
'id' => 'FilterCoursesTemplate',
'name' => 'LBL_FILTER_COURSES_TEMPLATE',
'filter_definition' => array(
array(
'accounts_courses_accounts_ida' => array(
'$equals' => ' ',
),
),
),
'editable' => true,
'is_template' => true,
);

Note:
1. Courses  is the module which we are filtering.
2. accounts_courses_accounts_ida: Relationship id between branches and courses. (this can be found in the relationship table between Branches and Courses)
3.The filter id and file-name should match each other
Step 2
search_more_button

Now we need to give a display label for our template we have created in Step 1.To do this add a new file in the following path with the below code.

custom/Extension/modules/Courses/Ext/Language/en_us.filterCourseTemplate.php

<?php
$mod_strings['LBL_FILTER_COURSES_TEMPLATE'] = 'Courses Offered by the Selected Branch';

Step 3

We are ready with our filter template.Now we need to pass this template as filter options into  the look up search when user try to select a Course by clicking the Search for more button.For that we will create a new controller file for relate field and will extend it from parent controller.

Create a new JavaScript file in the following path and add the below code into it.

custom/modules/Enrollments/clients/base/fields/relate/relate.js

({
extendsFrom: 'RelateField',
initialize: function(options) {
this._super('initialize', [options]);
},
openSelectDrawer: function() {
var filterOptions = new app.utils.FilterOptions()
.config({
'initial_filter': 'FilterCoursesTemplate',
'initial_filter_label': 'LBL_FILTER_COURSES_TEMPLATE',
'filter_populate': {
'accounts_courses_accounts_ida': this.model.get('accounts_enrollments_accounts_ida'),
}
})
.format();
//this custom code will effect for all relate fields in Enrollment module.But we need initial filter only for Courses relate field.
filterOptions = (this.getSearchModule() == "Courses") ? filterOptions : this.getFilterOptions();
app.drawer.open({
layout: 'selection-list',
context: {
module: this.getSearchModule(),
fields: this.getSearchFields(),
filterOptions: filterOptions,
}
}, _.bind(this.setValue, this));
},
})
view raw relate.js hosted with ❤ by GitHub

Note:

1. Enrollment is the module for which we are going to use filter.

2.accounts_enrollments_accounts_ida: Relationship id between branches and enrollments (this you can find in the  relationship table between Branches and enrollments modules.)

3.Here we are overriding the standard openSelectDrawer method .

Step 4

Now navigate to Admin > Repair and click “Quick Repair and Rebuild”. This will rebuild the extensions and make the initial filter available for users when selecting a course for a student enrollment.

Here we go!!
initial_filter_setThis customization will work if the user edit the record from record view,list view and sub-panel list view.Also while creating the record.And this is purely upgrade safe.

In next article I will explain how to apply initial filter while linking a record in sub-panel with the “Link Existing Records” button.

Please feel free to write your comments and feedback.

Thanks
Shijin Krishna


27 thoughts on “Applying Initial Filter For Relate Fields and Relationship fields In Sugar 7.x

  1. I believe

    ~/custom/Extension/modules/Courses()/clients/base/filters/basic/FilterCoursesTemplate.php
    should be
    ~/custom/Extension/modules/Courses()/Ext/clients/base/filters/basic/FilterCoursesTemplate.php

    and

    ~/custom/modules/Enrollments()/clients/base/fields/relate.js

    should be

    ~/custom/modules/Enrollments()/clients/base/fields/relate/relate.js

    A complete example would help understand better what is meant by “relationship-id” is this the link name?

    thanks,
    FrancescaS

    Liked by 1 person

  2. This works for “Relate” fields, where relationship-id is the id field that corresponds to the relate field. Do you have a solution for Related Records? i.e. records that have an M-N relationship and thus have to go through a table?

    Liked by 1 person

    1. Hi FrancescaS,

      This solution will work for both relate fields and relationship fields also.The example I have given is for relationship field only.
      If you see the ids accounts_courses_accounts_ida,accounts_enrollments_accounts_ida are from relationship tables not from custom tables as in the case of a relate field.

      Thanks!

      Like

  3. Hi Shijin,

    Nice solution you presented here. I was wondering if there is a way to update the “quick search” as well and not only the “search more”?
    So if I keep your example: the user could type “AM” in the Course relate field and he could see the list auto-completed with all the courses of the selected branch and starting with “AM”.

    I’ve been searching for some time but I still have no clue regarding the location of this auto-complete query for relate field

    Like

  4. This is excellent effort but this code seems to be not working. The filter populate does fill in the right id and filter does comes up in popup but the course value is not selected. Please help.

    Like

  5. The sample code is pasted below.

    ({
    extendsFrom:’RelateField’,
    initialize:function(options){
    this._super(‘initialize’,[options]);
    },

    openSelectDrawer: function() {
    self=this;

    var member = self.model.get(‘contacts_ts_transaction_1contacts_ida’);
    // alert(member);
    var filterOptions = new app.utils.FilterOptions()
    .config({
    ‘initial_filter’: ‘FilterSubscriptionTemplate’,
    ‘initial_filter_label’: ‘LBL_FILTER_SUBSCRIPTION_TEMPLATE’,
    ‘filter_populate’: {
    ‘contacts_sb_subscription_1contacts_ida’: member
    }
    })
    .format();
    alert(this.getSearchFields());
    alert(JSON.stringify(filterOptions));
    //this custom code will effect for all relate fields in Enrollment module.But we need initial filter only for Courses relate field.

    // filterOptions=(this.getSearchModule()==”sb_Subscription”) ? filterOptions : this.getFilterOptions();

    app.drawer.open({
    layout: ‘selection-list’,
    context: {
    module: this.getSearchModule(),
    fields: this.getSearchFields(),
    filterOptions: filterOptions,
    }
    }, _.bind(this.setValue, this));

    },

    })

    Like

  6. Hi,

    I need to apply above logic on multiple relate fields like Contacts will show on selected Account and Projects will show on selected Account

    How the above code can help?

    Regards

    Like

  7. Hi,

    I have 2 Accounts and 2 Contacts relate fields on the Tasks module

    If I select Account 1 than Contacts related to Account 1 should appear
    and If I select Account 2 than Contacts related to Account 2 should appear

    Any help will be highly appreciable

    Regards

    Like

  8. Hi,

    in custom/modules/Enrollments/clients/base/fields/relate/relate.js, line 25 [ }, _.bind(this.setValue, this));]

    why does the filterOptions becomes undefined on the “this”, but when i check on dev tools the value for filterOptions is set.
    I’m using Sugar 7.6.1

    Best Regards

    Like

  9. Hello,

    I am not sure how much clear am about your question.
    The object filterOptions is just a local variable , not a property of the relate field object. Hence you won’t be able access it with ‘this’.

    Please let me know if you are looking for something different.

    Thanks

    Like

  10. Hi,

    I make this worked!
    but what I want is to hide the area wherein someone can edit the search defination, or make it not editable. I tried making the editable value to false, but after that the customization isn’t working at all. Anything you can suggest?

    Like

  11. Hello,

    Editable parameter must be set to true for initial filters. This parameter will be set to false if the filter template is being used in List view. Basically initial filter will be editable in SugarCRM.

    I may be able to suggest some other approach if you can explain the use case little more detail.

    Thanks!

    Like

  12. Hi,

    I have a functionality in which in the Accounts module I have OrderHistory subpanel. I have added a “SHOWALL” functionality in the paneltop, on the click of which it gets routed to OrderHistory ListView.
    Now I want to put a filter on the List view where only the order histories against that account id will be shown in the list view.

    For example if I’m viewing the account Stanford and in the OH(orderhistory) subpanel I click on the “SHOWALL” it will route to OH listview with OHs of stanford only.

    For this I am able to communicate the record Id of the account to the list view of OH using backbone.js. I have the account Id,now I want an initial filter in the listview which dynamically takes up that account Id and filters the LISTVIEW on load.

    I need help on this please.

    Thanks,
    Varun

    Like

    1. Hi Arun,

      You can set initial filter to list view by extending the recordlist view and adding the below code to initialize method.

      initialize: function(options) {
      this._super(‘initialize’, [options]);
      //apply custom filter if listview
      if(options.context.get(“dataView”)==”list”) {
      options.context.set(“currentFilterId”, “”);
      }
      },

      I have not tried with passing dynamic values to the filter definition here. But you can try it out.

      Hope it helps!

      Like

      1. Hi Shijin,

        I have applied this code and I can see the changes in the currentFilterId attribute in the context array getting changed to my filterId but while running the debugger I could see that the value disappears and hence it’s not making changes in the UI and filter remains the previous one itself.

        But that’s just to find out whether if I make any changes to the filterIds will it work or not. So I could see that it’s working. Now I wanted to ask one thing just like I am able to modify the filterId attribute of the context object, similarly will I be able to make changes to filterconfigurations as you have done in app.drawer.open?

        Regards
        VARUN

        Like

  13. Hi Varun,

    I would probably say yes. Just before setting the currentFilter property of the context object with your filter id, modify the filter definition as how am doing while passing for initial filter.

    Please try it out. Let me know if you need any help!

    Thanks!

    Like

  14. Hi Shijin,
    I am not getting the value in the filter field.I have consoled also but i am not able to fetch the id, name from that particular module.I am using sugarcrm 7.6

    Like

  15. Hi Shijin,

    Your solution works on latest version of sugar especially in 7.7. but throws an error since the relate field is an array. i modified it a little bit so instead of $equals i used $in. then on the js value i pass the value encapsulated in an array.

    Thank you for this great tutorial.

    Like

  16. Hi Shijin,

    A big thanks for this blog !! I’m a new bee in sugarcrm 7 , your blogs are really helpful.
    I also have 1 more doubt, I have two module Vehicle & Car . I am redirecting from Vehicle to Car module with a value, when car module will be open with list of records, i want that redirect value should be work as filter.

    e.g.
    redirect with filter value = Honda,
    In car list view should show only HONDA brand cars in list view.

    Thanks
    Nitin

    Like

    1. Hello Nitin,

      Is the value needs to be populated under quick search field of car list view? If so before redirecting u can set the value in app.user.lastState(key,’HONDA’);
      Key-you can find in chrome developer tool under local storage.

      Like

Leave a comment