PXSmartPanel in Acumatica

Hello everybody,

today I want to write few words how to work with PXSmartPanel.

One of my clients asked following:

1. Press at button.

2. Pop up should appear with two buttons ( "OK" , "Cancel")

3. At pop up should be also selector of contracts and datetime.

4. Existing screen should be modified.

In order to do this, following actions were implemented:

1. Existing screen was CT301000.

2. If to look in screen source code, following line says about graph:

<px:PXDataSource ID="ds" runat="server" Visible="True" Width="100%" TypeName="PX.Objects.CT.ContractMaint"
        PrimaryView="Contracts" BorderStyle="NotSet">

3. It means, that we need to create extension class for ContractMaint.

4. For example like this:

public class ContractMaintExt : PXGraphExtension<ContractMaint>

        public PXFilter<SubstituteSettingsFilter> SubstituteSettings;
        public PXAction<Contract> Substitute;
        [PXButton(CommitChanges = true)]
        [PXUIField(DisplayName = "Substitute")]
        protected void substitute()
            if (this.SubstituteSettings.AskExt(new PX.Data.PXView.InitializePanel(this.fillFilter)) ==
                var subsFilter = (SubstituteSettingsFilter)this.SubstituteSettings.Cache.Current;
                CopyOpenPMTaskHistory(Base.Contracts.Current.ContractID, subsFilter.ContractID, subsFilter.TransitionDate);

5. In the line 4 we declared to Acumatica, that we want to extend ContractMaint, and we want to create some data input, which is related to SubstituteSettingsFilter. Take note of Substitute and substitute: both of them are needed in order to make processing of inputted values.

6. Take a look at SubstituteSettingsFilter class itself:

        public class SubstituteSettingsFilter  : IBqlTable
            #region contractID

            public abstract class contractID : IBqlField, IBqlOperand

            protected int? _ContractID;
            [PXDimensionSelector("CONTRACT", typeof(Search2<Contract.contractID, 
                InnerJoin<ContractBillingSchedule, On<Contract.contractID, Equal<ContractBillingSchedule.contractID>>, 
                LeftJoin<Customer, On<Customer.bAccountID, Equal<Contract.customerID>>>>, 
                Where<Contract.isTemplate, Equal<boolFalse>,
                And<Contract.baseType, Equal<Contract.ContractBaseType>>>>), 
                new System.Type[] { typeof(Contract.contractCD), typeof(Contract.customerID), typeof(Customer.acctName), 
                    typeof(Contract.locationID), typeof(Contract.description), typeof(Contract.status), typeof(Contract.expireDate), 
                    typeof(ContractBillingSchedule.lastDate), typeof(ContractBillingSchedule.nextDate) },
                    DescriptionField = typeof(Contract.description), Filterable = true)]
            [PXUIField(DisplayName = "Contract ID", Visibility = PXUIVisibility.SelectorVisible)]
            public virtual int? ContractID
                get { return this._ContractID; }
                set { this._ContractID = value; }


            #endregion contractID

            #region TransitionDate
            public abstract class transitionDate : PX.Data.IBqlField
            protected DateTime? _TransitionDate;
            [PXUIField(DisplayName = "Transition Date")]
            public virtual DateTime? TransitionDate
                    return this._TransitionDate;
                    this._TransitionDate = value;
            #endregion TransitionDate

7. We described two properties: contractID and TransitionDate.

8. Now goes time of aspx page at <px:PXFormView> section I described the following:

<px:PXSmartPanel ID="pnlSubstitute" runat="server" AcceptButtonID="PXButtonOK" AutoReload="true" CancelButtonID="PXButtonCancel"
        Caption="Substitute" CaptionVisible="True" DesignView="Content" HideAfterAction="false" Key="SubstituteSettings"
        LoadOnDemand="true" Height="190px" Width="360px" DefaultControlID="edContract">
        <px:PXFormView ID="PXFormView6" runat="server" CaptionVisible="False" DataMember="SubstituteSettings" Width="100%"
            DefaultControlID="edActivationDate" DataSourceID="ds" TabIndex="1400">
            <ContentStyle BackColor="Transparent" BorderStyle="None">
                <px:PXLayoutRule runat="server" StartColumn="True" LabelsWidth="SM" ControlSize="M" />
                <px:PXSelector runat="server" ID="edContract" DataField="ContractID" CommitChanges="True" Width="130px" />
                <px:PXDateTimeEdit CommitChanges="True" ID="edTransitionDate" runat="server" DataField="TransitionDate" Width="130px" />
                <px:PXLayoutRule runat="server" StartRow="True" />
                <px:PXPanel ID="PXPanel1" runat="server" SkinID="Buttons">
                    <px:PXButton ID="OK" runat="server" DialogResult="OK" Text="OK" />
                    <px:PXButton ID="Cancel" runat="server" DialogResult="Cancel" Text="Cancel" />

Few words. AcceptButtonID speak about who plays role of OK button, Caption means title, CaptionVisible means that title will be visible, HideAfterAction means hide or not after action, Key means name of member in extension or graph, DefaultControlID means which control is active by default. Another important detail is DataMember property, which equals to Key.  Then goes layout rules, which I ommit. Then in Template goes selector, and datetime input. 

9. Here how control look like:

Here it is. If you have any comments, wishes, etc, you are welcome to post them

No Comments

Add a Comment