I have created a report (no SSRS) in AX2012, via a Menu Item I am running this report, i want to achieve to show the AssetId, from the Asset Record i have selected.
My Dialog method:
public Object dialog(Object _dialog)
{
DialogRunbase dialog = _dialog;
;
dialogAssetIds = dialog.addField(ExtendedTypeStr(AssetId));
return dialog;
}
My getFromDialog method:
public boolean getFromDialog()
{
;
curAssetId = dialogAssetIds.value();
return true;
}
I also have created a display method to return the value:
display AssetId assetId()
{
return curAssetId;
}
On my report field, I have selected the above method to show the AssetID number, obviously I am missing the key link, but I am not sure what.
I am receiving the error:
Report is empty - Report
Eventually, I want to print the AssetId number without the dialog field, based on the selected record, I have built in the dialog so I am sure nothing was wrong with printing the value directly.
Guessing what went wrong with your report requires more data, but ...
You do not need a RunbaseReport class or any code to achieve this behavior.
Just set the AutoJoin property to Yes on your report's AOT node.
Change your menu item to reference the report.
Add the menu item to your Asset form, remember to set the DataSource property of the control to the AssetTable datasource.
Then by magic it works provided dynalink on form table and report table is established. If the report is called from the main menu there is no autojoin of cause, it will select whatever the user queried.
Works for MorphX reports, not for SSRS reports. SSRS sucks (again, and again ...).
Related
There is a form which is linked to the display menu item. I was checking the property of the menu item and see two properties have yes value, (1) neededRecord and (2) CopyCallerQuery. I discovered that when copyCallerQuery property is true, jumping to this form from other forms failed with this error :
Cannot apply initial query because no form root data source table
matches the query root data source table..
On the other hand, in some situations this form is open by code in a helper class as bellow:
private void openMyForm(MyTable _myTable)
{
MenuFunction _menuFunction;
Args _args;
_args = new Args();
_args.record(_myTable);
_args.caller(this);
_menuFunction = new MenuFunction(menuItemDisplayStr(MyFormDisplayMenu),MenuItemType::Display);
_menuFunction.openMode(OpenMode::Edit);
_menuFunction.run(_args);
}
When I set copyCallerQuery to No the form is open with wrong record but when I set it yes form is open with correct record.
So I want to know what is usage of the CopyCallerQuery property? Did I use it correctly?
copyCallerQuery will specify if the calling form's query should be copied to the target form, for example copying a list page query to a details form.
You can see and better understand this for yourself by
Create a form (Form1)
Add a SalesTable datasource to it
Override an init method at \Forms\Form1\Methods\init and after the super(); call put info(SalesTable_ds.query().toString());
Create a Display menu item (\Menu Items\Display\Form1) with property Object = Form1 and CopyCallerQuery = Yes.
Go to the SalesTable form at \Forms\SalesTable and just add that new menu item (Form1) anywhere on the SalesTable form as a button in the action pane, and set the datasource property to SalesTable
Open the SalesTable form and press the button. Copy the infolog to notepad somewhere.
Modify \Menu Items\Display\Form1 and set CopyCallerQuery = No and then open SalesTable form again and copy the query into notepad and compare the two.
Your error you are receiving is because the caller form's root datasource needs to match the target form's root datasource in order to copy it.
I have created a command button in the CustGroup form action pane.
I have added a new base enum edt field to both the CustGroup and CustTable tables and forms.
When you click on the button the data that was previously changed in the CustGroup table must be reflected in the cust table form.
I have written code in button on click event handler but it's not updating.
What to do, any suggestions?
If I understand your question correctly, you want to transfer a change of a new field in a customer group to all customers that share this customer group.
This kind of mass data update is usually not done by code in a form, because that code is executed on the client tier, which results in a bad performance. Instead, you should create a class that is set to execute on the server tier. If you create a main method for this class, you can easily create an action menu item for it, which let's you easily integrate the call to this class as a button in the CustGroup form.
In the main method you can access the CustGroup record for which the button was clicked via the Args object. This gives you the value of your new field that was changed. With this value, you can then use code similar to the following to update your customers:
public void updateCustomersWithNewCustGroupFieldValue(CustGroup _custGroup)
{
CustTable custTable;
ttsBegin;
while select forUpdate custTable
where custTable.CustGroup == _custGroup.CustGroup
{
custTable.MyNewEnumField = _custGroup.MyNewEnumField;
if (custTable.validateWrite())
{
custTable.update();
}
else
{
error('Please implement some error handling');
}
}
ttsCommit;
}
Inside AX2012 R3, when creating a new Return Order from the Return Order list view page (using the button in the Header), the SalesCreateOrder form opens and functions as expected.
Upon close of this form, however, instead of opening the newly created Order, instead the order that was selected in the grid is opening.
Several developers have made customization to this form, but none that (at first glance) appear relevant to this behavior.
Where would I find the behavior to open a form upon close of the SalesCreateOrder dialog?
You can open the created order by changing the SalesCreateOrder.close method:
public void close()
{
Args args = new Args(this); //Change here
// Save user's customer search type
MCRCustSearch::saveCustSearchType(mcrCustSearchType.selection());
if (salesTableType)
{
salesTableType.formMethodClose();
}
//Change here -->
args.record(salesTable);
new MenuFunction(menuitemDisplayStr(SalesTable),MenuItemType::Display).run(args);
//End of change <--
super();
}
You may have to change the called menuitem if called from Return order.
Your understanding of how returns are created is wrong. A form isn't opened upon closing, it's opened upon creation.
When you do Ctrl+n or click to create a new return order, the ReturnTable form actually instantiates the SalesCreateOrder form eventually.
To see this, place a breakpoint in the init method of the ReturnTable at \Forms\ReturnTable\Methods\init and then try and create a new return order.
I have modified a validate method of form control. On this control I'm typing the product name.
In validate method I'm checking if this product name exists in the table. If it does not exists the error is thrown.
My issue is that after the error is thrown I want to clear control. Here is my code:
public boolean validate()
{
InventTable inventTable;
boolean ret = super();
select inventTable
where inventTable.nameAlias == this.text();
if (!inventTable.recid)
{
error("error");
this.text("");
}
return ret;
}
this.text(""); does not work. So how can I clear the control? The control is a field from my datasource.
In validate methods you do not need to clear the field. The system does that for you when validate returns false.
So instead of this.text('')) just return false.
But I doubt that the idea of users entering the full name is really useful at all.
If you use NameAlias as an alternate item number an even easier option exist.
Change the AliasFor property on the InventTable.NameAlias field to point to ItemId.
When entering in an ItemId and you enter a NameAlias instead, it is translated to the corresponding item id by the AX run-time. This happens everywhere an item id is entered and validated.
I have created a wizard in Ax 2012 using wizard>wizard and i am calling this wizard from Custtablelistpage form... now, i have put some controls in this wizard like CustAccount, and i need to initialize value in this control from selected record in Custtablelistpage form....
I am trying to perform this using Args class, but it is not working, please suggest some solutions..
please create one wizard in AX 2012 using tools>wizard>wizard
then, please put menu item of this wizard somewhere on custtablelistpage.
After that, please put one field named Customer account on welcome tab of wizard.
Now, if you any record that is displayed in custtablelistpage form, please select that.
My task is to display the Account num of selected record to my wizard when i am clicking the menu item button which i have put on custtablelistpage.
Actually, i have written some code,, which is is working absolutely fine for normal forms. but it is not working for Wizard and i am not getting value to initialize in my control on wizard.
Ok, I took some time to try this out and I have two possible solutions for you.
You can do it by using unbound controls and pass in the selected record
Or you could use a datasource on the wizard form and filter on the selected values
First let's try and do it by using a simple unbound control. Start by adding a CustTable member variable and parameter method to your wizard class.
public class MyTestWizardWizard extends SysWizard
{
CustTable mySelectedCustomer;
}
public CustTable parmMySelectedCustomer(CustTable _mySelectedCustomer = mySelectedCustomer)
{
;
mySelectedCustomer = _mySelectedCustomer;
return mySelectedCustomer;
}
Then in your form, you can overwrite the init method and do the following :
void init()
{
int controlid;
FormStringControl fsControl;
;
super();
if (element.Args().caller())
{
sysWizard = element.Args().caller();
// Get the control id of the CustomerId control
controlid = element.controlId(formControlStr(MyTestWizardWizard, CustomerId));
// Check if we actually have a form string control
if(element.control(controlid) is FormStringControl)
{
// Cast to the FormStringControl type
fsControl = element.control(controlid) as FormStringControl;
// Now fill in the field value
fsControl.text(sysWizard.parmMySelectedCustomer().AccountNum);
}
}
else
{
MyTestWizardWizard::main(new args());
element.closeCancel();
}
}
So what you actually do here is just fetch the selected record stored in you wizard class. Then we check if the control we want to assign values to is actually the right control to put the value in.
Though this is working, I would prefer a second method. That would be to use a datasource on the form and put a range on the selected record like this. Just put the CustTable as a datasource on the form and place your control as you would normally do.
Then, make sure the init method is performing the super() call at the bottom to make sure initialisation is done before calling the datasource methods:
void init()
{
;
// make sure the sysWizard is already initialized before the super to make sure the init on the datasource has an instance of sysWizard
if (element.Args().caller())
{
sysWizard = element.Args().caller();
}
else
{
MyTestWizardWizard::main(new args());
element.closeCancel();
}
super();
}
Then overwrite the init method on the datasource to put a range on the recId field of the custTable.
Please mind the you could assign the value of the range in the ExecuteQuery method, but for this case, I just do it here.
public void init()
{
;
super();
SysQuery::findOrCreateRange(this.query().dataSourceTable(tableNum(CustTable)), fieldNum(CustTable, RecId)).value(queryValue(SysWizard.parmMySelectedCustomer().RecId));
}
Now when your wizard is run, the args passes the record to your wizard class, the form picks it up on the init of the datasource and puts a range on the record that you have selected. All the rest of the magic is normal Ax behavior with bound data controls.
So I hope this is what you needed. Please let me know if you have further questions.