EP Tips-n-Tricks – Data Sets / Data Sources


Happy New Year !!!


 Data Sets


                Init


                 For checking arguments passed from managed code or context and adding ranges/ modifying query.


if (element.args().dataset() == tablenum(EPPriceCalc))


    {


        epPriceCalc = element.args().record();


        custTable = CustTable::find(epPriceCalc.AccountNum);


        priceTransferParmId = epPriceCalc.ParmId;


    }


 


Pack/UnPack


Persisting values of in-memory variables between postbacks


public container pack()


{


    return [#CurrentVersion, #CurrentList] + [super()];


}


public boolean unpack(container _pack)


{


    Integer     version = conpeek(_pack,1);


    container   base;


    boolean     ret;


 


    switch (version)


    {


        case #CurrentVersion    :   [version, #currentList, base] = _pack;


                                    ret = super(base);


                                    break;


        default: super(_pack);


    }


 


    return ret;


 


}


Other Methods


Also common methods that could be called from Managed code or from other methods in the Data sources could be added at the DataSet level.


Args


Get external arguments through the args objects


Checking for RecordContext


public void init()


{


    ;


 


    super();


    EPPersonalize::find(curuserid());


    if (element.args() && element.args().dataset() == tablenum(EmplTable))


    {


        callerEmplTable = element.args().record();


        emplId = callerEmplTable.EmplId;


    }


 


}


Passing parameters from Managed code to X++ in dataset


protected void Page_Init(object sender, EventArgs e)
{
this.AxDataSource1.CreatingDataSetRun += new EventHandler<CreatingDataSetRunEventArgs>(AxDataSource1_CreatingDataSetRun);
}


Set the param value  to the event arugments


void AxDataSource1_CreatingDataSetRun(object sender, CreatingDataSetRunEventArgs e)


{


e.DataSetRunArgs.parm = “4000”;


}


 


In AOT override or add method in the data set and use element.args().parm() to received the paramter  


public void executeQuery()
{


 QueryBuildRange             custRange;
 ;
        custRange = SysQuery::findOrCreateRange(this.query().dataSourceNo(1), fieldnum(CustTable, AccountNum));
        custRange.value(element.args().parm());
   super();


}


You can also pass an Enum. For example


void AxDataSource1_CreatingDataSetRun(object sender, CreatingDataSetRunEventArgs e)
{
e.DataSetRunArgs.parmEnumType = EnumMetadata.EnumNum(this.AxSession, “EPFormAction”);
e.DataSetRunArgs.parmEnum(2);
}


 


public void init()
{
    super();


     if (element.args().parmEnumType() == enumnum(EPFormAction) && element.args().parmEnum() == EPFormAction::CreateMode)
    {
        //do somethign here


    }
}


 


Data Sources


Set the below properties at the individual datasources.


InsertAtEnd : No


InsertIfEmpty : No


 


Also set Allow* properties on the Data source appropriately.


Init


Adding ranges


 


public void init()


{


    super();


 


    qbrName = this.query().dataSourceTable(tablenum(InventDimCombination)).addRange(fieldnum(InventDimCombination,Name));


    qbrName.status(RangeStatus::Hidden);


 


    qbrItem = this.query().dataSourceTable(tablenum(InventDimCombination)).addRange(fieldnum(InventDimCombination,ItemId));


    qbrItem.status(RangeStatus::Hidden);


}


 


Setting temporary table mode


public void init()


{


    super();


    //BP Deviation documented


    salesTable.setTmp();


}


InitValue


Initializing values


public void initValue()


{


    super();


 


   // Is form called with a record


    if (element.args() && element.args().record())


    {


        callerRecord = element.args().record();


        // Init opportunity from lead record


        if (callerRecord.TableId == tablenum(smmLeadTable))


        {


            smmCreateEntity::initFromCommon(callerRecord, smmOpportunityTable);


            info(DirParty::toolTip(smmOpportunityTable));


        }


    }


}


ValidateWrite


For validation that are specific to the dataset. ( common table level validation could be at the table level)


public boolean validateWrite()


{


    #VendRequest


    boolean ret;


 


    ret = super();


 


    if  (ret && !VendTable::find(vendrequest.AccountNum))


        ret = checkFailed(strfmt(“@SYS301682”,vendrequest.AccountNum));


 


    if  (ret && element.args().managedContentItemName() == #VendRequestStatusChangeAddEdit &&


            DirPerson::find(vendRequest.ContactParty) == null)


        ret = checkFailed(strfmt(“@SYS301683”,vendrequest.ContactParty));


 


    return ret;


}


Write


For updating tables not in the data set and reread


public void write()


{


 


    if (purchLine.RecId)


    {


        purchLine.InventDimId = InventDim::findOrCreate(inventDim).InventDimId;


        purchLine_ds.setCurrentInventDim();


 


        mapLines.insert(purchLine.RecId, purchLine);


    }


    super();


}


<field>.datasetlookup


For Customizing field lookup. This does not appear in the override method list. But you should be able to manually create this method which will act as override.


void dataSetLookup(SysDataSetLookup sysDataSetLookup)


{


    List          list;


    Query         query;


 


    args = new Args();


    list = new List(Types::String);


    list.addEnd(fieldstr(ProjTable, ProjId));


    list.addEnd(fieldstr(ProjTable, Name));


    list.addEnd(fieldstr(ProjTable, Status));


    sysDataSetLookup.parmLookupFields(list);


    sysDataSetLookup.parmSelectField(‘ProjId’);


 


    // Call query


    query = projTimeSheet_ds.getProjectIDQuery();


 


    // Pass the query to SysDataSetLookup so it result is rendered in the lookup page.


    sysDataSetLookup.parmQuery(query);


}


<field>.modified


public void modified()


{


    super();


 


    purchLine.modifyItemDim(inventDim,


        fieldnum(InventDim,ConfigId),


        InventTable::itemProductDimensionGroup(purchLine.ItemId));


    purchLine_ds.setCurrent();


}


AXDataSourceControl


Make sure only one AXDataSourceControl has Role property set to Provider ( or ProviderConsumer) in your user control. If the user control contains other user control then across all these , only one datasourcecontrol should play the provider role.


Always set EnableViewState and PersistState to True( This is the default. Don’t change it)


AXGridView


1.       DataKeyNames must point to a one (or set) of unique fields int the DataSetView.


2.       If the user control is playing the Provider Role ( a propert on the AX user control webpart) , then at least one AXDataSourceControl should have the Role property set to Provider or ProviderConsumer and the ProviderView is set.


AXForm


1.       Make Sure DataKeyNames set correctly.


2.       When Fields are selected for AXGroup using the boundfield designer, sometime the selectedfields are updated to the markup. (Known bug). Update the markup directly and add the boundfields.


3.       If the same Axform control is used for different modes than use the EPFormAction parameter set on the WebContent and switch to the right mode


4.       Set the DataMember to <DataSetView>_Current


5.       UpdateOnPostBack is generally set to False. If you need to access the field values entered in the control before the record is persisted in a postback, then set it to true. For example if you want to change the lookup of a second control based on the value entered on the first control, then you would need to set this property.


6.       If you are using the Form for Edit operation set AutoGenerateEditButton to true.  


 


protected void Page_Init(object sender, EventArgs e)


    {


       


        this.SetupMode();


    }


private void SetupMode()


    {


        switch (this.FormMode)


        {


            case ApplicationProxy.EPFormAction.EditMode:


                if (this.PageDefinition != null)


                {


                    this.PageDefinition.pageTitle = Labels.GetLabel(“@SYS131104”);


                }


                this.formVendRequestProfileEdit.DefaultMode = DetailsViewMode.Edit;


                this.formVendRequestProfileEdit.AutoGenerateEditButton = true;


                break;


           


            default:


                this.formVendRequestProfileEdit.DefaultMode = DetailsViewMode.ReadOnly;


                break;


        }


    }


8.       Derive from AxBaseUserControl if the AxForm control requires RecordContext and should not display any data when there is no record Context.


<%@ Register Src=”AxBaseUserControl.ascx” TagName=”AxBaseUserControl” TagPrefix=”Ax” %>


protected override bool RequiresExternalContext


    {


        get


        {


            if (this.FormAction == AppProxy.EPFormAction.CreateMode)


            {


                return false;


            }


            else


            {


                return true;


            }


        }


    }


 


9.       Some useful code generally used in AXForm controls


//Web part  private


    AxBaseWebPart _baseWebpart = null;


 


    //Webpart


    AxBaseWebPart BaseWebpart


    {


        get


        {


            //return the basewebpart if it is not null


            if (this._baseWebpart != null)


                return this._baseWebpart;


            //get the webpart if basewebpart is null


            this._baseWebpart = AxBaseWebPart.GetWebpart(this);


            return this._baseWebpart;


        }


    }


    //Web part managed content item for the page


    Proxy.WebManagedContentItem ContentItem


    {


        get


        {


            //get the managed content item from the webpart


            return this.BaseWebpart == null ? null : this.BaseWebpart.WebManagedContentItem;


        }


    }


private Boolean IsCustomer()


    {


        bool isCustomerBool = false;


        if (ApplicationProxy.EP.isCustomer(AxSession.AxaptaAdapter))


        {


            isCustomerBool = true;


 


        }


        return isCustomerBool;


    }


static AxBoundField GetField(DataControlFieldCollection fields, string name)


    {


        foreach (DataControlField field in fields)


        {


            AxBoundField boundField = field as AxBoundField;


            if (boundField != null && String.Compare(boundField.DataField, name, true) == 0)


            {


                return boundField;


            }


        }


        return null;


    }


 

Comments (2)

  1. Michael O. says:

    Hi meysun,

    First thank you for a great blog.

    I have a question on passing values. I would like to have the possibility make something like the globalcache you have within AX or a session variable in ASP. Since the website is stateless I'm in doubt how to achieve this in EP 2009.

    I can pass the values between web parts by using “element.args()” etc. like described above, but if you click a menu item within the QuickLaunch menu you lose this context.

    In 4.0 you could use the “setMenuFunctionRecord” on the WebForm for this.

    What I want to make is that user on the first page select a value. This value is then used on all subsequent websites as a filter on the dataset.

    Thanks

  2. Jaffer says:

    Hi meysun,

    Really this is a great blog. Thanks

    My question is now i am creating one web page.

    I have two tables, one table have data(20 rows), i need to insert continueously the data in to another table. but that first table remain same. it should not affect

    Hope you understand the requirement. company conduct survey to employee like 20 to 25 question'(constant)

    . that question will be same. all the employee should answer(that wil insert in another table). is this possible to achieve in EP.

    I already created and display question in one axform through dataset. now my quetions is how to insert output in another table.

    am new to EP. just past week only started to work. please reply

    Thanks