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.
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
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)); | |
}, | |
}) |
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!!
This 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
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
LikeLiked by 1 person
Hi FrancescaS,
Thanks for your comments.I will be updating the post soon.Expecting your comments on my future posts also.
Thanks!
LikeLike
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?
LikeLiked by 1 person
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!
LikeLike
Thank you!
LikeLike
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
LikeLike
Hi Ed,
I am working on the filtering option for quick search functionality.Once its done I will be posting an article on that here.
LikeLike
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.
LikeLike
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));
},
})
LikeLike
Hi Vikram,
Sorry for the very late reply. Where you able to make it work afterwards?
LikeLike
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
LikeLike
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
LikeLike
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
LikeLike
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
LikeLike
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?
LikeLike
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!
LikeLike
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
LikeLike
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!
LikeLike
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
LikeLike
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!
LikeLike
How can i list all filter to all user in module listview ?? everybody can see eachother filters ???
LikeLike
Hi Shijin
How can i do common listview filters for all users ?
Every user can see eachothers filters .?
LikeLike
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
LikeLike
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.
LikeLike
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
LikeLike
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.
LikeLike