Forms are main elements of the Finance and Operations development platform. Many standard forms are already available in the application.
You can also create new forms. Each form consists of form methods, which can be classified as standard methods or custom methods. Standard methods must have a super()
call to implement the parent method. Standard and custom methods are available with all standard and custom forms. You can extend the existing form methods and include code by using chain of command.
The following sections explain the standard form methods in the Finance and Operations apps development platform.
The init()
method is a standard method that's called when a form is opened. This method helps to initialize the form, and it's run after the constructor method new()
. The init()
method is responsible for creating the runtime interface of the form. Mostly, you'll use this method when you need to:
Example
You have a custom form with a table named TrainingMaster. The table has an enum type field called TrainingType that has two values: Online and Classroom. The form should be opened with those records where TrainingType is Online.
The code pattern is as follows:
X++Copy
public void init()
{
super();
TrainingMaster_ds.query().dataSourceName("TrainingMaster")
.addRange(fieldNum(TrainingMaster,TrainingType))
.value(enum2Str(TrainingType::Online));
}
Note
Modifications to the data source should be done only after the super()
call because the base initialization happens there.
The close()
method is a standard method that's called when a form is closed. The super()
call in this method closes the form, manages the database updates, and sets the closed()
method to true. You can use the closeCancel()
or closeOK()
methods to initiate the close()
method. Additionally, you can use the close()
method to forcefully clear the values of some variable or to deallocate a class. Make sure that you complete these actions before the super()
call. Often, NumberSequence classes are called from the close()
method to facilitate an abort operation.
The closeCancel()
method is a standard method that's called when a form is canceled. The super()
call in this method updates the Boolean value of closedCancel()
and ensures that the modifications in the form aren't saved.
The closeOK()
method is a standard method that's called when a form is closed by selecting the OK button. The super()
call in this method updates the Boolean value of closedOK()
and calls the close()
method.
The run()
method is a standard method that's called immediately after the init()
method. The super()
call in this method makes the form window appear on the screen and performs a database search for the data to be displayed in the form.
Typical reasons for overriding this method include:
The following sections explain the standard form data source methods in the Finance and Operations apps development platform.
The init()
method is a standard method of a form data source, which is called when a form is opened after the implementation of the form init()
method. This method helps create a data source query based on the data source properties.
Example
You have a custom form with a table named TrainingMaster. The table has an enum type field named TrainingType that has two values: Online and Classroom. The form should be opened with those records, where TrainingType is Online.
The code pattern should be as follows:
X++Copy
[DataSource]
class TrainingMaster
{
public void init()
{
super();
this.query().dataSourceName("TrainingMaster")
.addRange(fieldNum(TrainingMaster,TrainingType))
.value(enum2Str(TrainingType::Online));
}
}
The active()
method is a standard method of a form data source that's called when a user navigates to a new record.
Example
You have a custom form with a table named TrainingMaster. The table has a field named Venue and an enum type field named TrainingType, which has two values of Online and Classroom. While you're navigating through the records, the Venue field will be uneditable if TrainingType is Online. Otherwise, the Venue field will be editable.
The code pattern should be as follows:
X++Copy
[DataSource]
class TrainingMaster
{
public int active()
{
int ret;
ret = super();
TrainingMaster_ds.object(fieldNum(TrainingMaster,
Venue)).allowEdit(TrainingMaster.TrainingType == TrainingType::Classroom);
return ret;
}
}
The validateWrite()
method is a standard method of a form data source, which is called when a user attempts to save a record to determine whether data is valid and ready to be written.
Example
You have a custom form with a table named TrainingMaster. The table has a date field named TrainingDate. No backdated training data should be allowed.
The following code pattern can be a way to achieve this result:
X++Copy
[DataSource]
class TrainingMaster
{
public boolean validateWrite()
{
boolean ret;
ret = super() && (TrainingMaster.TrainingDate >= today());
return ret;
}
}
Note
You don’t want to let the validateWrite()
method fail without a message regarding why. A best practice would be to throw an error with a specific message rather than using the Boolean return of the if
statement.
The validateDelete()
method is a standard method of a form data source, which is called when a user attempts to delete a record, to confirm the deletion.
Example
You have a custom form with a table named TrainingMaster. The table has a date field named TrainingDate. No backdated training data should be deleted.
The following code pattern can be a way to achieve this result:
X++Copy
[DataSource]
class TrainingMaster
{
public boolean validateDelete()
{
boolean ret;
ret = super() && (TrainingMaster.TrainingDate >= today());
return ret;
}
}
Note
You should throw an error with a message rather than let the validateDelete()
method silently fail.
The executeQuery()
method is a standard method of a form data source that runs the data source query and displays the retrieved records. You can apply a filter on the data source that uses a query by overriding executeQuery()
. The main difference between this method and the init()
method is that the init()
method runs once during the opening of the form, whereas the executeQuery()
method runs whenever the form is refreshed.
Example
You have a custom form with a table named TrainingMaster. The table has an enum type field named TrainingType that has two values: Online and Classroom. The data in the form should be filtered with the Trainingtype of Online only.
X++Copy
[DataSource]
class TrainingMaster
{
public void executeQuery()
{
QueryBuildDataSource queryBuildDataSource;
queryBuildDataSource =
this.query().dataSourceTable(tablenum(TrainingMaster));
queryBuildDataSource.clearRanges();
queryBuildDataSource.addRange(fieldnum(TrainingMaster,
TrainingType)).value(enum2Str(TrainingType::Online));
super();
}
}
The initValue()
method is a standard method of a form data source. While you're inserting a new record, initValue()
can help you initialize field values. This method is called when a new record is created.
Example
You have a custom form with a table named TrainingMaster. The table has a date field named TrainingDate. During the creation of a new record, the TrainingDate field should be initialized with today’s date.
The coding pattern can be as follows:
X++Copy
[DataSource]
class TrainingMaster
{
public void initValue()
{
super();
TrainingMaster.TrainingDate = today();
}
}
The write()
method is a standard method of a form data source. This method is called when a record is modified and when you've attempted to save it by selecting the Save button or navigating out of the record.
Example
You have a custom form with a table named TrainingMaster. The table has a real field called Price that indicates the total price of the trainer. It also contains an integer field called NoofDays that indicates the duration of the training. Additionally, the table has a field named TrainerID, which creates a foreign key with the TrainerTable. The TrainerTable has a real field called Rate, which captures the daily rate of the trainers.
After you've saved the record in the TrainingMaster table, the Price field of the TrainerMaster table should be updated with the multiplication of NoofDays and Rate of the TrainerTable.
The coding pattern is as follows:
X++Copy
[DataSource]
class TrainingMaster
{
public void write()
{
TrainingMaster.Price = TrainerTable::find(TrainingMaster.TrainerID).Rate * TrainingMaster.NoofDays;
super();
}
}
The delete()
method is a standard method of a form data source. This method is called when a record is deleted.
Example
You have a custom form with a table named TrainingMaster. The table has a field named TrainerID, which has a foreign key relation with the TrainerTable. TrainerTable has a field named TrainingCount. The requirement is to reduce the TrainingCount number by one if a record is deleted from the TrainingMaster table.
The coding pattern can be as follows:
X++Copy
public void delete()
{
TrainerTable trainerTable;
ttsbegin;
trainerTable = TrainerTable::find(TrainingMaster.TrainerID, true);
trainerTable.TrainingCount = trainerTable.TrainingCount - 1;
trainerTable.update();
ttscommit;
super();
}
The following sections explain the standard form data source field methods in the Finance and Operations apps development platform.
modified()
The modified()
method is a standard method on the field of the form data source. This method is called when the value of a specific field is modified.
Example
You have a custom form with a table named TrainingMaster. The table has a field named Venue and an enum type field named TrainingType that has two values: Online and Classroom. If Online is selected for the TrainingType, the Venue field should become blank.
The coding pattern can be as follows:
X++Copy
[DataSource]
class TrainingMaster
{
[DataField]
class TrainingType
{
public void modified()
{
super();
if(TrainingMaster.TrainingType == TrainingType::Online)
TrainingMaster.Venue = "";
}
}
}
The validate()
method is a standard method on the field of the form data source. This method is called when a value is entered in a specific field, and it's overridden if extra field validation is needed.
Example
You have a custom form with a table named TrainingMaster. The table has a field named Participants, where entering a number higher than 20 isn't allowed.
The coding pattern can be as follows:
X++Copy
[DataSource]
class TrainingMaster
{
[DataField]
class Participants
{
public boolean validate()
{
boolean ret;
ret = super() && (TrainingMaster.Participants <= 20);
return ret;
}
}
}
Make sure that you offer a reason for errors that are thrown, as shown in the following code example:
X++Copy
[DataSource]
class TrainingMaster
{
[DataField]
class Participants
{
public boolean validate()
{
boolean ret;
if (TrainingMaster.Participants > 20)
{
throw error("Maximum 20 participants");
return false;
}
ret = super();
return ret;
}
}
}
The lookup()
method is a standard method on the field of the form data source. This method is called when a lookup operation is attempted on a data source field. If data that's shown in the lookup form must be customized with some filter, the lookup()
method should be overridden.
Example
You have a custom form with a table named TrainingMaster. The table has a field named TrainerID that creates a foreign key with the TrainerTable. TrainerTable has an enum field called TrainerType that has two values: Technical and Functional. The lookup in the TrainerID field should display only technical trainers.
The coding pattern can be as follows:
X++Copy
[DataSource]
class TrainingMaster
{
[DataField]
class TrainerID
{
public void lookup(FormControl _formControl, str _filterStr)
{
SysTableLookup sysTableLookup =
SysTableLookup::newParameters(tableNum(TrainerTable),_formControl);
Query query = new Query();
QueryBuildDataSource qbds;
qbds= query.addDataSource(tableNum(TrainerTable));
qbds.addRange(fieldNum(TrainerTable,
TrainerType)).value(enum2Str(TrainerType::Technical));
sysTableLookup.addLookupfield(fieldNum(TrainerTable,TrainerID));
sysTableLookup.addLookupfield(fieldNum(TrainerTable,TrainerName));
sysTableLookup.parmQuery(query);
sysTableLookup.performFormLookup();
}
}
}
Chain of command is an option that helps you enhance the functionality of a form method. This option is applicable for standard methods and custom methods of the form.
You can use the following code pattern if you need to extend the init()
method of the form:
X++Copy
[ExtensionOf(formStr(Currency))]
final class CurrencyForm_Extension
{
public void init()
{
//code
next init();
//code
}
}
Chain of command is an option that helps you enhance the functionality of a form data source method. This option is applicable for standard methods and custom methods of the form.
You can use the following code pattern if you need to extend the initValue()
method of the form data source:
X++Copy
[ExtensionOf(FormDataSourceStr(Currency, Currency))]
final class CurrencyFormCurrencyTableDataSource_Extension
{
public void initValue()
{
//code
next initValue();
//code
}
}
Chain of command is an option that helps you enhance the functionality of a form data source field method. This option is applicable for standard methods and custom methods of the form.
You can use the following code pattern if you need to extend the lookup()
method of the form data source fields:
X++Copy
[ExtensionOf(formDataFieldStr(CustTable, CustTable, CustGroup))]
final class CustTableFormDataFieldCustGroup_Extension
{
public void lookup(FormControl _formControl, str _filterStr)
{
//Code
next lookup(_formControl, _filterStr);
//Code
}
}
Chain of command is an option that helps you enhance the functionality of a form control method. This option is applicable for standard methods and custom methods of the form.
You can use the following code pattern if you need to extend the clicked()
method of the form button control:
X++Copy
[ExtensionOf(formControlStr(CustTable, DirPartyEntityAssociationUpdate))]
final class CustTableFormControlDirPartyEntityAssociationUpdate_Extension
{
public void clicked()
{
//code
next clicked();
//Code
}
}