Easy way to create a UI to edit one record with @xdata.proxy field (LAZY association table)

What is the easy way to create a UI-User interface to edit one record with @xdata.proxy field?

1. Project API Database

a. We have XData server publishing a table data with LAZY association to other table and @xdata.proxy in service published

sample of service published:

{ "value": [ {

  "$id": 1,

  "LUID": "59bv2vz3pden",

  "IdSeguridadGrupos@xdata.proxy": "Seguridad_Grupos_Usuarios('59bv2vz3pden')/IdSeguridadGrupos",

  "IdUsuarios@xdata.proxy": "Seguridad_Grupos_Usuarios('59bv2vz3pden')/IdUsuarios"

}  \]}

2. Client interface

a. We are developing a UI-Userinterface FORM with Web Core components using:

i. TXDataWebConnection

ii. TXDataWebDataSet

iii. TWebDataSource

3. Problematic situation:

If we add all fields in fields editor of TXDataWebDataSet a proxy fields are included as TXDataWebEntityField

a.1 Record is not editable if fields TXDataWebEntityField exists, because data is not displayed in TWebDBEdit for all fields,

a.2 If we replace TXDataWebEntityField for TStringField on @xdata.proxy fields, other fields are displayed but @xdata.proxy field is not displayed to edit

-–- This situation is not fine for rapid development ----

4. Questions about solution for rapid development

a. How can easily add all field and work with dataset to edit a record?

b. How can easy edit a @xdata.proxy with dataset and without extra code for edit with TWebDBEdit and TWebDBLookupComboBox?

You can use the $expand param to force the server to return the inlined association object, it makes more sense since you want to use its data right away.

This was discussed here:

And here:

Test (with QueryString and SubpropsDepth=1)

$expand was added: TXdataWebDataSet.QueryString = $expand=IdUsuarios and TXdataWebDataSet.SubpropsDepth=1

Now, We can display data for all fields, but relational fields are not editable under the following conditions:

a.1 Record is not editable if fields TXDataWebEntityField exists in TXdataWebDataSet, because data is not displayed in TWebDBEdit for all fields

a.2 If we replace TXDataWebEntityField with TStringField on @xdata.proxy fields, other fields are displayed but @xdata.proxy field is not displayed to edit

Please your comments about of:

  1. TXdataWebDataSet is not working if TXDataWebEntityField exists
  2. How can edit field @xdata.proxy in TXdataWebDataSet ?

Can you elaborate on this? Do you have a sample project?
The presence or absence of TXDataWebEntityField shouldn't affect the other fields in the dataset.

If you use $expand, the @xdata.proxy field won't exist (for example, no IdUsuarios@xdata.proxy, only the entity field named IdUsuarios, which contains the full usuario object. To update the field, you should replace it with another full object.

I created a demo to test data editing functionalities, using TXDataWebConnection and TXDataWebDataSet to retrieve data. The project uses simple test data and consists of two parts: a data server and a UI client.

  1. When TXDataWebDataSet.Filter is active, the data is not displayed. I’m not sure where my mistake is.

  2. I’m trying to edit the IDCountry field in the data sample using a TWebDBLookupComboBox. Could you please help me configure it to work directly and without extra code? (Yellow component in UI)

    DemoTest.zip (96.8 KB)

You have to use a TWebComboBox and set things manually. Here is the modified project that illustrates how to do it.

DemoTestProjects.zip (27.4 KB)

In RAD development, 'no-code' component functionality is a priority. I've updated the demo to include a VCL/Aurelius example using cbCountry (TDBLookupComboBox). I propose enhancing the TWebDBLookupComboBox in Web Core to support similar out-of-the-box functionality without requiring manual event handling.

I have attached the extended project

TMS Components XData-Aurelius-WebCore.zip (181.4 KB)

In the demo under Demo\Basics\DBLookupCombo, there is a sample for a codeless implementation.
We'll investigate what to do to have a similar setup with the TXDataWebDataSet or what prevents us from doing this.

For a large-scale project featuring hundreds of forms and a multi-layered architecture:

  1. The database is exposed via a Sparkle/XData server.

  2. The web client connects to the data using TXDataWebConnection and TXDataWebDataSet.

At this stage, it is crucial to determine if TWebClientConnection and TWebClientDataSet should replace the TXData components, or which stack is better suited for performing CRUD operations with minimal additional code. I noticed that the 'Demo\Basics\DBLookupCombo' example populates data manually rather than connecting to Sparkle/XData.

Every client form will include Dataset components for the various tables, which are bound to TWebDBEdit controls for editing. For related tables, TWebDBLookupComboBox is used; this is the reason for my previous inquiries regarding its implementation, as I am seeking the most efficient way to edit and update record data.

Please make a feature request under

New functionality request

https://support.tmssoftware.com/t/enhanced-webcore-xdata-integration-for-lazy-associations-in-txdatawebdataset-and-twebdblookupcombobox/26857

I created a simple workaround: just add one line of code in the OnChange event of TWebDBLookupComboBox:

WebDBLookupComboBoxXDataProxySync(Sender as TWebDBLookupComboBox);

And then add the following procedure:

procedure WebDBLookupComboBoxXDataProxySync(Lcbb: TWebDBLookupComboBox);
var
LDatasetMain: TXDataWebDataSet;
LDatasetList: TXDataWebDataSet;
LDataField: string;

function ObjProxyName(AFieldName: string): string;
var
p: Integer;
begin
p := Pos('.', AFieldName);
if p > 0 then
result := Copy(AFieldName, 1, p - 1)
else
result := AFieldName;
end;

begin
if (Lcbb.DataSource <> nil) and (Lcbb.DataSource.DataSet <> nil) and (ObjProxyName(Lcbb.DataField) <> '') and (Lcbb.DataSource.DataSet.FieldByName
(ObjProxyName(Lcbb.DataField)) <> nil) and (Lcbb.ListSource <> nil) and (Lcbb.ListSource.DataSet <> nil) then
begin
LDatasetMain := Lcbb.DataSource.DataSet as TXDataWebDataSet ;
LDataField := ObjProxyName(Lcbb.DataField);
LDatasetList := Lcbb.ListSource.DataSet as TXDataWebDataSet;
LDatasetMain.FieldByName(LDataField).Value := TJSObject(LDatasetList.CurrentData);
end;
end;

This solution updates the value of @xdata.proxy fields.

1 Like