How to Customize Selector in Acumatica

Hi Everyone,

Sometimes you want to add additional selector column to the screen, but this process not always is super strait forward.

Acumatica Selector

I will try to guide you step by step, how to add additional address line column to location selector on Sales Orders Screen.

First of all lets create a new customization try to analyse this selector control.

If you select this field and check attributes, that you can can see that there is no selector attribute, but we have strange LocationIDAttribute. Actually selector is there, but it is hidden by LocationIDAttribute. Sometimes to accumulate some logic in one attribute, Acumatica developers uses special types attributes – PXAccumulatorAttribute. This attribute has a collection of other attributes inside. During runtime, Acumatica framework will check that our attribute is inherited from Accumulator and will add all nested attributes in the PXCache.

LocationIDAttribute
In this code you can see that PXDimensionSelectorAttribute (that is real selector attribute) is added to protected collection on all attributes.
LocationID Attribute inheritance flow:Acumatica Selector Attributes Inheritance

Ok, but how to customize selector columns? And here Acumaita frameworks, starting from version 5.0 has super nice feature – additional attribute that will customize selector columns even if selector is nested. Just specify PXCustomizeSelectorColumns and define columns that yoг want to see.

[PXCustomizeSelectorColumns(
typeof(PX.Objects.CR.Location.locationCD),
typeof(PX.Objects.CR.Location.descr),
typeof(PX.Objects.CR.Address.addressLine1))]

You can add this attribute manually, or using visual designers. Do the following:

  1. Select required field in DAC customization window.
  2. Click Selector Columns
  3. In this popup panel you will see all current selector columns
  4. Click Add Columns
  5. Here you will see all available columns for this selector.
  6. Try to filter columns by “Address”
Acumatica Customization Browser for Selectors

Actually, there is no any address in the list of available columns, except Default Address – this is a link to another DAC, that holds address information.
So we have to add a join condition from our selector to address table using this field. Please, refer to where we have a source code of LocationIDBase Atrribute and notice there an additional constructor parameter – JoinType.

Lest just customize the LocationID attribute with additional Join condition and lets add PXCustomizeSelectorColumns  with address field as well.

Acumatica Customization Browser

There result customization code is here:

Now you can just publish the customization and use your new super nice user interface.

6 Replies to “How to Customize Selector in Acumatica”

  1. I tried to follow the instructions in order to add Address Line 1.

    But, the Original attributes for CustomerLocationID are different than in the instructions. Maybe it was changed in an update?

    Original attributes (Verison 2022 R2 – 22.202.0040):

    [LocationActive(typeof(Where<Location.bAccountID, Equal<Current>,
    And<MatchWithBranch>>), DescriptionField = typeof(Location.descr), Visibility = PXUIVisibility.SelectorVisible)]
    [PXDefault(typeof(Coalesce<Search2<BAccountR.defLocationID,
    InnerJoin<CRLocation, On<CRLocation.bAccountID, Equal, And<CRLocation.locationID, Equal>>>,
    Where<BAccountR.bAccountID, Equal<Current>,
    And<CRLocation.isActive, Equal,
    And<MatchWithBranch>>>>,
    Search<CRLocation.locationID,
    Where<CRLocation.bAccountID, Equal<Current>,
    And<CRLocation.isActive, Equal, And<MatchWithBranch>>>>>))]
    [PXForeignReference(
    typeof(CompositeKey<
    Field.IsRelatedTo,
    Field.IsRelatedTo
    >))]

    I tried to insert the new lines via Replace Original:

    [PXCustomizeSelectorColumns(
    typeof(PX.Objects.CR.Location.locationCD),
    typeof(PX.Objects.CR.Location.descr),
    typeof(PX.Objects.CR.Address.addressLine1))]

    [LocationActive(typeof(Where<Location.bAccountID, Equal<Current>,
    And<MatchWithBranch>>),
    typeof(InnerJoin<Address, On<Location.defAddressID, Equal>>),
    DescriptionField = typeof(Location.descr), Visibility = PXUIVisibility.SelectorVisible)]

    [PXDefault(typeof(Coalesce<Search2<BAccountR.defLocationID,
    InnerJoin<CRLocation, On<CRLocation.bAccountID, Equal, And<CRLocation.locationID, Equal>>>,
    Where<BAccountR.bAccountID, Equal<Current>,
    And<CRLocation.isActive, Equal,
    And<MatchWithBranch>>>>,
    Search<CRLocation.locationID,
    Where<CRLocation.bAccountID, Equal<Current>,
    And<CRLocation.isActive, Equal, And<MatchWithBranch>>>>>))]
    [PXForeignReference(
    typeof(CompositeKey<
    Field.IsRelatedTo,
    Field.IsRelatedTo
    >))]

    But, when I Preview Changes (preview layout changes without publication), I see no changes to the column selector. Any ideas?

  2. Thank you for your tutorial, I had tried your example and it’s work,
    But It’s not work in my case, it show “Segemented Key ‘GUINUMBERDETAIL’ cannot be found in the system.

    There are four tables in database below.

    GVGuiWord
    – GuiWordID
    – GuiWordCD
    GVGuiNumber
    – GuiNumberID
    – GuiWordCD
    GVGuiNumberDetail
    – GuiNumberDetailID
    – GuiNumberID
    GVGuiBook
    – GuiNumberDetailID

    public class GuiNumberDetailIDAttribute : AcctSubAttribute
    {
    public const string DimesionName = “GUINUMBERDETAIL”;
    protected const string CS_VIEW_NAME = “_GVGuiNumberDetail_GVGuiNumber_GVGuiWord_”;

    public GuiNumberDetailIDAttribute()
    : this(typeof(Where<GVGuiNumberDetail.guiNumberDetailID, Equal<Current>>))
    {

    }

    public GuiNumberDetailIDAttribute(Type WhereType) : base() {
    Type SearchType = typeof(Search<GVGuiNumberDetail.guiNumberDetailID,
    Where<Match<Current>>>);

    _Attributes.Add(
    new PXDimensionSelectorAttribute(
    DimesionName,
    SearchType,
    typeof(GVGuiNumberDetail.guiNumberDetailID),
    typeof(GVGuiNumberDetail.guiNumberDetailID),
    typeof(GVGuiNumberDetail.lineID)
    ));

    _SelAttrIndex = _Attributes.Count – 1;
    }

    public GuiNumberDetailIDAttribute(Type WhereType, Type JoinType)
    : base()
    {
    Type SearchType =
    BqlCommand.Compose(
    typeof(Search2),
    typeof(GVGuiNumberDetail.guiNumberDetailID),
    JoinType,
    WhereType);

    _Attributes.Add(
    new PXDimensionSelectorAttribute(
    DimesionName,
    SearchType,
    typeof(GVGuiNumberDetail.guiNumberDetailID),
    typeof(GVGuiNumberDetail.guiNumberDetailID),
    typeof(GVGuiNumberDetail.lineID)
    ));

    _SelAttrIndex = _Attributes.Count – 1;
    }

    }

    [Serializable]
    public class GVGuiBook : IBqlTable
    {

    #region customerGVGuiNumberDetailID
    public abstract class customerGVGuiNumberDetailID : PX.Data.IBqlField
    {
    }
    protected int? _CustomerGVGuiNumberDetailID;
    [PXUIField(DisplayName = “Gui Number Detail ID”, Required = true)]
    [PXMergeAttributesAttribute(Method = MergeMethod.Merge)]
    [PXCustomizeSelectorColumns(
    typeof(GVGuiNumberDetail.guiNumberDetailID),
    typeof(GVGuiNumberDetail.guiNumberDetailID),
    typeof(GVGuiWord.guiWordCD)
    )]
    [GuiNumberDetailID(
    typeof(Where<GVGuiNumberDetail.guiNumberDetailID, Equal<Current>>),
    typeof(InnerJoin<GVGuiNumberDetail,
    On<GVGuiBook.guiNumberDetailID, Equal>,
    LeftJoin<GVGuiNumber, On<GVGuiNumber.guiNumberID, Equal>,
    LeftJoin<GVGuiWord, On<GVGuiWord.guiWordID, Equal>>>>),
    DescriptionField = typeof(GVGuiWord.guiWordCD),
    Visibility = PXUIVisibility.SelectorVisible)]

    public virtual int? CustomerGVGuiNumberDetailID
    {
    get
    {
    return this._CustomerGVGuiNumberDetailID;
    }
    set
    {
    this._CustomerGVGuiNumberDetailID = value;
    }
    }
    #endregion
    }
    }

    1. Hi Dean,
      Have you created a “GUINUMBERDETAIL” Segmented key in Acumatica Segmented Keys (CS202000) screen?
      It looks like it is missing there.

      1. Hi Sergey,
        No, I don’t create it, the error is gone after I created it, but the result not what I expected.
        I think I need more time to understand what’s segmented key purpose,
        However, thank you anyways

  3. Hi Ben,

    Try this approach please
    #region CustomerID
    [PXDefault]
    [CustomerActive(typeof(Search, Equal,
    And>>>>),
    typeof(Customer.acctCD), typeof(Customer.acctName), typeof(Customer.acctReferenceNbr),
    typeof(Address.addressLine1), typeof(Address.addressLine2), typeof(Address.postalCode),
    typeof(Contact.phone1), typeof(Address.city), typeof(Address.countryID),
    typeof(Location.taxRegistrationID), typeof(Customer.curyID),
    typeof(Contact.salutation),
    typeof(Customer.customerClassID), typeof(Customer.status),
    Visibility = PXUIVisibility.SelectorVisible,
    DescriptionField = typeof(Customer.acctName), Filterable = true)]
    public int? CustomerID { get; set; }
    #endregion

  4. Thank you for your blog on how to customize the Location selector.

    I am trying to do something similar for the Customer selector on the Sales Order screen. Specifically, I would like to show the address fields (addressLine1, city, state, etc.) associated with the defBillAddressID instead of the main customer address.

    The customer selector uses a [CustomerActive] attribute, but I haven't been able to figure out how to add a join condition to allow me to access the billing address fields. Any ideas or tips?

Leave a Reply

Your email address will not be published. Required fields are marked *