public void executeQuery()
{
qbrLoad.value(loadId);
super();
if (detailUnmatched)
{
element.args().lookupRecord(TMSFreightBillDetail::find(detailUnmatched.FreightBillRecId));
tmsFreightBillDetail_ds.research(false);
}
}
it will give infinite loop.
try like below :
if (detailUnmatched)
{
tmsFreightBillDetail_ds.positionToRecord(TMSFreightBillDetail::find(detailUnmatched.FreightBillRecId));
}
http://happydev/Teams/Client/Pages/Code%20Migration%20-%20FindRecord%20FindValue.docx
{
qbrLoad.value(loadId);
super();
if (detailUnmatched)
{
element.args().lookupRecord(TMSFreightBillDetail::find(detailUnmatched.FreightBillRecId));
tmsFreightBillDetail_ds.research(false);
}
}
it will give infinite loop.
try like below :
if (detailUnmatched)
{
tmsFreightBillDetail_ds.positionToRecord(TMSFreightBillDetail::find(detailUnmatched.FreightBillRecId));
}
http://happydev/Teams/Client/Pages/Code%20Migration%20-%20FindRecord%20FindValue.docx
Code Migration – findRecord and findValue methods on FormDataSource
Overview
The findRecord(Common record) method finds a specific record
in the data source and makes it the current record.
The findValue(FieldId field, str value) method find a
specific value in a specific field in the data source and makes the
corresponding record the current record. It uses the findRecord method for
this.
The problem with these methods is that they use linear
searching. This causes a large number of records to be loaded in memory and
impacts performance.
Replacement APIs – positionToRecord and positionToRecordByValue
The framework team has made available replacement APIs for
the findRecord and findValue methods. The new APIs have the same signature as
the old APIs to ensure easy migration but work differently under the covers.
Also note that while we expect these to cover most cases there are limitations
(details below).
·
public
boolean positionToRecord(Common _record)
Replacement for: public boolean
findRecord(Common _record)
·
public
boolean positionToRecordByValue(FieldId _field, str _value)
Replacement for: public boolean
findValue(FieldId _field, str _value)
Details and Limitations of replacement APIs
The new APIs first try and look for the record in the cache.
This part works without any restrictions on the underlying data sources.
However if the record cannot be found in the cache the APIs will try to use
positioning as long as the underlying data sources support it.
Some cases where positioning and therefore the APIs do not
work are:
•
When a View is being used as a data source
•
When a Temp Table is being used as a data source
•
When a Union Query is being used
•
If firstOnly is being used
•
If an Order By does not exist
•
If all data sources (QueryBuildDataSource) are
set as enabled = false
To keep things simple we have designed the API to always
throw an exception when the underlying data source does not support
positioning, even if the record is in the cache.
Migration
•
A fixer is being written by the Client team to
replace all calls in supported scenarios to new APIs.
•
Application
teams need to manually investigate and migrate the occurrences remaining after
the fixer has been run.
•
Application
teams will also need to migrate any findRecord and findValue override methods.
•
For cases where the new APIs do not work you
could try using
o element.args().lookupRecord(recordToFind) Followed by
o FormDataSource.research(false);
FormDataSource
is the data source that contains the record you want to find. Passing in a
“false” argument to research causes it to not retain the current position since
we want to change the position to the record we found using args.lookupRecord.
It also avoids resetting sort order, ranges, etc.
Old Migration Notes from Application Teams
Note: These notes pre-date the
introduction of the positionToRecord and positionToRecordByValue APIs and are
kept here for reference only. You should try and use positionToRecord and
positionToRecordByValue first. If that does not work for your scenario you
could try one of the solutions listed here to see if it helps.
Pattern
|
Explanation
|
Solution
|
Lookup
form
|
The
form tries to find the record that the caller supplied via args.record()
|
Set
args.lookupRecord() when opening the form.
|
Tmp
= current.data();
DS.ExecuteQuery();
DS.FindRecord(tmp);
|
An
action is triggered that updates/adds/removes multiple records other than the
active record, and the form needs to be refreshed to show the new set of
records while retaining position
|
Call
DS.research(true)
The
true argument tells the framework to retain current position.
|
An
action is triggered that updates/adds/removes multiple records in a linked
datasource, and the form needs to be refreshed to show the new set of
records while retaining position.
|
Call
research() on the linked datasource instead of main datasource. Consider
research(true) if position should be retained in the linked datasource as
well.
|
|
Tmp
= current.data();
DS.research();
DS.FindRecord(tmp);
|
To
refresh the current record, e.g. from a caller
|
element.doResearch();
|
Temporary
records
|
Temporary
records are recreated and form needs to find the same (but not identical)
record after pointing form at new set of records
|
To
be determined
|
Loop:
FindValue+MarkRecord
|
To
be determined
|
|
Using
FindRecord() to find a record in root datasource
|
Element.args().lookupRecord(the
record to find);
DS.research(false)
Note
that this will cause the pagination to start with this record like in a
lookup form, so even if there are only a few records, some of those records
may be hidden from the user until the user pages left.
|
|
Using
FindRecord() to find a record in an active/passive joined datasource
|
A
form has 2 datasources: headerTable and lineTable. FindRecord is used on the
lineTable instead of the parent table.
For
instance, the ProjInvoiceJournal form supports a special case of lookup,
where the form is called from a project transaction. In this case, the ProjInvoiceJournal
form will show the invoice in which the transaction was billed, and also move
to the specific invoice line that billed the calling transaction.
Another
use case is in TrvExpenses. When an employee files an expense report, some
expense types, like Hotel, may require an itemization of values. In this
case, a table is shown and the user may declare how much was spent on each
sub category (Room rate, laundry, internet, ..) per day. An itemization for a
long stay may contain 50-100 entries. Each cell has its own RecId. When the
user tries to edit/clear a cell value, findValue() is used to move the DS
cursor to the desired record for update. Contact: pevezzac
Repro
steps:
1.
In USSI
2.
Open Expense management > Common
> My expenses > Expense reports
3.
Select the record 000030, Conference
and click Expense lines
4.
In the hotel line, click Edit and
open the Itemize tab
5.
Change the cell (Daily room rate;
Tue, 26, Jan) value to 50
6.
Change the cell (Daily room rate;
Tue, 27, Jan) value to 50
7.
Hit Save
Expected:
The bottom of the page shows: Itemized cost = 410, Remaining = 40
|
To
be determined. LookupRecord() + research(false) only works on root
datasources. A solution is needed for the child datasource scenario.
|
Using
findRecord/findValue for datasource bound to a view.
|
When
the datasource is bound to a view it is losing the ordering on the query when
using the lookupRecord/research replacement pattern.
Need
the ability to bind to a view sorted by the natural key of the view, such as
a Name field, and then be able to find records without losing the query
ordering.
Repro
steps:
1.
Click New
2.
Enter the name New in the drop dialog
and click Create
Expected:
The
list is updated to show the New record and the record is selected in the
list.
|
Additional notes on args.lookupRecord() + research(false) in a
non-lookup scenario
this will cause the pagination to start at the
record set in lookup record, which may be confusing if there are multiple
records, as the user might have the middle record selected and then afterwards,
the top record (the same record) is now selected and a different set of records
are in practice shown on the screen.