Overview
Pattern: Full custom
Ne' il data layer ne' i componenti UI sono del framework. Scrivi Angular standard (eventualmente con PrimeNG come widget set) e chiami il tuo backend via HttpClient. Il framework ti da' solo l'app shell (autenticazione, layout, theming, eventuali servizi di utilita').
Quando usarlo
- UX completamente bespoke (wizard multi-step, designer custom, editor visuale, viewer specializzati).
- Pagina pubblica/landing che non deve usare lo stile della back-office.
- Integrazione con SDK terzi (Stripe checkout, Google Maps custom, video player avanzati).
- Strumenti interni con esigenze molto specifiche dove il pattern framework sarebbe overhead.
- Test, playground, demo isolate.
Architettura
- Sviluppatore: scrive un componente Angular standalone, eventualmente forms reattivi, e chiama il tuo backend con
HttpClient. - Framework: presta solo l'app shell (login cookie, layout, theming). Niente datasource, niente list-grid, niente metadata.
- Backend: un Controller .NET classico (o servizio esterno). Nessuna convenzione del framework.
Cosa fai tu (frontend)
Componente Angular standalone con widget standard. Esempio: tabella PrimeNG + CRUD con HttpClient.
<!-- source: wwwroot/src/app/component/examples/pattern-4/4a-pure-ptable-crud/4a-pure-ptable-crud.component.html -->
<p-table [value]="tasks()" dataKey="id">
<ng-template pTemplate="header">
<tr><th>ID</th><th>Title</th><th>Done</th><th></th></tr>
</ng-template>
<ng-template pTemplate="body" let-row>
<tr>
<td>{{ row.id }}</td><!-- source: wwwroot/src/app/component/examples/pattern-4/4a-pure-ptable-crud/4a-pure-ptable-crud.component.ts -->
import { Component, signal, inject, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
interface TaskItem { id: number; title: string; done: boolean; }
@Component({
selector: 'app-tasks',Cosa fai tu (backend)
Un Controller REST classico. Nessuna integrazione col framework.
<!-- source: WuicTest/Controllers/SamplesController.cs -->
[HttpGet("tasks")]
public IActionResult GetTasks() => Ok(_tasks);
[HttpPost("tasks")]
public IActionResult AddTask([FromBody] TaskItem item)
{
item.Id = _tasks.Count == 0 ? 1 : _tasks.Max(t => t.Id) + 1;Trade-off
| Pro | Contro |
|---|---|
| Massima flessibilita' UX/UI | Devi reimplementare cose pronte (filtri, paging, export, audit) |
| Stack standard Angular/PrimeNG | Niente integrazione con scaffolding e metadata del framework |
| Backend libero, niente convenzioni | Schema e migration tutti a tuo carico |
| Buono per pagine pubbliche o tool isolati | Costo di mantenimento alto se la stessa entity ha anche bisogno della back-office WUIC |
Esempi vivi nel WuicTest
- Pure p-table CRUD → PrimeNG
<p-table>+HttpClientper CRUD su/api/samples/tasks. Cartella sorgente:wwwroot/src/app/component/examples/pattern-4/4a-pure-ptable-crud/. Apri demo. - Pure form wizard →
p-steppermulti-step con reactive forms, submit a/api/samples/registrations. Cartella sorgente:wwwroot/src/app/component/examples/pattern-4/4b-pure-form-wizard/. Apri demo.
> Negli esempi WuicTest i dati lato server sono in liste in-memory: si perdono al restart. E' una semplificazione demo per non aggiungere migration. In produzione sostituisci con EF Core / Dapper / store di tua scelta.
Vedi anche
- Pattern 1 — Full autogeneration: se la stessa entity ha senso anche in back-office standard.
- Pattern 2 — Framework data + Custom component: se la fonte dati e' nel modello del framework ma serve UI custom.
- Pattern 3 — Framework component + Custom data: se vuoi tenere
<wuic-list-grid>mantenendo backend libero. - Pattern 5 — Framework component + Framework data (manual mount): se vuoi layout custom ma entrambi data + widget dal framework.