Building List screens with FilterBoxes

2 minute read time.
 Custom Pages that contain Search screens are fussy about block positioning.
The search block does not work correctly if it is included into the container following the list making it more difficult to create a screen with filterbox like behaviour. The type of Screen I am aiming at is shown here. This is a known issue.

The problem can be illustrated with some example code. For instance, the following code works:


var FilterBoxBlock = CRM.GetBlock("projectfilterbox");
var ProjectListBlock = CRM.GetBlock("ProjectList");
var myBlockContainer = CRM.GetBlock("Container");
with (myBlockContainer)
{
AddBlock(FilterBoxBlock);
AddBlock(ProjectListBlock);
}
ProjectListBlock.ArgObj = FilterBoxBlock;



BUT!!!!!

This code sample does not:


var FilterBoxBlock = CRM.GetBlock("projectfilterbox");
FilterBoxBlock.NewLine = false;
var ProjectListBlock = CRM.GetBlock("ProjectList");
var myBlockContainer = CRM.GetBlock("Container");
with (myBlockContainer)
{
AddBlock(ProjectListBlock);
AddBlock(FilterBoxBlock);
}
ProjectListBlock.ArgObj = FilterBoxBlock;


All that is different is that I have moved the search block to the right hand side of the List block.

To work round this I have had to control the building of the Argument that is passed to the list block. The following code is a partial work around for this issue.
You will still have to do some fine tuning but it should give you an idea.

The code is designed to be added to the Company tab group and call a list of projects belonging to that company.


if (CRM.Mode == View)
{
CRM.Mode = Edit;
}

var intRecordId = CRM.GetContextInfo("company","comp_companyid");
var strFilterButton = CRM.Button("filter", "filter.gif", "javascript:document.EntryForm.submit();");

var projectlistBlock = CRM.GetBlock("projectlist");

var FilterBoxBlock = CRM.GetBlock("projectfilterbox");
with (FilterBoxBlock)
{
NewLine = false;
AddButton(strFilterButton);
ButtonLocation = Bottom;
ButtonAlignment = Right;
}

var SuperContainer = CRM.GetBlock("Container");
with (SuperContainer)
{
AddBlock(projectlistBlock);
AddBlock(FilterBoxBlock);
DisplayButton(Button_Default) = false;
}

//Make sure fields in filter box are each on new line.
var strArg="proj_companyid="+intRecordId;
var myE = new Enumerator(FilterBoxBlock);
while (!myE.atEnd())
{
myEntryBlock = myE.item();
if (String(Request.Form(myE.item()))!='undefined')
{
strArg+=" and "+myE.item()+" like '"+Request.Form(myE.item())+"%'";
}
myEntryBlock.NewLine = true;
myEntryBlock.AllowBlank = false;
myE.moveNext();
}

projectlistBlock.ArgObj = strArg;

CRM.AddContent(SuperContainer.Execute());
Response.Write(CRM.GetPage());


  • It has meddled with that last post too. Drop me a line if you want an unadulterated copy of the code paul dot cowper at marda dot com.

  • Note that my code has been changed somewhat by the content management system of this website. The line with the .replace() methods has had two additional "" tags inserted:

    fbHtml += CRM.Button("filter", "filter.gif", "javascript:document.EntryForm.submit();").replace("","").replace("er_buttonItem ","FilterButtonItem ");

    and there shouldn't be a at the end of my post!

  • Further to Ian Urquhart's excellent idea of wrapping the filter box + button(s) in html to make it resemble the output in standard CRM pages, and then add the code as a button (that was inspired!), the following code sample generates list + filter box screens that are compatible with the 'Contemporary' AND the older (and far better in my opinion) 'Classical' CRM themes:

    CurrentCompanyID=CRM.GetContextInfo("company", "Comp_CompanyId");

    var sURL=new String( Request.ServerVariables("URL")() + "?" + Request.QueryString );

    // Get the list block

    List=CRM.GetBlock("CompanyEntityGrid");

    List.prevURL=sURL;

    // Get the filter screen block and configure it

    FilterBox=CRM.GetBlock("CompanyEntityFilterBox");

    FilterBox.NewLine = false;

    FilterBox.DisplayForm = false;

    FilterBox.DisplayButton(Button_Default) = false;

    FilterBox.ButtonLocation=Bottom;

    FilterBox.ShowValidationErrors = false;

    FilterBox.RefreshFromContent = true;

    // Get the container, add list and set it's ArgObj to the filter box

    container = CRM.GetBlock('container');

    container.DisplayButton(Button_Default) = false;

    container.AddBlock(List);

    List.ArgObj = FilterBox;

    // Compile the filter screen + buttons html

    fbHtml = "";

    fbHtml += FilterBox.Execute();

    fbHtml += CRM.Button("filter", "filter.gif", "javascript:document.EntryForm.submit();").replace("","").replace("er_buttonItem ","FilterButtonItem "); //note the terminal spaces in the params in the 2nd replace!

    fbHtml += "";

    fbHtml += CRM.Button("New", "new.gif", CRM.URL("Entity/EntityNew.asp")+"&E=Entity", 'Entity', 'insert');

    fbHtml += "";

    // Add the compiled html to the list block as a button

    List.AddButton(fbHtml);

    // Code generated by the entity wizard:

    if( false )

    {

    container.WorkflowTable = 'Entity'

    container.ShowNewWorkflowButtons = true;

    }

    if( CurrentCompanyID != null && CurrentCompanyID != '' )

    {

    CRM.AddContent(container.Execute("Enty_CompanyId="+CurrentCompanyID));

    }

    else

    {

    CRM.AddContent(container.Execute("Enty_CompanyId IS NULL"));

    }

    Response.Write(CRM.GetPage('Company'));

    Note that it isn't necessary to do a dummy container.Execute().

  • As an update to my previous posts, Stephen Cochrane at Sage Developer Support was able to assist me with this and sent me over some sample code which resolved the issue. I used this to amend my code and the issue was resolved. I have copied in my new code below for anyone to use in future if they are having a similar issue:

    CurrentCompanyID=CRM.GetContextInfo("company", "Comp_CompanyId");

    var FilterBoxBlock = CRM.GetBlock("ProductFilterBox");

    var strFilterButton = CRM.Button("filter", "filter.gif", "javascript:document.EntryForm.submit();");

    var strNewButton = CRM.Button("New", "new.gif", CRM.URL("Product/ProductNew.asp")+"&E=Product");

    FilterBoxBlock.NewLine = false;

    FilterBoxBlock.ButtonLocation = Bottom;

    FilterBoxBlock.ButtonAlignment = Right;

    List = CRM.GetBlock("CompanyProductGrid");

    container = CRM.GetBlock('container');

    container.DisplayButton(Button_Default) = false;

    container.AddBlock(List);

    container.AddBlock(FilterBoxBlock);

    List.ArgObj = FilterBoxBlock;

    var whereArg = "";

    if ( CurrentCompanyID != null && CurrentCompanyID != '' )

    {

    whereArg = "pro_CompanyId="+CurrentCompanyID;

    }

    else

    {

    whereArg = "pro_CompanyId IS NULL";

    }

    if((Request.Form('HIDDENSCROLLMODE') != '2') && (Request.Form('HIDDENSCROLLMODE') != '3'))

    {

    container.Execute(whereArg);

    }

    FilterBoxBlock.AddButton(strFilterButton);

    FilterBoxBlock.AddButton(strNewButton);

    CRM.AddContent(container.Execute(whereArg));

    Response.Write(CRM.GetPage());

  • With mine (and potentially Kevin's) issue(s) I've realised that the issue isn't that the first click doesn't do anything, but rather does the previous filter again, and then the new one on the second click. I.e. if you have a filter of type (with 'Type 1', 'Type 2', 'All', 'Either' options) which defaults to 'All' then changing the filter (to 'Type 1') and clicking will still show all list items, it is only on the second click (with 'Type 1' still selected) that the items are filtered to 'Type 1'. If after the first click (with 'Type 1') you change the filter (to 'Type 2') then on the second click the items will still be filtered by 'Type 1', on a third click they will then be filtered by 'Type 2'.

    Default: Show All -> Change Filter to Type 1 -> Result: Shows All -> Keep filter as Type 1 -> Result: Shows only Type 1

    Default: Show All -> Change Filter to Type 1 -> Result: Shows All -> Change filter to Type 2 -> Result: Shows only Type -> Keep filter as Type 2 -> Result: Shows only Type 2