CRUD

TsgcHTMLComponent_CRUD: Liste, Suche, Paginierung, Formular zum Anlegen und Bearbeiten, Löschbestätigung und Schreibpfad einer Tabelle als eine einzige Komponente, über ein TDataSet oder Ihr eigenes SQL, in Delphi, C++ Builder und .NET.

TsgcHTMLComponent_CRUD

Die Seite, die jede Geschäftsanwendung für jede Tabelle neu schreibt, als eine Komponente. Geben Sie ihr ein Schlüsselfeld und ein Routenpräfix, binden Sie dann ein TDataSet oder übergeben Sie ihr einen Adapter mit sechs Methoden für Ihr eigenes SQL. ShowList liefert das Markup zurück, und was die Seite zurücksendet, läuft über ProcessAction.

Komponentenklasse

TsgcHTMLComponent_CRUD, mit TsgcHTMLCRUDAdapter und TsgcHTMLCRUDAdapter_DataSet in derselben Unit

Rendert

Die Liste mit Suche und Seitennavigation, das Formular zum Anlegen und Bearbeiten und die Löschbestätigung

Sprachen

Delphi, C++ Builder, .NET

Ein Dataset binden oder den Adapter schreiben

Setzen Sie KeyField und RoutePrefix, binden Sie ein aktives DataSet und rufen Sie ShowList(search, page) auf. Für Ihr eigenes SQL übergeben Sie der Komponente stattdessen mit SetAdapter einen Adapter. Leiten Sie alles, was die Seite zurücksendet, an ProcessAction weiter.

uses
  Classes, sgcHTML_Component_CRUD;

var
  oCRUD: TsgcHTMLComponent_CRUD;
  vHTML: string;
begin
  oCRUD := TsgcHTMLComponent_CRUD.Create(nil);
  try
    oCRUD.CRUDID := 'customers';
    oCRUD.Title := 'Customers';
    oCRUD.RoutePrefix := '/customers';
    oCRUD.KeyField := 'ID';
    oCRUD.PageSize := 15;
    oCRUD.Actions := [caCreate, caEdit, caDelete, caView, caExport];
    oCRUD.VersionField := 'UPDATED_AT';   // optimistic locking
    oCRUD.OnValidate := CustomersValidate;

    // an active dataset: the columns are read off it
    oCRUD.DataSet := qryCustomers;

    vHTML := oCRUD.ShowList('', 1);   // search text, page number
  finally
    oCRUD.Free;
  end;
end;

// The rules that are about your data. Add a line per problem: nothing is
// written and the form comes back with the messages.
procedure TServer.CustomersValidate(Sender: TObject;
  aOperation: TsgcHTMLCRUDOperation; const aKey: string;
  aValues, aErrors: TStrings);
begin
  if Length(Trim(aValues.Values['NAME'])) < 3 then
    aErrors.Add('The name needs at least three characters.');
end;

// A message from the browser carries action, crud and key with the form fields
if oCRUD.ProcessAction(vAction, vKey, oFields, vHTML) then
  aResponse := vHTML;   // the markup to swap into the page

// Or over your own SQL: an adapter of six methods
type
  TCustomersAdapter = class(TsgcHTMLCRUDAdapter)
  public
    function Locate(const aKey: string): Boolean; override;
    function Read(const aKey: string; aValues: TStrings): Boolean; override;
    function List(const aSearch: string; aPage, aPageSize: Integer;
      aRows: TStrings): Integer; override;
    function Insert(aValues: TStrings; var aKey: string;
      aErrors: TStrings): Boolean; override;
    function Update(const aKey: string; aValues, aErrors: TStrings): Boolean;
      override;
    function Delete(const aKey: string; aErrors: TStrings): Boolean; override;
  end;

oCRUD.SetAdapter(TCustomersAdapter.Create(oCRUD));   // the component owns it
// includes: sgcHTML_Component_CRUD.hpp

TsgcHTMLComponent_CRUD *oCRUD = new TsgcHTMLComponent_CRUD(NULL);
try
{
  oCRUD->CRUDID = "customers";
  oCRUD->Title = "Customers";
  oCRUD->RoutePrefix = "/customers";
  oCRUD->KeyField = "ID";
  oCRUD->PageSize = 15;
  oCRUD->Actions = TsgcHTMLCRUDActions() << caCreate << caEdit << caDelete
    << caView << caExport;
  oCRUD->VersionField = "UPDATED_AT";   // optimistic locking
  oCRUD->OnValidate = CustomersValidate;

  // an active dataset: the columns are read off it
  oCRUD->DataSet = qryCustomers;

  String html = oCRUD->ShowList("", 1);   // search text, page number
}
__finally
{
  delete oCRUD;
}

// The rules that are about your data. Add a line per problem: nothing is
// written and the form comes back with the messages.
void __fastcall TServer::CustomersValidate(TObject *Sender,
  TsgcHTMLCRUDOperation aOperation, const String aKey,
  TStrings *aValues, TStrings *aErrors)
{
  if (aValues->Values["NAME"].Trim().Length() < 3)
    aErrors->Add("The name needs at least three characters.");
}

// A message from the browser carries action, crud and key with the form fields
String html;
if (oCRUD->ProcessAction(action, key, fields, html))
  response = html;   // the markup to swap into the page

// For your own SQL, derive from TsgcHTMLCRUDAdapter, override its six methods
// (Locate, Read, List, Insert, Update, Delete) and call oCRUD->SetAdapter().
using System.Collections.Generic;
using esegece.sgcWebSockets;

var crud = new TsgcHTMLComponent_CRUD();
crud.CRUDID = "customers";
crud.Title = "Customers";
crud.RoutePrefix = "/customers";
crud.KeyField = "ID";
crud.PageSize = 15;
crud.Actions = TsgcHTMLCRUDActions.caCreate | TsgcHTMLCRUDActions.caEdit
    | TsgcHTMLCRUDActions.caDelete | TsgcHTMLCRUDActions.caView
    | TsgcHTMLCRUDActions.caExport;
crud.VersionField = "UPDATED_AT";   // optimistic locking

// The key travels with the page: it is in neither the list nor the form
var id = crud.Columns.Add();
id.FieldName = "ID";
id.InList = false;
id.InForm = false;

var name = crud.Columns.Add();
name.FieldName = "NAME";
name.Caption = "Name";
name.Required = true;
name.MaxLength = 120;

// There is no TDataSet: read a DataTable, an IList<T> or a table behind a DbConnection
crud.SetAdapter(new TsgcHTMLCRUDAdapter_DataTable(crud, customersTable));

// The rules that are about your data
crud.OnValidate += (object sender, TsgcHTMLCRUDOperation op, string recordKey,
    List<string> values, List<string> errors) =>
{
    if (TsgcHTMLComponent_CRUD.ValueOf(values, "NAME").Trim().Length < 3)
        errors.Add("The name needs at least three characters.");
};

string html = crud.ShowList("", 1);   // search text, page number

// A message from the browser carries action, crud and key with the form fields
if (crud.ProcessAction(action, key, fields, out string reply))
    response = reply;   // the markup to swap into the page

Wichtige Eigenschaften & Methoden

Die Member, die Sie am häufigsten verwenden.

Adapter

TsgcHTMLCRUDAdapter ist der Schreibpfad, mit sechs virtuellen Methoden: Locate, Read, List, Insert, Update und Delete. TsgcHTMLCRUDAdapter_DataSet steuert das gebundene Dataset, und mit SetAdapter übergeben Sie der Komponente einen eigenen Adapter, dessen Besitz sie übernimmt. List liefert eine Seite als tabulatorgetrennte Zeilen, den Schlüssel als letzte Zelle, und gibt zurück, wie viele Zeilen die gesamte Menge hat.

In .NET

Es gibt kein TDataSet, daher bringt die Portierung drei Adapter mit: TsgcHTMLCRUDAdapter_DataTable über eine DataTable, TsgcHTMLCRUDAdapter_List<T> über eine beliebige IList<T> und TsgcHTMLCRUDAdapter_DbConnection über eine Tabelle hinter einer DbConnection, wobei jeder Wert als Parameter gesendet wird. Deklarieren Sie die Columns selbst, denn sie werden nicht aus der Tabelle gelesen.

Die Seite

ShowList(search, page), ShowNew, ShowEdit(key), Save(key, values, html) und DeleteRecord(key, html) liefern jeweils das Markup, das der Host einsetzt. ProcessAction leitet die gesendeten crudList, crudNew, crudEdit, crudSave und crudDelete an sie weiter und antwortet mit False auf jede andere Aktion, damit eine Seite mehrere Komponenten enthalten kann.

Seitenoptionen

Actions ist eine Menge aus caCreate, caEdit, caDelete, caView und caExport, und eine Seite mit nur caView ist ein Bericht. EditMode ist cemModal oder cemPage, ConfirmDelete fragt vor dem Löschen nach, PageSize ist standardmäßig 25 und geht nie über 500 hinaus, und SearchFields listet die Felder auf, in denen das Suchfeld sucht, durch Semikolons getrennt.

Spalten

Eine TsgcHTMLCRUDColumn hat FieldName, Caption, Visible, ReadOnly, Required, InList, InForm, Width und MaxLength. Sind keine deklariert, liest die Komponente sie aus dem aktiven Dataset: die Beschriftung aus DisplayLabel, dazu das Pflichtfeld-Kennzeichen und die Länge, und der Schlüssel wird angezeigt, aber nie bearbeitet. LoadColumnsFromDataSet erledigt das auf Anforderung.

Validierung

Eine leere Pflichtspalte und ein Wert, der länger als MaxLength ist, werden zuerst abgelehnt. Danach wird OnValidate befragt: Fügen Sie aErrors je Problem eine Zeile hinzu, dann wird nichts geschrieben, und das Formular kommt mit den Meldungen zurück. OnApplyUpdates läuft vor dem Adapter, und wenn Sie aHandled setzen, übernehmen Sie das Schreiben selbst. OnApplied wird ausgelöst, nachdem ein Schreibvorgang durchgelaufen ist, um ihn zu protokollieren oder alle zu aktualisieren, die gerade dieselbe Liste ansehen.

Optimistisches Sperren

Tragen Sie in VersionField ein Versionsfeld ein. Beim Speichern wird verglichen, was der Browser sendet, mit dem, was gespeichert ist, und der Schreibvorgang wird abgelehnt, wenn inzwischen jemand anderes den Datensatz geändert hat. So überschreibt die Person, die als zweite auf Speichern klickt, nicht die Änderung der ersten.

Master und Detail

Details enthält die untergeordneten Listen eines Datensatzes. Jedes Element nennt eine weitere TsgcHTMLComponent_CRUD in CRUD, in MasterField das Feld der Detailliste, das den Master-Schlüssel enthält, und eine Caption. Sie werden unter dem Formular dargestellt, solange ein Datensatz bearbeitet wird. SetMaster(field, value) schränkt eine Liste auf einen Master-Datensatz ein.

CSV-Export

Mit caExport zeigt die Toolbar einen Export-Link auf RoutePath('export.csv'). Beantworten Sie diese Route mit GetExportCSV(search). Exportiert wird die Suche, die die Liste gerade anzeigt, bis zu 500 Zeilen, nicht die ganze Tabelle. Jeder Wert steht in Anführungszeichen, sodass ein Komma oder ein Zeilenumbruch die Datei nicht beschädigen kann.

Der Schlüssel wird zuerst gesucht

Jeder Schlüssel kommt vom Browser. ShowEdit, Save und DeleteRecord lassen den Adapter ihn mit Locate suchen, bevor etwas bearbeitet oder gelöscht wird, sodass das Ändern einer Zahl in einer URL nie einen anderen Datensatz erreicht. Actions wird ebenfalls durchgesetzt: Eine Seite ohne caDelete lehnt einen Löschvorgang auch dann ab, wenn ein gefälschtes Formular einen sendet. Zellen und Felder werden maskiert, sodass ein Datensatz, der Markup enthält, als Text angezeigt wird.

Socket und HTTP

Das Suchfeld, Neu, Bearbeiten, Löschen und das Formular sind Formulare, die mit data-sgc-ws-send markiert sind, jeweils mit den versteckten Feldern action, crud und key, und der Host übergibt sie an ProcessAction. Eine Nachricht über den Socket trägt keinen Pfad und erreicht den Router nie, daher müssen Sie sie selbst autorisieren. In Delphi liefert TsgcHTMX_Engine_Server.MessageSession die Sitzung hinter den Handshake-Cookies oder nil. Für HTTP baut RoutePath die Pfade, die ein Host am Engine-Router deklariert: /customers, /customers/new, /customers/{id}/edit, /customers/save und /customers/{id}/delete.

Möglichkeiten für den Einstieg

Erstellen Sie sie wie oben im Code oder nutzen Sie den Assistenten in der Delphi-IDE: Tools › New sgcHTML CRUD page listet die Datasets des geöffneten Formulars auf, liest die Felder des ausgewählten Datasets und fügt dem Formular eine konfigurierte Komponente hinzu, wobei die beiden Verdrahtungszeilen in der Zwischenablage liegen. Dafür ist Delphi 10.4 oder höher erforderlich. Außerhalb der IDE schreibt das Kommandozeilenwerkzeug sgcHTMLGen den Quelltext der Seite in Object Pascal oder in C# aus der Tabelle, dem Routenpräfix und den Feldern, die jeweils als name:flag angegeben werden, zum Beispiel ID:key oder NAME:req:60.

Verfügbarkeit

Teil von sgcHTML, das unabhängig von sgcWebSockets verkauft wird. Die Unit kompiliert überall dort, wo SGC_HTML definiert ist, was sgcVer.inc für das HTML-Paket auf jeder Plattform außer Android und iOS tut. Die Demo ist Demos\60.HTML\01.RunTime\02.AdminCRUD, in der der Kundenbereich auf dieser Komponente aufgebaut ist, neben der von Hand geschriebenen Seite, die sie ersetzt hat.

Weiter entdecken

Online-HilfeAnleitung zur Verwendung von CRUD-Seiten, des Adapters und des Schreibpfads.
Alle sgcHTML-KomponentenDurchsuchen Sie die vollständige Funktionsmatrix von über 80 Komponenten.
Kostenlose Testversion herunterladenDie 30-Tage-Testversion enthält die 60.HTML-Demoprojekte.
PreiseSingle-, Team- und Site-Lizenzen mit vollständigem Quellcode.
Bestes Preis-Leistungs-Verhältnis: All-AccessAlle eSeGeCe-Produkte, inklusive Premium-Support, ab €1,059 pro Jahr.
All-Access-Preise ansehen

Bereit loszulegen?

Laden Sie die kostenlose Testversion herunter und beginnen Sie, Web-UIs in Delphi, C++ Builder und .NET zu erstellen.