CRUD

TsgcHTMLComponent_CRUD : la liste, la recherche, la pagination, le formulaire de création et de modification, la confirmation de suppression et le chemin d'écriture d'une table en un seul composant, sur un TDataSet ou sur votre propre SQL, en Delphi, C++ Builder et .NET.

TsgcHTMLComponent_CRUD

La page que toute application métier réécrit pour chaque table, réunie en un seul composant. Donnez-lui un champ clé et un préfixe de route, puis liez un TDataSet ou fournissez-lui un adaptateur de six méthodes sur votre propre SQL. ShowList renvoie le balisage, et ce que la page envoie en retour passe par ProcessAction.

Classe du composant

TsgcHTMLComponent_CRUD, avec TsgcHTMLCRUDAdapter et TsgcHTMLCRUDAdapter_DataSet dans la même unité

Produit

La liste avec recherche et pagination, le formulaire de création et de modification, et la confirmation de suppression

Langages

Delphi, C++ Builder, .NET

Liez un jeu de données, ou écrivez l'adaptateur

Définissez KeyField et RoutePrefix, liez un DataSet actif et appelez ShowList(search, page). Pour votre propre SQL, donnez plutôt au composant un adaptateur avec SetAdapter. Acheminez ce que la page envoie en retour via ProcessAction.

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

Propriétés & méthodes clés

Les membres que vous utilisez le plus souvent.

Adaptateur

TsgcHTMLCRUDAdapter est le chemin d'écriture, avec six méthodes virtuelles : Locate, Read, List, Insert, Update et Delete. TsgcHTMLCRUDAdapter_DataSet pilote le jeu de données lié, et SetAdapter donne au composant votre propre adaptateur et en prend possession. List renvoie une page sous forme de lignes séparées par des tabulations, la clé dans la dernière cellule, et retourne le nombre de lignes de l'ensemble complet.

En .NET

Il n'existe pas de TDataSet, la version .NET fournit donc trois adaptateurs : TsgcHTMLCRUDAdapter_DataTable sur un DataTable, TsgcHTMLCRUDAdapter_List<T> sur n'importe quelle IList<T> et TsgcHTMLCRUDAdapter_DbConnection sur une table derrière une DbConnection, chaque valeur étant envoyée comme paramètre. Déclarez les Columns : elles ne sont pas lues depuis la table.

La page

ShowList(search, page), ShowNew, ShowEdit(key), Save(key, values, html) et DeleteRecord(key, html) renvoient chacun le balisage que l'hôte insère dans la page. ProcessAction aiguille vers elles les actions crudList, crudNew, crudEdit, crudSave et crudDelete envoyées par la page, et répond False pour toute autre action, afin qu'une page puisse contenir plusieurs composants.

Options de la page

Actions est un ensemble de caCreate, caEdit, caDelete, caView et caExport, et une page avec seulement caView est un rapport. EditMode vaut cemModal ou cemPage, ConfirmDelete demande confirmation avant une suppression, PageSize vaut 25 par défaut et ne dépasse jamais 500, et SearchFields liste les champs dans lesquels la zone de recherche cherche, séparés par des points-virgules.

Colonnes

Une colonne TsgcHTMLCRUDColumn possède FieldName, Caption, Visible, ReadOnly, Required, InList, InForm, Width et MaxLength. Si aucune n'est déclarée, le composant les lit depuis le jeu de données actif : le libellé depuis DisplayLabel, l'indicateur « obligatoire » et la longueur, et la clé est affichée mais jamais modifiée. LoadColumnsFromDataSet le fait à la demande.

Validation

Une colonne obligatoire vide et une valeur plus longue que MaxLength sont refusées en premier. Ensuite, OnValidate est appelé : ajoutez une ligne par problème à aErrors et rien n'est écrit, le formulaire revient avec les messages. OnApplyUpdates s'exécute avant l'adaptateur, et si vous affectez aHandled, l'écriture est à vous. OnApplied se déclenche après qu'une écriture a abouti, pour la journaliser ou rafraîchir les autres utilisateurs qui consultent la liste.

Verrouillage optimiste

Nommez un champ de version dans VersionField. Une sauvegarde compare ce que le navigateur envoie avec ce qui est stocké, et refuse l'écriture lorsque quelqu'un d'autre a modifié l'enregistrement entre-temps, de sorte que la deuxième personne qui clique sur Enregistrer n'écrase pas la première.

Maître et détail

Details contient les listes filles d'un enregistrement. Chaque élément nomme un autre TsgcHTMLComponent_CRUD dans CRUD, le champ de la table fille qui contient la clé maître dans MasterField, et un Caption. Elles s'affichent sous le formulaire pendant qu'un enregistrement est en cours de modification. SetMaster(field, value) restreint une liste à un seul enregistrement maître.

Export CSV

Avec caExport, la barre d'outils affiche un lien Exporter vers RoutePath('export.csv'). Répondez à cette route avec GetExportCSV(search) : elle exporte la recherche affichée par la liste, jusqu'à 500 lignes, et non la table entière. Chaque valeur est entre guillemets, de sorte qu'une virgule ou un saut de ligne ne peut pas casser le fichier.

La clé est d'abord localisée

Chaque clé arrive du navigateur. ShowEdit, Save et DeleteRecord demandent à l'adaptateur de la localiser avec Locate avant toute modification ou suppression, de sorte que changer un numéro dans une URL n'atteint jamais un autre enregistrement. Actions est également appliqué : une page sans caDelete refuse une suppression même si un formulaire falsifié en envoie une. Les cellules et les champs sont échappés, de sorte qu'un enregistrement contenant du balisage est affiché comme du texte.

Socket et HTTP

La zone de recherche, Nouveau, Modifier, Supprimer et le formulaire sont des formulaires marqués data-sgc-ws-send, chacun avec des champs cachés action, crud et key, et l'hôte les remet à ProcessAction. Un message envoyé par le socket ne porte aucun chemin et n'atteint jamais le routeur, autorisez-le donc vous-même. En Delphi, TsgcHTMX_Engine_Server.MessageSession renvoie la session associée aux cookies du handshake, ou nil. Pour HTTP, RoutePath construit les chemins qu'un hôte déclare sur le routeur du moteur : /customers, /customers/new, /customers/{id}/edit, /customers/save et /customers/{id}/delete.

Façons de démarrer

Créez-le dans le code, comme ci-dessus, ou utilisez l'assistant de l'IDE Delphi : Tools › New sgcHTML CRUD page liste les jeux de données du formulaire ouvert, lit les champs de celui que vous choisissez et ajoute un composant configuré au formulaire, avec les deux lignes de câblage dans le presse-papiers. Il requiert Delphi 10.4 ou une version ultérieure. En dehors de l'IDE, l'outil en ligne de commande sgcHTMLGen écrit le code source de la page en Object Pascal ou en C#, à partir de la table, du préfixe de route et des champs, chacun écrit sous la forme name:flag, par exemple ID:key ou NAME:req:60.

Disponibilité

Fait partie de sgcHTML, qui est vendu indépendamment de sgcWebSockets. L'unité se compile là où SGC_HTML est défini, ce que sgcVer.inc fait pour le pack HTML sur toutes les plateformes sauf Android et iOS. La démo est Demos\60.HTML\01.RunTime\02.AdminCRUD, où l'espace clients est construit sur ce composant, à côté de la page écrite à la main qu'il a remplacée.

Continuez l'exploration

Aide en ligneGuide d'utilisation des pages CRUD, de l'adaptateur et du chemin d'écriture.
Tous les composants sgcHTMLParcourez la matrice complète des fonctionnalités de plus de 80 composants.
Télécharger la version d'essai gratuiteLa version d'essai de 30 jours fournit les projets de démonstration 60.HTML.
TarifsLicences Single, Team et Site avec code source complet.
Meilleur rapport qualité-prix : All-AccessTous les produits eSeGeCe, Support Premium inclus, à partir de €1,059/an.
Voir les tarifs All-Access

Prêt à démarrer ?

Téléchargez la version d'essai gratuite et commencez à créer des interfaces web en Delphi, C++ Builder et .NET.