praxis-dynamic-form
Este documento e a referencia canonica da API JSON de praxis-dynamic-form.
Summary
- Tipo documental: API reference canonica de contrato JSON.
- Source of truth: runtime e codigo declarados no frontmatter.
- Objetivo operacional: consulta rapida, auditavel e deterministica sob pressao.
- Resumo funcional herdado: Referencia canonica da JSON API do
praxis-dynamic-form, com foco em:
Canonical authoring semantics
Em Geral → Dados do formulário,
Modo de dadoseModo de exibiçãosão preferências independentes.bindings.presentationModeGlobalreutiliza o input runtime existente:true= Apresentação (efetiva somente emview),false= Campos de formulário,null/ausência = Automático, seguindolayoutPolicy.Em replace-all, omitir a preferência remove o override anterior;
falsedeve ser preservado. Não existe um quarto valor embindings.mode.O Page Builder projeta a preferência nos inputs do widget, preservando ausência de
configem formulários schema-driven. No editor do runtime, Apply/Save também publicammodeepresentationModeGlobalemconfigPatchChange.inputPatch.contextSnapshot.presentationcontinua reservado aos estilos (tipografia, densidade e alinhamento), editáveis nos dois caminhos pela aba Estilo da apresentação; não é o seletor de ativação. O Filter Form não oferece o seletor de exibição porque seu runtime não suporta apresentação.DynamicFormAuthoringDocumente o snapshot canonico completo de autoria depraxis-dynamic-form.Quando aplicado por fluxos canonicos de editor,
config,bindingsecontextSnapshotpossuem semanticareplace-all.Ausencia de
bindings.modelimpa o binding persistido e restaura o modo default efetivo do host.Ausencia de
backConfig,presentationouschemaPrefsno documento canonico significa remocao explicita do bloco ausente.backConfig,presentationeschemaPrefspermanecem fora deFormConfig, mas fazem parte oficialmente do documento autoral persistivel emcontextSnapshot.APIs de compatibilidade como
applyConfigFromAdapter(...)continuam aceitando payloads legados/parciais com semanticamerge-compat, preservando campos nao informados.
Backend-owned reactive determinations
x-ui.reactiveDeterminationse lido exclusivamente do request schema exato retornado por/schemas/filtered; nao integra nem e persistido emFormConfig.- O runtime aceita somente o contrato fechado normalizado por
normalizeReactiveDeterminations: triggeron-change, scope de create/edit, capabilityPOST, no maximo 64 bindings totais, JSON Pointers sem duplicidade ou sobreposicao hierarquica e provenance estrutural. A lista e um unico grafo canonico: uma definicao invalida rejeita a projecao inteira, sem execucao parcial. href, request/response schemas e bindings sao compilados pelo Praxis Metadata. O Angular nao aceita callback, headers, method, URL ou write policy autorados pelo host/editor/LLM.- Cada valor ou status relevante invalida imediatamente a geracao anterior, antes do debounce da proxima chamada; somente a geracao ainda autoritativa pode aplicar a resposta.
- Hrefs protocol-relative, com separadores codificados ou resolvidos fora da origem configurada da API falham de forma fechada.
- A resposta so e aplicada quando todos os bindings existem. Os controles alvo aninhados sao preenchidos antes da notificacao dos observers; determinacoes encadeadas recebem um unico sinal logico depois do commit completo, nao um disparo por output. A ordem da cadeia e derivada dos bindings existentes: downstream aguarda a geracao upstream e so executa apos outputs autoritativos ou inputs confirmados como inalterados. Output upstream
null/undefinede geracao upstream com erro, invalida ou cancelada encerram downstream comoskipped, sem chamada com dado ausente ou obsoleto. Se um controle rejeitar a escrita, o runtime tenta restaurar os anteriores e emite falha terminal. O resultado tem semantica fechada server-derived e substitui o draft alvo; o commit e um batch coordenado no cliente, sem promessa de transacao ACID. - O estado permanece pending durante debounce, validacao assincrona e execucao. Uma tentativa de submit aguarda estabilizacao com timeout e repete a espera depois de hooks que podem alterar controles.
- Controles de output sao desabilitados transitoriamente como valores server-derived, sem mutar/persistir
FormConfig; seus valores continuam emgetRawValue(),valueChangee no payload de submit. Depois da hidratacao, fonte inicialmente preenchida entra empendinge e determinada antes de o draft ser considerado estavel; fonte inicial vazia encerra comoskipped/initial-source-empty, satisfeita e sem HTTP. Alteracao programatica posterior em output owned invalida a autoridade anterior e reexecuta a capability. reactiveDeterminationExecutedpublica apenas IDs, paths, provenance, estado (pending,success,skippedouerror), duracao, correlation ID e motivo. Valores do formulario e da resposta nao participam da evidencia.- Hosts compostos recebem estado agregado por
reactiveDeterminationPendingChange. Antes de navegar ou fechar, devem consultarhasPendingReactiveDeterminations()ehasUnsatisfiedReactiveDeterminations()e aguardarwaitForReactiveDeterminations(timeoutMs?); retornofalseindica timeout ou geração mais recente sem draft autoritativo e bloqueia a transição. Correlações canceladas recebem terminalskipped/superseded. - Cascatas de opcoes continuam em
optionSource.dependsOn; recommendations, side-effect refresh, backend validation e workflow actions permanecem capacidades separadas. - O comando backend final continua responsavel por autorizacao, recomputacao e validacao de qualquer decisao consequente.
AI assistant and semantic authoring boundary
praxis-dynamic-form usa o copiloto semantico Praxis como superficie assistiva contextual, nao como fonte primaria de regra de negocio. O componente pode abrir o assistente a partir de controles de configuracao, floating help ou selecao do canvas, mas a presenca global, minimizacao e retomada da sessao pertencem ao PraxisAssistantSessionRegistryService.
Contrato operacional:
- a integracao nova deve abrir
PraxisAiAssistantShellComponent;PraxisAiAssistantComponentpermanece legado para novos fluxos inteligentes; - a identidade canonica da sessao segue
form:{routeKey}:{componentInstanceId || formId || 'form'}; - o contexto assistivel publico e
PraxisAssistantContextSnapshot, comidentity,target,contextItems,authoringManifestRef,resourcePath,schemaFields, digests seguros e hints de governanca; - o snapshot pode apontar para
field,schemaBackedField,localField,section,row,column,visualBlock,formAction,messageourule, mas nao deve transportarform.value,rawFormData, config completa, notas privadas, estado runtime bruto, diagnostics arbitrarios,pendingPatch,File,Blob, bytes, base64 oupreviewUrl; - turnos do assistente usam
AgenticAuthoringTurnClientServicee/api/praxis/config/ai/authoring/turn/stream/**; indisponibilidade do transporte falha de forma fechada e nao reabre o caminho legadogetPatch; - o grounding do turno pode incluir
schemaFieldsedataProfileestruturais produzidos pelo adapter, mas nunca valores dos controles; anexos sao reduzidos a nome, tipo, MIME, tamanho, origem e indicador de preview; - edicao local so pode ser aplicada quando a resposta for compilada para
componentEditPlanvalidado pelo manifesto autoral do componente; - patches livres retornados por backend/LLM sem plano compilado sao rejeitados pelo turn flow;
- pedidos sobre regra de negocio compartilhada, elegibilidade, compliance, LGPD, politica, acesso, aprovacao, publicacao, materializacao ou enforcement devem virar handoff governado para
domain-rules, nao patch local de formulario; - em
mode="view"sem customizacao, ou quando o host estiver readonly, o assistente opera apenas eminline-help,explainediagnose;local-applyemanifest-compileficam bloqueados.
Essa fronteira preserva a premissa de plataforma: o formulario materializa e explica decisoes governadas, mas nao redefine sozinho a semantica canonica da decisao.
Scope and positioning
- Escopo: contrato JSON publico e limites de comportamento observavel.
- Fora de escopo: tutorial de adocao e walkthrough operacional detalhado.
- Posicionamento: referencia canonicamente governada para consumidores, arquitetos e mantenedores.
Source of truth
| Source | Kind | Notes |
|---|---|---|
| projects/praxis-dynamic-form/src/lib/praxis-dynamic-form.ts | runtime-code | Source de implementacao declarado no repositorio. |
| projects/praxis-dynamic-form/src/lib/praxis-dynamic-form.html | template-style | Source de implementacao declarado no repositorio. |
| projects/praxis-dynamic-form/src/lib/config-editor/praxis-dynamic-form-config-editor.ts | runtime-code | Source de implementacao declarado no repositorio. |
| projects/praxis-dynamic-fields/src/lib/directives/dynamic-field-loader.directive.ts | runtime-code | Source de implementacao declarado no repositorio. |
| projects/praxis-core/src/lib/models/form/form-config.model.ts | runtime-code | Source de implementacao declarado no repositorio. |
| projects/praxis-core/src/lib/models/form/form-layout.model.ts | runtime-code | Source de implementacao declarado no repositorio. |
Support legend
- Active: suportado e observado no runtime atual.
- Partial: suporte parcial, com restricoes conhecidas.
- Declared-only: declarado em tipos/schema sem ligacao runtime confirmada.
- Schema-only: presente em schema/modelo sem confirmacao de execucao.
- Deprecated: mantido por compatibilidade legada com migracao prevista.
Contract classification
Canonical paths (public contract)
| Path | Type | Required | Default | Status | Notes |
|---|---|---|---|---|---|
sections[] |
not-specified | not-specified | n/a | Active | Render estrutural principal (section/row/column). |
fieldMetadata[] |
not-specified | not-specified | n/a | Active | Fonte de campos para DynamicFieldLoader. |
metadata |
not-specified | not-specified | n/a | Active | Usado em reconciliacao/snapshot/status de schema. |
actions |
not-specified | not-specified | n/a | Active | Render de praxis-form-actions e roteamento de eventos. |
behavior |
not-specified | not-specified | n/a | Partial | Subset funcional (detalhado abaixo). |
api |
not-specified | not-specified | n/a | Declared-only | Declarado no modelo; sem binding operacional direto no runtime atual. |
messages |
not-specified | not-specified | n/a | Partial | Chaves principais de submit/confirmacao usadas; contrato e mais amplo. |
formRules |
not-specified | not-specified | n/a | Active | Aplicadas no pipeline de regras do runtime. |
formCommandRules |
not-specified | not-specified | n/a | Active | Regras condicionais de comando avaliadas sobre formData estabilizado depois de formRules; primeiro corte suporta global-action. |
formRulesState |
internal-round-trip | Gerado pelo builder visual; nao e alvo de autoria manual ou IA. | n/a | Internal | Estado visual derivado de formRules para reabertura do editor. |
hooks |
not-specified | not-specified | n/a | Active | Integracao de ciclo (before/after) via runtime de hooks. |
hints |
not-specified | not-specified | n/a | Declared-only | Mantido no contrato/editor; sem render dedicado no template principal. |
helpPresentation |
FormHelpPresentationConfig |
No | { display: "inline" } |
Active | Politica visual para exibir hint/helpText dos campos sem alterar semantica dos DTOs; erros de validacao continuam inline. |
presentation |
FormPresentationConfig |
No | runtime defaults | Active | Preferencias tipadas de label/value para modos read-only e presentation. Valores numericos de tamanho e largura sao materializados como comprimentos CSS em px; o mesmo shape alimenta o snapshot canonico do editor. |
fieldMetadata[].array |
FieldArrayConfig |
No | n/a | Active | Contrato de Editable Collection apenas quando fieldMetadata[].controlType === "array" ou quando x-ui.array foi publicado explicitamente. |
Nota editorial:
praxis-dynamic-formcarrega e orquestraFieldMetadata, mas a resolução devaluePresentationem display/read-only pertence ao runtime de@praxisui/dynamic-fields.fieldMetadata[].source,fieldMetadata[].transientefieldMetadata[].submitPolicygovernam campos locais do host. Campos comsource: "local"outransient: trueparticipam de validação, regras, visibilidade evalueChange, mas são omitidos deformSubmit.formDatae do payload HTTP por default.fieldMetadata[].submitPolicytem prioridade sobresourceetransient:includeforça envio,omitforça omissão eincludeWhenDirtyenvia apenas quando o controle estiver dirty.- Dentro de
array.itemSchema.fields,includeWhenDirtyconsidera o item ou subcampo especifico dirty, comoparticipantes.0ouparticipantes.0.observacao. OFormArraypai dirty, comoparticipantes, nao torna todos os subcampos de todos os itens elegiveis para submit. - O evento
formSubmitmantémformDatacomo payload persistível filtrado e expõerawFormDatapara hosts que precisam ler os campos locais/transientes no contexto de UI. - O evento
payloadPreviewChangeprojeta o payload persistível atual sem executar hooks de submit nem disparar HTTP.formDatausa o mesmo pipeline síncrono de normalização/políticas do submit,rawFormDatapreserva o estado completo echangedFieldslista somente paths de controles dirty. - Botões com
type="reset"preservam a semântica canônica de reset mesmo quando recebem umideditorial próprio. O runtime impede o reset nativo do navegador, restaura o snapshot hidratado, marca o formulário como pristine/untouched e publica nova prévia comreason: "reset". - Configs persistidas são reconciliadas com o schema estrutural antes da montagem. Campos locais explícitos são preservados, mas campos server-backed recebem novamente a semântica publicada pelo backend, incluindo
endpoint,resourcePath,optionLabelKeyeoptionValueKey. - Para selects com
x-ui.endpointterminando em/options/filter,endpointé a operação concreta de opções eresourcePathé o recurso dono. O runtime deve chamar/options/filter; não deve converter esse endpoint para/filter.
Supported legacy paths
Nenhum path legado suportado foi identificado nesta revisão baseada em evidência textual preservada.
Internal-only paths
| Path | Internal consumer | Runtime presence | Public support | Notes |
|---|---|---|---|---|
__formConfigKey (storage key derivado) |
persistencia interna (ASYNC_CONFIG_STORAGE) |
Yes | No | Chave computada por formId/componentInstanceId; não faz parte do contrato JSON. |
schema-meta:* (storage namespace) |
verificação de drift de schema | Yes | No | Usado por verifyServerSchemaVersion() para status/outdated. |
Experimental paths
| Path | Enablement (flag/guard) | Stability | Rollout notes | Notes |
|---|---|---|---|---|
behavior.reactiveValidation |
feature flag no contrato + runtime checks | Partial | Disponível; requer validação de carga para forms grandes | Debounce configurável por reactiveValidationDebounceMs. |
Overview
Este arquivo foi adaptado para o padrao canonico atual sem remover conteudo tecnico existente. O conteudo detalhado anterior foi preservado para manter rastreabilidade historica e reduzir perda de contexto.
Public contract surface
Top-level configuration blocks
| Block | Purpose | Required | Merge strategy | Notes |
|---|---|---|---|---|
sections[] |
Estrutura principal de layout (section/row/column) | Yes | replace-array | Base para render e ordenação visual. |
fieldMetadata[] |
Definição dos campos e componentes dinâmicos | Yes | replace-array | Consumido por DynamicFieldLoaderDirective. |
metadata |
Metadados de versão/origem/schema | No | deep-merge | Usado em status, drift e rastreabilidade. |
actions |
Ações de formulário (submit/cancel/custom) | No | deep-merge | Roteadas para outputs e confirmação condicional. |
behavior |
Regras de UX/validação/edição | No | deep-merge | Inclui confirmação em dirty, validação reativa e overlays. |
messages |
Mensagens de UX e feedback | No | deep-merge | Fallback para mensagens default quando ausente. |
formRules |
Regras declarativas de runtime | No | replace-array | Aplicadas no pipeline de rulesService. |
formCommandRules |
Comandos condicionais governados | No | replace-array | Executa GlobalActionRef estruturado depois que valores calculados de formRules estabilizam. |
hooks |
Hooks before/after por estágio | No | replace-array per stage | @Input() hooks pode sobrescrever config.hooks. |
Nested configuration blocks
| Path | Type | Required | Default | Constraints | Notes |
|---|---|---|---|---|---|
sections[] |
not-specified | not-specified | n/a | component-defined | Render estrutural principal (section/row/column). |
fieldMetadata[] |
not-specified | not-specified | n/a | component-defined | Fonte de campos para DynamicFieldLoader. |
metadata |
not-specified | not-specified | n/a | component-defined | Usado em reconciliacao/snapshot/status de schema. |
actions |
not-specified | not-specified | n/a | component-defined | Render de praxis-form-actions e roteamento de eventos. |
behavior |
not-specified | not-specified | n/a | component-defined | Subset funcional (detalhado abaixo). |
api |
not-specified | not-specified | n/a | component-defined | Declarado no modelo; sem binding operacional direto no runtime atual. |
messages |
not-specified | not-specified | n/a | component-defined | Chaves principais de submit/confirmacao usadas; contrato e mais amplo. |
formRules |
not-specified | not-specified | n/a | component-defined | Aplicadas no pipeline de regras do runtime. |
formRulesState |
internal-round-trip | Gerado pelo builder visual; nao e alvo de autoria manual ou IA. | n/a | internal-derived | Estado visual derivado de formRules para reabertura do editor. |
hooks |
not-specified | not-specified | n/a | component-defined | Integracao de ciclo (before/after) via runtime de hooks. |
sections[].sectionHeader |
FormSectionHeaderConfig |
No | n/a | Active | Header visual rico da seção com suporte a avatar dinâmico resolvido a partir de formData. |
Editable Collection field contract
Editable Collection e o contrato publico para listas editaveis de objetos dentro de fieldMetadata[].
O runtime trata um campo como Editable Collection somente quando o campo declara controlType: "array" ou quando a metadata veio com array explicitamente. Um schema OpenAPI com type: "array" usado por controles simples, como chipInput ou multiSelect, nao deve receber fieldMetadata[].array por normalizacao implicita.
Subconjunto suportado no beta atual:
| Path | Type | Required | Default | Status | Notes |
|---|---|---|---|---|---|
fieldMetadata[].controlType |
"array" |
Yes | n/a | Active | Seleciona pdx-editable-collection via Dynamic Fields. |
fieldMetadata[].array.itemType |
"object" |
Yes | "object" |
Active | O MVP monta cada item como FormGroup. Arrays simples usam controles proprios, nao Editable Collection. |
fieldMetadata[].array.mode |
"cards" |
No | "cards" |
Active | Primeiro renderizador oficial. Modos table, drawer, accordion, wizard, chips permanecem fora do contrato beta. |
fieldMetadata[].array.itemSchemaRef |
string |
Conditional | n/a | Active | Referencia OpenAPI do DTO de item quando publicada pelo backend. |
fieldMetadata[].array.itemSchema.fields |
FieldMetadata[] |
Conditional | [] |
Active | Metadata resolvida/inline usada para criar os subcontroles do item. |
fieldMetadata[].array.itemIdentityField |
string |
No | n/a | Active | Preserva identidade de item existente quando o valor inicial contem o campo. |
fieldMetadata[].array.minItems |
number |
No | n/a | Active | Validador agregado do FormArray. |
fieldMetadata[].array.maxItems |
number |
No | n/a | Active | Validador agregado e limite operacional de adicao. |
fieldMetadata[].array.operations.add |
boolean |
No | true |
Active | Governanca metadata-driven da acao adicionar. |
fieldMetadata[].array.operations.edit |
boolean |
No | true |
Active | Quando falso, subcampos de item entram em modo somente leitura. |
fieldMetadata[].array.operations.remove |
boolean |
No | true |
Active | Governanca metadata-driven da acao remover. |
fieldMetadata[].array.deleteMode |
"removeFromPayload" |
No | "removeFromPayload" |
Active | Remocao exclui a linha do array final em formSubmit.formData. |
fieldMetadata[].array.collectionValidation.uniqueBy |
string[] |
No | n/a | Active | Detecta duplicidade somente em chaves completas; linhas incompletas nao geram erro prematuro. |
fieldMetadata[].array.collectionValidation.exactlyOne |
{ field, value, message? } |
No | n/a | Active | Exige exatamente um item com valor tipado estritamente igual. |
fieldMetadata[].array.collectionValidation.atLeastOne |
{ field, value, message? } |
No | n/a | Active | Exige pelo menos um item com valor tipado estritamente igual. |
O host deve persistir formSubmit.formData para fluxos normais. formSubmit.rawFormData existe para auditoria, diagnostico e hooks de UI, mas nao substitui o payload normalizado.
Input bindings
initialValue is an active component input for host-authored or complementary
field values. In edit/view, the runtime applies it without redefining the
canonical remote entity loaded through resourcePath and resourceId. In
create, including item-scoped command forms, it is the only supported source
of initial values: a contextual resourceId never triggers entity hydration.
| Binding/Path | Type | Required | Source | Runtime normalization | Notes |
|---|---|---|---|---|---|
config |
FormConfig |
Conditional | component-input | normalizeFormConfig(config) |
Contrato principal quando fornecido diretamente pelo host. |
resourcePath |
string | undefined |
Conditional | component-input | crud.configure(resourcePath) |
Endpoint base para schema e dados remotos. Alternativa canônica: schemaUrl explícito. |
resourceId |
string | number | undefined |
No | component-input | update pendingEntityId; hydrate only in edit/view |
Carrega entidade em modo edit/view. Em create, pode identificar o item dono de um comando sem iniciar leitura nem bloquear os campos. |
mode |
'create' | 'edit' | 'view' |
No | component-input/storage | persistido em formInputsKey |
Preferência de modo pode ser hidratada do storage. |
schemaSource |
'resource' | 'filter' |
No | component-input | runtime branch | Seleciona caminho de obtenção de schema quando schemaUrl não é informado. |
schemaUrl |
string | null | undefined |
Conditional | component-input | parsed as /schemas/filtered contract |
Fonte canônica explícita para inicialização schema-backed sem depender de resourcePath. |
readUrl |
string | null | undefined |
No | component-input | resolved via API origin and {id} placeholders |
URL concreta de leitura publicada por surface VIEW/READ_PROJECTION; quando presente, substitui crud.getById na hidratação da entidade. |
submitUrl |
string | null | undefined |
Conditional | component-input | resolved via API origin | URL concreta de submit publicada por surface/action; exige submitMethod quando usada para envio HTTP. |
submitMethod |
'post' | 'put' | 'patch' | null | undefined |
Conditional | component-input | normalized lowercase | Método HTTP concreto de submit publicado por surface/action; exige submitUrl quando usado para envio HTTP. |
submitIdempotencyKey |
string | null | undefined |
No | action execution contract | Idempotency-Key |
Identidade estável da tentativa; deve ser reutilizada em retries da mesma execução. |
submitCorrelationId |
string | null | undefined |
No | action execution contract | X-Correlation-Id |
Correlação de observabilidade do comando entre host e backend. |
submitResourceVersion |
string | number | null | undefined |
Conditional | action execution contract | quoted If-Match |
Versão esperada do item; obrigatória quando execution.preconditions.resourceVersionTransport é IF_MATCH. |
submitResourceVersionTargetResourceKey |
string | null | undefined |
Conditional | action execution contract | exact resource discovery | Recurso canônico cujo ETag atual deve ser lido quando a action protege um agregado diferente do recurso dono. Exige submitResourceVersionTargetIdField. |
submitResourceVersionTargetIdField |
string | null | undefined |
Conditional | action execution contract | exact request field lookup | Campo escalar do payload que identifica o alvo concorrente. Exige submitResourceVersionTargetResourceKey; ausência, divergência de catálogo ou ETag ausente falham fechado. |
responseSchemaUrl |
string | null | undefined |
No | component-input | diagnostic only | Schema de resposta para diagnóstico e follow-up; não compõe campos editáveis nem o payload do comando. |
enableCustomization |
boolean |
No | component-input | boolean coercion | Alterna UX de edição visual/configuração. |
formId |
string | undefined |
Yes (corporate flow) | component-input | component key scoping | Obrigatório para ciclo corporativo com persistência e sync. |
componentInstanceId |
string | undefined |
No | component-input | component key scoping | Isola persistência por instância. |
layout |
FormLayout | undefined |
No | component-input | apply as runtime override | Override estrutural de layout quando fornecido. |
backConfig |
BackConfig | undefined |
No | component-input/storage | precedence over behavior.confirmOnUnsavedChanges |
Política de retorno/confirm on dirty. |
hooks |
FormHooksLayout | undefined |
No | component-input | overrides config.hooks |
Fonte de hooks prioritária quando presente. |
customEndpoints |
EndpointConfig |
No | component-input | service-level override | Sobrescreve endpoints do CRUD interno. |
Section header visual contract
| Path | Type | Required | Default | Status | Notes |
|---|---|---|---|---|---|
sections[].icon |
string |
No | n/a | Active | Ícone estático tradicional da seção; continua suportado. |
sections[].sectionHeader.mode |
'icon' | 'avatar-image' | 'avatar-initials' | 'auto' |
No | icon |
Active | Seleciona a estratégia visual do header. |
sections[].sectionHeader.sourceField |
string |
No | n/a | Active | Field do formData usado como origem de foto/avatar. |
sections[].sectionHeader.initialsSourceField |
string |
No | n/a | Active | Field textual usado para derivar iniciais. |
sections[].sectionHeader.altField |
string |
No | n/a | Active | Field usado como texto acessível do avatar e fallback textual para iniciais. |
sections[].sectionHeader.fallbackIcon |
string |
No | sections[].icon |
Active | Ícone usado quando a fonte dinâmica estiver vazia/inválida. |
sections[].sectionHeader.emptyState |
'fallback-icon' | 'placeholder-avatar' | 'none' |
No | placeholder-avatar |
Active | Resolve o estado inicial comum em formulários de inclusão com default neutro para qualquer domínio; fallback-icon preserva a moldura/avatar e respeita size. |
sections[].sectionHeader.size |
'sm' | 'md' | 'lg' |
No | md |
Active | Tamanho semântico do avatar; o runtime materializa via tokens --pfx-form-section-avatar-size*. |
sections[].sectionHeader.initialsMaxLength |
number |
No | 2 |
Active | Limita a quantidade de letras no avatar textual e é normalizado para 1..4. |
sections[].headerActions |
FormSectionHeaderAction[] |
No | n/a | Active | Ações iconográficas renderizadas na borda direita do header da seção e emitidas pelo mesmo output customAction. |
sections[].headerActions[].id |
string |
Yes | n/a | Active | Identificador estável da ação usado por rules, host e automações. |
sections[].headerActions[].label |
string |
Yes | n/a | Active | Label acessível usada como fallback de tooltip e aria-label. |
sections[].headerActions[].icon |
string |
Yes | n/a | Active | Ícone Material/Praxis renderizado no botão do header. |
sections[].headerActions[].action |
string |
No | sections[].headerActions[].id |
Active | Nome lógico emitido no customAction; quando informado, também é a base para mensagens e rules dessa ação. |
sections[].headerActions[].tooltip |
string |
No | sections[].headerActions[].label |
Active | Tooltip opcional da ação do header. |
sections[].headerActions[].color |
'primary' | 'accent' | 'warn' | 'basic' |
No | basic |
Active | Tom visual mapeado para mat-icon-button. |
sections[].headerActions[].visible |
boolean |
No | true |
Active | Permite ocultar a ação no runtime sem removê-la do contrato. |
sections[].headerActions[].disabled |
boolean |
No | false |
Active | Trava interação da ação do header. |
sections[].headerActions[].loading |
boolean |
No | false |
Active | Renderiza spinner e marca a ação como busy/indisponível enquanto durar o estado de loading. |
sections[].headerActions[].className |
string |
No | n/a | Active | Classe CSS opcional aplicada ao botão da ação no header. |
sections[].headerActions[].style |
Record<string, any> |
No | n/a | Active | Estilo inline opcional aplicado ao botão da ação; propriedades inválidas podem ser saneadas pelo pipeline de rules/editor. |
avatar-imageaceita URL, data URL,File,Blob,ArrayBuffer, views tipadas e objetos com chaves comourl,src,dataUrl,base64oubytes.autotenta imagem, depois iniciais vindas deinitialsSourceFieldoualtField, e por fim oemptyState.- Se nenhum valor estiver disponível ainda, o runtime não falha: aplica
emptyStatee mantém o cabeçalho estável em fluxoscreate. - Nas superfícies de authoring da lib,
sections[].headerActions[].actionsugere o catálogo global canônico do core e mantém fallback para valor customizado livre por compatibilidade. - Quando a ação global selecionada exigir payload/param obrigatório, o authoring deve sinalizar isso explicitamente ao usuário antes da persistência; no caso de
surface.open, o authoring canônico usa editor especializado em vez de texto cru. - Em
formRulesparatargetType: 'section', o builder pode governar tantosectionHeaderinteiro quanto subpaths tipados comosectionHeader.mode,sectionHeader.emptyStateesectionHeader.size, além deheaderActionscomo objeto agregado. - Em
formRules,targetsusam IDs canônicos do alvo. Para ações globais de formulário isso continua sendo o ID lógico da action; para ações de header de seção, o ID canônico ésection:<sectionId>:header-action:<actionLogicalId>, evitando colisão com actions globais do form e entre seções. - Se a seção ainda não tiver
id, o runtime aceita o fallbackheader-action:<actionLogicalId>por compatibilidade; para contratos persistidos, prefira sempre materializarsection.id.
Field rule computed value contract
Regras com targetType: "field" podem usar effect.properties.value e effect.propertiesWhenFalse.value para escrever declarativamente o valor do FormControl alvo. O envelope canônico é fechado e exclusivo: exatamente { "expression": <JsonLogic> } para valores calculados ou exatamente { "literal": <valor> } para valores literais estruturados. Primitivos, null e arrays continuam aceitos como literais; objetos JSON Logic legados de operador único continuam aceitos para compatibilidade no runtime. O authoring visual e o editor JSON rejeitam objetos literais ambíguos sem envelope, como { "startDate": "...", "endDate": "..." }, e envelopes com chaves extras, como { "literal": 1, "expression": { "var": "age" } }. Valores calculados são resolvidos em uma fase anterior à aplicação das demais propriedades, com iteração limitada até estabilização, para que regras dependentes não fiquem acopladas à ordem do array.
Conditional command rule contract
Politica de erro do runtime: falhas de GlobalActionService.executeRef(...) em comandos condicionais sao fail-closed. Resultado success: false ou excecao assincrona gera diagnostico e nao reexecuta em loop enquanto a condicao continuar verdadeira. Quando GlobalActionService nao esta disponivel, acoes mutaveis (api.post, api.put, api.patch, api.delete) nao caem para customAction.
formCommandRules separa comandos com side effect das regras de propriedade. A regra é avaliada depois de formRules estabilizar fieldValues, então casos como birthDate -> age -> dialog.alert não dependem da ordem do array. O primeiro corte suporta apenas effects[].kind: "global-action" e executa globalAction via GlobalActionService.executeRef(...). Por padrão, comandos usam trigger: "on-condition-enter" e runOnInitialEvaluation: false; trigger: "while-true" não executa global-action nesta versão. distinct usa chave composta por componente, regra, efeito, action, contexto e valor de distinctBy, e a memória é limpa quando a condição volta a falso. No editor visual, payloadExpr permanece escape hatch de JSON avancado: o editor preserva payloadExpr existente quando nenhum payload estruturado e definido, mas campos estruturados authoram payload literal.
Exemplo:
{
"formRules": [
{
"id": "birth-date-computes-age",
"targetType": "field",
"targets": ["age"],
"effect": {
"condition": { "!": [{ "isBlank": [{ "var": "birthDate" }] }] },
"properties": {
"value": { "expression": { "yearsSince": [{ "var": "birthDate" }] } }
},
"propertiesWhenFalse": {
"value": { "literal": null }
}
}
}
]
}
Visual block rule contract
Itens de layout kind: "richContent" podem ser alvo de formRules com targetType: "visualBlock". O target é sempre o id do item em sections[].rows[].columns[].items[]; o bloco visual não recebe entrada em fieldMetadata[], não cria FormControl e não entra em formSubmit.formData nem no payload HTTP.
Subconjunto público de propriedades suportadas para targetType: "visualBlock":
| Propriedade | Tipo | Status | Notes |
|---|---|---|---|
visible / hidden |
boolean |
Active | Exibe ou oculta o bloco no runtime. |
layout |
"block" | "inline" |
Active | Alterna a apresentação do item quando o layout aceita a variação. |
className / rootClassName |
string |
Active | Aplica classes controladas pelo host/design system. |
style |
Record<string, any> |
Active | Estilo visual saneado pelo pipeline de regras/runtime. |
text |
string |
Active | Sobrescreve texto apenas em documento simples ou node textual seguro. |
title |
string |
Active | Sobrescreve título apenas em documento simples, card/media/timeline suportado ou node identificado. |
message |
string |
Active | Sobrescreve mensagem apenas em documento simples, card/media suportado ou node identificado. |
textNodeId / titleNodeId / messageNodeId |
string |
Active | Seleciona explicitamente o node que receberá text, title ou message; o editor deve tratar como detalhe técnico guiado por seletor. |
Exemplo canônico:
{
"formRules": [
{
"id": "employee-guidance-by-status",
"targetType": "visualBlock",
"targets": ["employee-guidance-block"],
"effect": {
"condition": { "===": [{ "var": "ativo" }, false] },
"properties": {
"title": "Revise a inativação",
"titleNodeId": "custom-title",
"message": "Informe justificativa antes de salvar.",
"messageNodeId": "custom-message",
"className": "employee-guidance-warning"
},
"propertiesWhenFalse": {
"title": "Cadastro ativo",
"titleNodeId": "custom-title",
"message": "Mantenha os dados funcionais atualizados.",
"messageNodeId": "custom-message",
"className": "employee-guidance-success"
}
}
}
]
}
Limites de segurança:
text,titleemessagenão aceitam HTML arbitrário, handlers, scripts ou substituição completa doRichContentDocument.- Em documentos compostos, prefira sempre
textNodeId,titleNodeIdoumessageNodeId; sem node explícito, o runtime só aplica override quando encontra alvo simples ou convencional seguro. - Regras de
visualBlocksão visual-only. Use campo local (fieldMetadata[].source: "local") quando a experiência precisar de valor, validação de campo, leitura emrawFormDataou participação explícita no payload viasubmitPolicy.
Output events
| Event | Payload | Trigger | Stability | Notes |
|---|---|---|---|---|
formSubmit |
FormSubmitEvent |
Submit validado do formulario. | Partial | formData e o payload persistivel filtrado; rawFormData preserva o valor completo do formulario, incluindo campos locais/transientes. |
formCancel |
void |
Acao cancelar. | Partial | Preservado da documentação anterior. |
formReset |
void |
Acao reset. | Partial | Preservado da documentação anterior. |
configChange |
FormConfig |
Alteracoes de layout/config durante edicao. | Partial | Preservado da documentação anterior. |
configPatchChange |
{ inputPatch: { config?: FormConfig; resourcePath?: string | null; mode?: DynamicFormMode; presentationModeGlobal?: boolean | null; presentation?: DynamicFormPresentationSnapshot | null } } |
Alteracoes autoradas de configuracao que devem ser persistidas pelo host. | Partial | Contrato aditivo para hosts genericos sem alterar o payload legado de configChange. |
formReady |
FormReadyEvent |
Form pronto para interacao. | Partial | Preservado da documentação anterior. |
valueChange |
FormValueChangeEvent |
Alteracao de valor no form runtime. | Partial | Preservado da documentação anterior. |
syncCompleted |
SyncResult |
Sincronizacao de schema/config concluida. | Partial | Preservado da documentação anterior. |
initializationError |
FormInitializationError |
Falha de inicializacao. | Partial | Preservado da documentação anterior. |
loadingStateChange |
LoadingState |
Mudanca de loading (config/schema/render/data). |
Partial | Preservado da documentação anterior. |
enableCustomizationChange |
boolean |
Alternancia do modo de customizacao. | Partial | Preservado da documentação anterior. |
ruleDiagnosticsChange |
RuleApplicationDiagnostic[] |
Mudanca nos diagnosticos de aplicacao de formRules no runtime. |
Active | Emite somente quando a assinatura dos diagnosticos muda; hosts podem exibir alerta, bloquear publicacao ou enviar telemetria. |
customAction |
FormCustomActionEvent |
Acao custom definida no contrato ou ação do header de seção. | Partial | source pode ser button, shortcut ou section-header; quando vier de header, o payload inclui sectionId. |
actionConfirmation |
FormActionConfirmationEvent |
Pedido de confirmacao de acao sensivel. | Partial | Preservado da documentação anterior. |
External side channels
| Channel | Direction | Contract | Failure mode | Notes |
|---|---|---|---|---|
ASYNC_CONFIG_STORAGE |
bidirectional | loadConfig/saveConfig/clearConfig |
fail-open | Persistência de config, prefs de input e status de schema. |
CONNECTION_STORAGE |
bidirectional | loadConnection/saveConnection |
fail-open | Hidrata/salva resourcePath quando não vem por input. |
SettingsPanelService |
bidirectional | open(...).applied$/saved$ |
fail-open | Atualiza config em runtime sem recarregar host. |
GenericCrudService |
outbound I/O | configure/getSchema/filter/... |
fail-soft | Integração de schema/dados remotos com fallback controlado. |
Host/runtime dependencies
| Dependency | Required | Environment | Purpose | Notes |
|---|---|---|---|---|
GenericCrudService |
Yes | browser/dev/prod | schema/data runtime | Fonte remota para criação/sincronização de config. |
ASYNC_CONFIG_STORAGE |
Yes | browser/dev/prod | persistência | Armazena config por formId/instância e flags de schema. |
CONNECTION_STORAGE |
Yes | browser/dev/prod | persistência de conexão | Reutiliza resourcePath salvo previamente. |
FormRulesService |
Yes | browser/dev/prod/ssr | execução de regras | Aplica formRules e recalcula comportamento de campos. |
FormConfigService |
Yes | browser/dev/prod/ssr | validação e normalização | Validação estrutural e utilitários de config. |
MatDialog |
Optional | browser/dev/prod | confirmações e fluxos de ação | Acionada em ações sensíveis conforme contrato. |
Coverage matrix
| Surface | Verified | Coverage status | Evidence | Notes |
|---|---|---|---|---|
| Runtime | false | Partial | source_of_truth + conteudo preservado | Revisao estrutural concluida; validacao comportamental fina pode exigir follow-up. |
| Schema/Types | true | Partial | interfaces/modelos citados | Mapeamento formal de todos os campos ainda pode requerer refinamento. |
| Editor/Tooling | false | Partial | secoes de editor quando presentes | Cobertura de editor/tooling nem sempre confirmada por evidencia direta. |
Runtime coverage boundaries
- Cobertura consolidada com base em documentacao existente e source of truth declarado.
- Comportamentos fora de evidencia direta foram marcados como not-yet-verified ou Partial.
- Compatibilidade legada, quando detectada, foi separada em classificacao explicita.
Resolution model
Merge order
- inputs explícitos (
config,resourcePath,mode, flags globais) - hidratação de preferências de input (
formInputsKey) e conexão persistida initializeForm(): config local persistida (formConfigKey) ou criação a partir do servidor- normalização final via
normalizeFormConfig() - overrides de runtime (
hooks,backConfig,customEndpoints, presentation vars)
Fallback order
config local persistida -> config default criada do schema remoto -> erro de inicialização (quando formId e uma fonte schema-backed, resourcePath ou schemaUrl, estão ausentes no fluxo corporativo).
Override points
@Input()públicos (config,hooks,layout,backConfig,customEndpoints)- edição em runtime via
SettingsPanelService - persistência de host (
ASYNC_CONFIG_STORAGE,CONNECTION_STORAGE)
Runtime normalization
normalizeFormConfig()estabiliza ids e estrutura antes do build/render.applyPresentationVars()resolve precedência entre configuração persistida e config em memória.resolveSchemaPrefs()consolida preferências locais e fallback global de notificação de drift.
Precedence rules
@Input() hookssobrescreveconfig.hookspor estágio.backConfig.confirmOnDirtysobrescrevebehavior.confirmOnUnsavedChanges.resourcePathexplícito no input tem precedência sobre conexão persistida.
Validation and error semantics
Validation model
| Path/Rule | Validation phase | Behavior on fail | Error code / warning | Notes |
|---|---|---|---|---|
formId + (resourcePath ou schemaUrl) no fluxo corporativo |
init | hard-fail + initializationError |
config-load |
Inicialização não prossegue sem identidade e fonte schema-backed. |
presentationModeGlobal=true com mode != view |
input-change | warning + ignore | runtime warning | Sem bloqueio; render segue em input mode. |
config recebido por input |
input-change | normalize + rebuild | n/a | normalizeFormConfig antes de renderização. |
| validação de config (editor/runtime) | pre-apply | reject when invalid | FormConfigService.validateConfig |
Erros retornados ao host via outputs/eventos. |
| verificação de hash de schema remoto | background runtime | mark outdated + emit status | schemaStatusChange |
Não aplica schema remoto automaticamente em background. |
Error semantics
Falhas de inicialização (config-load/form-build) são bloqueantes e emitem initializationError. Divergências de schema são tratadas como estado (schemaOutdated) com emissão de evento, sem interromper formulário já carregado.
No submit, RestApiResponse.errors é materializado somente quando a resposta possui status HTTP
4xx conhecido. Cada detalhe cujo target resolve um controle é anexado como erro server, sem
remover validadores do cliente, e desaparece quando aquele controle muda. Erros de outros campos
permanecem ativos; todos os erros de servidor são limpos no início da próxima tentativa e após
sucesso. target aceita path Angular pontuado ou JSON Pointer. Targets desconhecidos não são
inferidos por texto e continuam como feedback global.
Precedência do feedback: resposta 4xx com detalhes governados > mensagem customizada de submit
ou create/update > fallback normalizado e localizado. Falhas de rede, respostas 5xx e respostas
sem status confiável nunca expõem message/errors do payload e usam as chaves
global.submitError.*. visibleWhen, mensagens locais e validação visual não substituem a
autorização e a validação de negócio do backend.
Fail-open / fail-closed behavior
| Condition | Mode | Runtime behavior | Consumer impact |
|---|---|---|---|
| Falha ao ler config local/prefs | fail-open | segue com fluxo remoto/default | formulário ainda inicia quando possível |
formId ausente ou sem resourcePath/schemaUrl (fluxo corporativo) |
fail-closed | aborta inicialização | host recebe initializationError |
| schema remoto indisponível com fallback legado disponível | fail-open | usa fonte legada (crud.getSchema) |
mantém operação com cobertura parcial |
| payload de config inválido | reject | não aplica configuração | prevenir estado inconsistente no runtime |
Invalid or unknown field handling
- Campos desconhecidos: comportamento depende da estrategia do componente (ignore, warn ou reject).
- Campos invalidos: podem gerar fallback, warning ou falha conforme implementacao.
- Registrar divergencias observadas em Known limitations and mismatches.
Runtime warnings vs hard failures
| Condition | Severity | Observability | Consumer action |
|---|---|---|---|
| partial-or-declared-only-coverage | warning | logs/eventos do componente | confirmar ligacao runtime antes de uso critico |
Detailed API
Preserved technical reference (normalized from previous revision)
Referencia canonica da JSON API do praxis-dynamic-form, com foco em:
- contrato declarado (
FormConfig+ inputs/outputs do componente); - comportamento que o runtime consome de fato;
- limites conhecidos para uso corporativo (governanca, observabilidade, UX e risco).
Legenda de suporte:
Active: consumido no runtime atual.Partial: consumido parcialmente (subconjunto funcional).Declared-only: declarado no contrato, sem consumo direto no runtime atual.
Table of contents
- Overview
- Checklist corporativo pre-flight
- API
- FormConfig coverage matrix
- Behavior e Messages coverage detalhado
- DynamicFieldLoader error bridge
- Seguranca e fronteiras de responsabilidade
- Exemplos JSON
- Known limitations and pending investigation
- Source references
Overview
praxis-dynamic-form e um runtime de formulario schema-driven orientado por FormConfig.
Fluxo macro:
- Resolve configuracao (local, remota ou defaults).
- Normaliza estrutura (
sections/rows/columns/fieldMetadata) e IDs. - Monta
FormGroup, aplica regras e estados globais. - Renderiza campos via
DynamicFieldLoaderDirective. - Executa submit/cancel/reset/custom actions com hooks e mensagens.
- Emite eventos para host (estado, erros, sincronizacao e acao).
No ecossistema Praxis, ele funciona tanto como runtime final quanto como superficie de edicao (settings panel + config editor) para round-trip de JSON.
Checklist corporativo pre-flight
- Defina
formIdestavel por tela/uso para evitar colisao de persistencia. - Em cenarios multi-instancia na mesma pagina, use
componentInstanceId. - Se o formulario for remoto, valide
resourcePathe ciclo de schema (schemaStatusChange). - Declare explicitamente estrategia de modos (
create/edit/view) no host. - Trate
fieldRenderErrorno host para observabilidade de render por campo. - Garanta autorizacao no backend para submit/custom actions; regras visuais no front nao sao controle de acesso.
API
Component inputs
initialValue is part of the public runtime contract and accepts
Record<string, unknown> | null for local initial values.
| Input | Tipo | Default | Status | Runtime notes |
|---|---|---|---|---|
config |
FormConfig |
{ sections: [] } |
Active | Contrato principal consumido no ciclo inteiro. sections é opcional somente para forms schema-driven com grounding explícito (metadata.source='schema', schema metadata ou fonte runtime como schemaUrl/resourcePath); ausência de layout manual é normalizada internamente como array vazio e permite que layoutPolicy/schema materializem agrupamentos. |
resourcePath |
string | undefined |
undefined |
Active | Habilita carga de schema/dados remotos. Opcional quando schemaUrl explícito é fornecido. |
resourceId |
string | number | undefined |
undefined |
Active | Carrega entidade no modo edit/view; em create, funciona apenas como contexto do item e não dispara hidratação. |
mode |
'create' | 'edit' | 'view' |
'create' |
Active | Governa submit, leitura e apresentacao. |
schemaSource |
'resource' | 'filter' |
'resource' |
Active | Seleciona origem do schema remoto. |
schemaUrl |
string | undefined |
undefined |
Active | Permite usar schema canonico publicado pelo backend sem heuristica local de path e pode iniciar o fluxo corporativo sem resourcePath. |
readUrl |
string | undefined |
undefined |
Active | Hidrata dados de surfaces de leitura/projecao pelo endpoint publicado, preservando resourcePath como recurso dono. |
apiEndpointKey |
ApiEndpoint | string | undefined |
undefined |
Active | Resolve schemaUrl, readUrl e submitUrl relativos contra a origem canonica correta em hosts destacados. |
apiUrlEntry |
ApiUrlEntry | undefined |
undefined |
Active | Porta a entrada de API ja resolvida para overlays/dialogs que nao herdam o provider de API_URL da rota atual. |
domainRules |
PraxisDynamicFormDomainRulesOptions | boolean | null |
null |
Active | Opt-in para carregar materializacoes de regras compartilhadas em /api/praxis/config/domain-rules/materializations e combina-las com config.formRules. |
submitUrl |
string | undefined |
undefined |
Active | Executa submit canonico publicado por surface ou action, sem inferencia local de CRUD. |
submitMethod |
'post' | 'put' | 'patch' | undefined |
undefined |
Active | Metodo HTTP do submit canonico; deve acompanhar submitUrl. |
submitIdempotencyKey |
string | undefined |
undefined |
Active | Envia Idempotency-Key e preserva a identidade entre retries da mesma tentativa. |
submitCorrelationId |
string | undefined |
undefined |
Active | Envia X-Correlation-Id para rastreabilidade corporativa ponta a ponta. |
submitResourceVersion |
string | number | undefined |
undefined |
Active | Envia a versão esperada como If-Match, sem inferir concorrência a partir do formulário. |
submitResourceVersionTargetResourceKey |
string | undefined |
undefined |
Active | Quando não há submitResourceVersion estático, descobre o path do recurso canônico exato e lê o registro selecionado imediatamente antes do comando. É input runtime materializado pela action, não configuração de negócio authorável. |
submitResourceVersionTargetIdField |
string | undefined |
undefined |
Active | Lê do payload preparado o identificador escalar do alvo concorrente e exige ETag na resposta de leitura. Não aceita labels, objetos de lookup ou fallback para id. |
responseSchemaUrl |
string | undefined |
undefined |
Active | Porta diagnóstica/read-only; não deve ser usada para mesclar propriedades do schema de resposta no formulário de comando. |
enableCustomization |
boolean |
false |
Active | Habilita UX de customizacao do layout. |
formId |
string | undefined |
undefined |
Active | Chave de persistencia e identidade logica. |
componentInstanceId |
string | undefined |
undefined |
Active | Isola instancias com mesmo formId. |
configPersistenceStrategy |
'local-first' | 'input-first' |
'local-first' |
Active | Em input-first, os inputs fornecidos pelo host, inclusive mode, permanecem autoritativos sobre preferencias persistidas da mesma instancia. Combine com layoutPolicy.persistence='transient' em commands efemeros para nao carregar nem gravar layout local. |
layout |
FormLayout | undefined |
undefined |
Partial | Funciona como override estrutural em parte dos fluxos de layout/editor. |
generatedLayoutPreset |
'default' | 'compactPresentation' |
'default' |
Active | Usado apenas ao criar a configuracao inicial a partir de schema/metadata; nao reprocessa layouts persistidos ou authorados. |
layoutPolicy |
DynamicFormLayoutPolicy | null |
null |
Active | Politica opt-in para materializar layout a partir do schema atual. Use source: 'schema' com persistence: 'transient' para detalhe/read-only e command forms schema-driven sem persistir sections geradas nem reabrir configuracao local salva; politicas de host em config, como helpPresentation, continuam sendo aplicadas ao layout materializado. Em mode='view', intent: 'detail' ou preset: 'compactPresentation' ativa apresentacao quando presentationModeGlobal nao foi informado; use [presentationModeGlobal]=false para controles read-only tradicionais. No preset compactPresentation, x-ui.width explicito empacota campos em linhas de 12 colunas e tem precedencia sobre detailSummary.columns por default; campos sem width permanecem full-width, a menos que detailSummary.columns/responsiveColumns declare a densidade do resumo. Use detailSummary.widthPrecedence='summary' quando a densidade do resumo read-only deve sobrescrever x-ui.width apenas nessa surface compacta. No preset groupedCommand, groupedCommand.orphanFieldExpansion controla linhas logicas com um unico campo: medium-and-wide (default) expande spans 6/8, preserve mantem o width publicado e all tambem expande campos compactos. groupedCommand.partialRowStrategy usa preserve por default; fill-compatible particiona o grupo nas linhas visuais depois de resolver visibilidade responsiva, CSS order e wrap em cada breakpoint/container, projeta cada linha parcial elegivel em spans canônicos que completam 12 colunas e mapeia o resultado de volta as colunas authoradas apenas para renderizacao, sem alterar x-ui.width, sections ou o documento de authoring. Um singleton elegivel criado por wrap pode preencher sua linha visual; controles compactos, uploads e tipos desconhecidos preservam seus spans. groupedCommand.contextFields identifica campos schema-backed já hidratados pela surface: eles permanecem no FormGroup e no payload, mas não renderizam controles redundantes. Use responsiveColumns, por exemplo { lg: 3, md: 2, sm: 1 }, para drawers, side sheets e painéis corporativos estreitos sem copiar FormConfig.sections locais. schemaType e schemaOperation sao validados contra schemaUrl quando a URL declara esses parametros. |
O authoring emite o warning dynamicForm.config.layout.groupedCommand.row.incomplete quando uma linha gerada com dois ou mais campos ocupa menos de 12 colunas. Com partialRowStrategy='fill-compatible', o warning desaparece quando a projeção resolve a linha; ele permanece acionável para preserve ou quando controles compactos/fixos/desconhecidos não podem ser redistribuídos.
| backConfig | BackConfig \| undefined | undefined | Active | Integra retorno/navegacao no painel de configuracao; confirmOnDirty tem precedencia sobre behavior.confirmOnUnsavedChanges no cancel. |
| hooks | FormHooksLayout \| undefined | undefined | Active | Override direto de hooks sobre config.hooks. |
| customEndpoints | EndpointConfig | {} | Active | Override de endpoints no CRUD service interno. |
| removeEmptyContainersOnSave | boolean | false | Active | Sanitiza secoes/linhas/colunas vazias na persistencia de config. |
| reactiveValidation | boolean \| null | null | Active | Override de validacao reativa (valueChanges). |
| reactiveValidationDebounceMs | number \| null | null | Active | Debounce da validacao reativa. |
| notifyIfOutdated | 'inline' \| 'snackbar' \| 'both' \| 'none' | 'both' | Active | Canal de aviso de schema desatualizado quando a customizacao estiver ativa. |
| snoozeMs | number | 86400000 | Active | Janela de supressao de notificacao. |
| autoOpenSettingsOnOutdated | boolean | false | Active | Auto-abertura do settings quando schema diverge. |
| readonlyModeGlobal | boolean \| null | null | Active | Estado global de leitura propagado para loader. |
| disabledModeGlobal | boolean \| null | null | Active | Estado global de desabilitado propagado para loader. |
| presentationModeGlobal | boolean \| null | null | Active | Modo apresentacao global (efetivo em view). |
| fieldIconPolicy | 'all' \| 'presentation-only' \| 'none' | 'all' | Active | Controla icones prefixIcon/suffixIcon vindos da metadata dos campos. all preserva o comportamento atual; presentation-only mantem icones decorativos no modo apresentacao e oculta os slots de icone em controles input/read-only tradicionais; none oculta esses slots em todos os modos. |
| visibleGlobal | boolean \| null | null | Active | Visibilidade global propagada para loader. |
Perfil público local somente-leitura
PRAXIS_DYNAMIC_FORM_COMPONENT_METADATA.runtimeProfiles publica
public-local-readonly para hosts públicos não confiáveis. O profile aceita
somente mode='view', readonlyModeGlobal=true, estratégia input-first,
initialValue local e um subconjunto explícito de chaves de config, layout e
FieldMetadata. Controles remotos, endpoints, option sources, rich content,
hooks, rules, commands, actions, customização, assistente e IDs de persistência
invalidam o profile. Chaves desconhecidas também invalidam o documento para que
novas capacidades futuras não sejam liberadas implicitamente.
O profile declara effects: [] e não é grant de autorização. O host continua
responsável por validar o candidate e bloquear rede por padrão. No runtime,
onSubmit() retorna sem emitir evento e sem chamar create/update quando o form
está em readonly ou presentation, inclusive em submit programático.
In compactPresentation runtime detail surfaces, rows, columns and sections are visible only when
they contain at least one field that can be materialized after metadata visibility and field-rule
overrides are resolved. Boolean values, including false, are valid presentation values and must
not be treated as empty detail content. If no field in a section is materialized, the section is
hidden instead of rendering an orphan title.
Migration baseline for ErgonX-style screens
For enterprise migrations that must become templates for many screens, layoutPolicy,
helpPresentation and fieldIconPolicy should be selected as part of the DTO/schema
handoff, not patched locally after visual review.
Recommended baseline:
| Surface | Inputs | Contract gate |
|---|---|---|
| Detail/read-only | layoutPolicy.source='schema', intent='detail', preset='compactPresentation', persistence='transient', schemaType='response' |
Response DTO publishes business grouping, order, labels, value presentation and safe widths. |
| Create/edit | layoutPolicy.source='schema', intent='command', preset='groupedCommand', persistence='transient', schemaType='request' |
Request DTO/write contract publishes only editable fields, validators, options and help text required for the command. |
| Dense command drawer | config.helpPresentation.display='auto' with preferPopoverForControls for select, checkbox, toggle, date/datepickers and numeric controls |
DTO help text is semantic and not a substitute for validation messages. |
| Input-heavy operational form | fieldIconPolicy='presentation-only' |
Icons remain useful in read-only presentation but do not crowd editable controls. |
If a field requires a local label, local help text, local option mapping or local code/description
composition to look correct, the schema is not ready for scalable migration. Fix the backend DTO,
OpenAPI x-ui metadata or option/value-presentation contract first.
Regras compartilhadas materializadas
domainRules separa regra corporativa compartilhavel de regra materializada no FormConfig. Quando habilitado, o componente consulta o backend de configuracao via DomainRuleFormRulesService, transforma cada materializacao em FormLayoutRule e aplica a lista combinada:
config.formRules- regras vindas de
domain_rule_materialization.materializedPayload
Exemplo:
<praxis-dynamic-form
formId="funcionarios-form-demo"
[config]="formConfig"
[domainRules]="{
enabled: true,
targetArtifactKey: 'funcionarios-form-demo',
targetLayer: 'form_config',
targetArtifactType: 'praxis-dynamic-form',
status: 'applied'
}">
</praxis-dynamic-form>
Campos de PraxisDynamicFormDomainRulesOptions:
| Campo | Tipo | Default | Observacao |
|---|---|---|---|
enabled |
boolean |
false |
Deve ser true para consultar o backend. |
targetArtifactKey |
string | null |
`formId | |
targetLayer |
string | null |
'form_config' |
Camada alvo persistida no backend. |
targetArtifactType |
string | null |
'praxis-dynamic-form' |
Tipo do artefato alvo. |
status |
string | null |
undefined |
Filtro opcional. Para consumo runtime, prefira applied; pending_review pertence a etapas de governanca antes da aplicacao. |
Materializacoes diretas podem persistir um FormLayoutRule em materializedPayload. O adaptador tambem reconhece operation: "rule.visualBlockGuidance.add" e converte para regra targetType: "visualBlock" como projecao visual derivada, preservando rastreabilidade em metadata.domainRule sem transformar o formulario em fonte primaria da regra de negocio.
Quando o backend enviar decisionDiagnostics, o adaptador carrega esse envelope para metadata.domainRule.decisionDiagnostics, incluindo sourceHashPresent e sourceHash quando disponiveis, mantendo a explicacao canonica da decisao semanticamente authorada por IA junto da regra derivada, sem transformar o formulario em fonte primaria da regra de negocio.
Teste vivo de referencia:
PAX_PROXY_TARGET=https://praxis-api-quickstart.onrender.com \
node scripts/run-playwright-with-dev-host.js \
--port 4003 \
--path /funcionarios-form-demo \
--spec projects/praxis-dynamic-form/test-dev/e2e/funcionarios-form-demo-domain-rules.playwright.spec.ts
Validado em 2026-04-23 contra praxis-api-quickstart publicado no Render com
praxis-config-starter:0.1.0-rc.22: o spec confirmou resposta 200 de
/api/praxis/config/domain-rules/materializations e presença de materialização
form_config com operation: "rule.visualBlockGuidance.add".
Component outputs
| Output | Payload | Quando emite |
|---|---|---|
formSubmit |
FormSubmitEvent |
Submit validado do formulario. |
formCancel |
void |
Acao cancelar. |
formReset |
void |
Acao reset. |
configChange |
FormConfig |
Alteracoes de layout/config durante edicao. |
configPatchChange |
{ inputPatch: { config?: FormConfig; resourcePath?: string | null; mode?: DynamicFormMode; presentationModeGlobal?: boolean | null; presentation?: DynamicFormPresentationSnapshot | null } } |
Alteracoes autoradas de configuracao que devem ser persistidas pelo host. |
formReady |
FormReadyEvent |
Form pronto para interacao. |
valueChange |
FormValueChangeEvent |
Alteracao de valor no form runtime. |
syncCompleted |
SyncResult |
Sincronizacao de schema/config concluida. |
initializationError |
FormInitializationError |
Falha de inicializacao. |
loadingStateChange |
LoadingState |
Mudanca de loading (config/schema/render/data). |
enableCustomizationChange |
boolean |
Alternancia do modo de customizacao. |
customAction |
FormCustomActionEvent |
Acao custom definida no contrato ou ação do header de seção. |
actionConfirmation |
FormActionConfirmationEvent |
Pedido de confirmacao de acao sensivel. |
schemaStatusChange |
{ outdated, serverHash?, lastVerifiedAt?, formId? } |
Mudanca de estado de desatualizacao de schema. |
fieldRenderError |
{ phase, fieldName, error, fatal } |
Erro de render de campo emitido pelo DynamicFieldLoader. |
ruleDiagnosticsChange |
RuleApplicationDiagnostic[] |
Diagnosticos de regras invalidas, incompletas ou parcialmente saneadas durante aplicacao runtime. |
Data mode e fluxo
mode='create': cria registro ou materializa um comando; nunca carrega a entidade porresourceId, e valores iniciais devem vir deinitialValue.mode='edit': carrega entidade porresourceIdquando disponivel.mode='view': foco em leitura/apresentacao; actions de edicao podem ser suprimidas.
Precedencias importantes:
- Inputs explicitos do host (ex.:
reactiveValidation) sobrescrevem comportamento noconfig.behavior. hooksinput sobrescreveconfig.hooks.- Preferencias de outdated schema combinam input + widget/global defaults.
FormConfig coverage matrix
| JSON path | Status | Runtime notes |
|---|---|---|
sections[] |
Active | Render estrutural principal (section/row/column). |
fieldMetadata[] |
Active | Fonte de campos para DynamicFieldLoader. |
metadata |
Active | Usado em reconciliacao/snapshot/status de schema. |
actions |
Active | Render de praxis-form-actions e roteamento de eventos. |
behavior |
Partial | Subset funcional (detalhado abaixo). |
api |
Declared-only | Declarado no modelo; sem binding operacional direto no runtime atual. |
messages |
Partial | Chaves principais de submit/confirmacao usadas; contrato e mais amplo. |
formRules |
Active | Aplicadas no pipeline de regras do runtime. |
formRulesState |
Internal | Persistido somente como estado de round-trip do builder visual; nao e contrato autoravel. |
hooks |
Active | Integracao de ciclo (before/after) via runtime de hooks. |
hints |
Declared-only | Mantido no contrato/editor; sem render dedicado no template principal. |
Behavior e Messages coverage detalhado
behavior.*
| Caminho | Status | Observacao |
|---|---|---|
behavior.confirmOnUnsavedChanges |
Active | Governa confirmacao antes de cancelar quando backConfig.confirmOnDirty nao estiver definido; sem politica explicita, cancel dirty usa fallback seguro com confirmacao. |
behavior.disableMountAnimation |
Active | Desliga animacao inicial do form. |
behavior.mountAnimation.durationMs/offsetPx/staggerMs |
Active | Ajuste fino da animacao de montagem. |
behavior.reactiveValidation |
Active | Liga validacao reativa com hooks afterValidate. |
behavior.reactiveValidationDebounceMs |
Active | Debounce da validacao reativa. |
behavior.trackHistory |
Declared-only | Sem consumo direto no runtime atual. |
behavior.focusFirstError |
Active | No submit invalido, foca o primeiro campo invalido encontrado. |
behavior.scrollToErrors |
Active | No submit invalido, faz scroll para o primeiro campo invalido. |
behavior.clearAfterSave |
Active | No submit com sucesso, limpa o formulario quando habilitado. |
behavior.redirectAfterSave |
Active | No submit com sucesso navega via Router.navigateByUrl quando Router estiver disponivel; sem Router, emite warning e nao navega. |
messages.*
| Caminho | Status | Observacao |
|---|---|---|
messages.loading.submit |
Active | Mensagem de loading durante submit. |
messages.confirmations.* |
Active | Confirmacoes pre-acao (submit/cancel/reset/custom). |
messages.customActions[actionId].confirmation |
Active | Prioridade sobre confirmations[actionId]. |
messages.customActions.submit.success/error |
Active | Mensagens de resultado no submit customizado. |
messages.createRegistrySuccess/updateRegistrySuccess |
Active | Feedback de sucesso create/edit. |
messages.createRegistryError/updateRegistryError |
Active | Feedback de erro create/edit. |
Campos extras em messages |
Partial | Contrato aceita extensao, mas nem todas as chaves sao exibidas no runtime atual. |
DynamicFieldLoader error bridge
praxis-dynamic-form encaminha erros de render por campo para o host via fieldRenderError.
Payload:
{
phase: 'executeRendering' | 'detectChanges';
fieldName: string;
error: unknown;
fatal: boolean;
}
Politica atual do loader:
- Erro por campo nao derruba automaticamente o formulario inteiro.
- Erros de lifecycle Angular (
NG0205, injector/view destroyed) sao marcados comofatal=truepara o ciclo atual. - O runtime evita emissao duplicada quando o erro fatal ja foi reportado em etapa anterior.
Recomendacao corporativa:
- Capture
fieldRenderErrorno host e envie para telemetria comformId,resourcePath,modeefieldName. - Use alerta operacional apenas para
fatal=truerepetido em ambiente de producao.
Seguranca e fronteiras de responsabilidade
hidden,readonly,disabled,presentationsao controles de UX no front-end.- Validacao e autorizacao de negocio devem ser reforcadas no backend.
- Acoes custom emitidas pelo componente (
customAction) nao substituem checagens de permissao server-side.
Exemplos JSON
1) Baseline create/edit (foco em contrato ativo)
{
"sections": [
{
"id": "main",
"title": "Cadastro",
"rows": [
{
"id": "r1",
"columns": [
{ "id": "c1", "fields": ["name", "email"] }
]
}
]
}
],
"fieldMetadata": [
{ "name": "name", "label": "Nome", "controlType": "input", "required": true },
{ "name": "email", "label": "Email", "controlType": "input" }
],
"behavior": {
"confirmOnUnsavedChanges": true,
"reactiveValidation": true,
"reactiveValidationDebounceMs": 200
},
"messages": {
"loading": { "submit": "Salvando cadastro..." },
"confirmations": { "cancel": "Descartar alteracoes?" },
"createRegistrySuccess": "Registro criado com sucesso",
"updateRegistrySuccess": "Registro atualizado com sucesso"
}
}
2) View + apresentacao global
{
"sections": [
{
"id": "view-main",
"title": "Resumo",
"rows": [
{
"id": "vr1",
"columns": [
{ "id": "vc1", "fields": ["status", "owner"] }
]
}
]
}
],
"fieldMetadata": [
{ "name": "status", "label": "Status", "controlType": "input" },
{ "name": "owner", "label": "Responsavel", "controlType": "input" }
],
"actions": {
"submit": { "visible": false, "label": "Salvar" },
"cancel": { "visible": true, "label": "Voltar" },
"reset": { "visible": false, "label": "Limpar" }
}
}
No host Angular:
<praxis-dynamic-form
[config]="formConfig"
mode="view"
[presentationModeGlobal]="true"
(fieldRenderError)="onFieldRenderError($event)"
(ruleDiagnosticsChange)="onRuleDiagnosticsChange($event)">
</praxis-dynamic-form>
ruleDiagnosticsChange nao aplica UI propria no formulario. Ele existe para governanca do host: logar regras invalidas, sinalizar configuracao inconsistente ao autor ou impedir publicacao de metadata sem esconder o problema dentro do runtime.
O runtime emite target-not-found quando uma regra aponta para section, row, column, action ou visualBlock inexistente no FormConfig resolvido; para campos, o codigo legado field-target-not-found permanece.
Known limitations and pending investigation
FormConfig.apisegueDeclared-onlyno runtime principal.- Cobertura de
behaviore parcial; varios campos continuam sem binding dedicado. - Cobertura de
messagese parcial para chaves fora do fluxo principal de submit/confirmacao. - Ainda falta bateria de stress dedicada para corrida teardown/render alem de
NG0205. hintspermanece no contrato/editor sem exposicao no template principal.
Source references
projects/praxis-dynamic-form/src/lib/praxis-dynamic-form.tsprojects/praxis-dynamic-form/src/lib/praxis-dynamic-form.htmlprojects/praxis-dynamic-form/src/lib/config-editor/praxis-dynamic-form-config-editor.tsprojects/praxis-dynamic-fields/src/lib/directives/dynamic-field-loader.directive.tsprojects/praxis-core/src/lib/models/form/form-config.model.tsprojects/praxis-core/src/lib/models/form/form-layout.model.ts
JSON path index
| Path | Type | Required | Default | Status | Notes |
|---|---|---|---|---|---|
sections[] |
not-specified | not-specified | n/a | Active | Render estrutural principal (section/row/column). |
fieldMetadata[] |
not-specified | not-specified | n/a | Active | Fonte de campos para DynamicFieldLoader. |
metadata |
not-specified | not-specified | n/a | Active | Usado em reconciliacao/snapshot/status de schema. |
actions |
not-specified | not-specified | n/a | Active | Render de praxis-form-actions e roteamento de eventos. |
behavior |
not-specified | not-specified | n/a | Partial | Subset funcional (detalhado abaixo). |
api |
not-specified | not-specified | n/a | Declared-only | Declarado no modelo; sem binding operacional direto no runtime atual. |
messages |
not-specified | not-specified | n/a | Partial | Chaves principais de submit/confirmacao usadas; contrato e mais amplo. |
formRules |
not-specified | not-specified | n/a | Active | Aplicadas no pipeline de regras do runtime. |
formRulesState |
internal-round-trip | Gerado pelo builder visual; nao e alvo de autoria manual ou IA. | n/a | Internal | Estado visual derivado de formRules para reabertura do editor. |
hooks |
not-specified | not-specified | n/a | Active | Integracao de ciclo (before/after) via runtime de hooks. |
hints |
not-specified | not-specified | n/a | Declared-only | Mantido no contrato/editor; sem render dedicado no template principal. |
Events
| Event | Payload | Trigger | Stability | Notes |
|---|---|---|---|---|
formSubmit |
FormSubmitEvent |
Submit validado do formulario. | Partial | formData e o payload persistivel filtrado; rawFormData preserva o valor completo do formulario, incluindo campos locais/transientes. |
formCancel |
void |
Acao cancelar. | Partial | Preservado da documentação anterior. |
formReset |
void |
Acao reset. | Partial | Preservado da documentação anterior. |
configChange |
FormConfig |
Alteracoes de layout/config durante edicao. | Partial | Preservado da documentação anterior. |
configPatchChange |
{ inputPatch: { config?: FormConfig; resourcePath?: string | null; mode?: DynamicFormMode; presentationModeGlobal?: boolean | null; presentation?: DynamicFormPresentationSnapshot | null } } |
Alteracoes autoradas de configuracao que devem ser persistidas pelo host. | Partial | Contrato aditivo para hosts genericos sem alterar o payload legado de configChange. |
formReady |
FormReadyEvent |
Form pronto para interacao. | Partial | Preservado da documentação anterior. |
valueChange |
FormValueChangeEvent |
Alteracao de valor no form runtime. | Partial | Preservado da documentação anterior. |
syncCompleted |
SyncResult |
Sincronizacao de schema/config concluida. | Partial | Preservado da documentação anterior. |
initializationError |
FormInitializationError |
Falha de inicializacao. | Partial | Preservado da documentação anterior. |
loadingStateChange |
LoadingState |
Mudanca de loading (config/schema/render/data). |
Partial | Preservado da documentação anterior. |
enableCustomizationChange |
boolean |
Alternancia do modo de customizacao. | Partial | Preservado da documentação anterior. |
customAction |
FormCustomActionEvent |
Acao custom definida no contrato ou ação do header de seção. | Partial | source pode ser button, shortcut ou section-header; quando vier de header, o payload inclui sectionId. |
actionConfirmation |
FormActionConfirmationEvent |
Pedido de confirmacao de acao sensivel. | Partial | Preservado da documentação anterior. |
Styling API
| Token/Class | Scope | Purpose | Notes |
|---|---|---|---|
.praxis-dynamic-form |
root container | raiz visual/estrutural do runtime | Recebe classes derivadas de modo, estado e montagem no template principal. |
.form-loading / .form-error |
state containers | feedback de carregamento e falha de inicializacao | Acionados durante bootstrap/config/schema e erros de inicializacao. |
.pfx-form-info-banner |
schema-drift banner | aviso de schema desatualizado + CTA de reconciliacao | Exibicao condicionada por notifyIfOutdated e estado de drift. |
--pdx-form-mount-duration / --pdx-form-mount-offset / --pdx-form-mount-stagger |
css vars (host style) | controle de animacao de montagem | Definidos por bindings de estilo no host da raiz do formulario. |
Editor and tooling notes
- Cobertura de editor/tooling foi separada da cobertura de runtime para evitar confusao de suporte.
- Quando nao houver evidencia direta no codigo, o status deve permanecer not yet verified.
Examples
Minimal valid
{
"sections": []
}
Typical/common
{
"sections": [
{
"id": "main",
"title": "Dados",
"sectionHeader": {
"mode": "auto",
"sourceField": "employeePhoto",
"initialsSourceField": "fullName",
"altField": "fullName"
},
"rows": [
{
"id": "r1",
"columns": [
{
"id": "c1",
"span": 12,
"fields": ["fullName"]
}
]
}
]
}
],
"fieldMetadata": [
{ "name": "employeePhoto", "label": "Foto", "controlType": "input" },
{ "name": "fullName", "label": "Nome", "controlType": "input" }
]
}
Advanced
{
"sections": [],
"behavior": {
"reactiveValidation": true,
"reactiveValidationDebounceMs": 300
},
"messages": {
"customActions": {
"submit": {
"success": "Registro salvo com sucesso."
}
}
},
"hooks": {
"beforeSubmit": [
{
"type": "custom",
"handler": "sanitizePayload"
}
]
}
}
Enterprise scenario
{
"sections": [],
"api": {
"resourcePath": "customers",
"schemaSource": "resource"
},
"behavior": {
"notifyIfOutdated": "both",
"autoOpenSettingsOnOutdated": true
},
"messages": {
"global": {
"saveError": "Nao foi possivel salvar no momento."
}
}
}
Known limitations and mismatches
| Path/Behavior | Observed behavior (runtime) | Desired behavior | Impact | Tracking issue | Target fix |
|---|---|---|---|---|---|
| coverage/mapping | Evidência textual preservada indica itens Partial/Declared-only. | Cobertura confirmada por evidência runtime + schema + editor. | Pode gerar uso de paths não totalmente ligados. | to-be-linked | next-doc-cycle |
Compatibility and migration notes
| Concern | Affected versions | Migration action | Deadline | Notes |
|---|---|---|---|---|
| legacy aliases and mixed status vocabulary | pre-canonical docs | unificar para taxonomia canonica (Active/Partial/Declared-only/...) | next-doc-cycle | manter backward compatibility documentada |
Source references
| Source type | Path/URL | Why it is source of truth | Last verified (YYYY-MM-DD) | Notes |
|---|---|---|---|---|
| local-file | projects/praxis-dynamic-form/src/lib/praxis-dynamic-form.ts | Evidencia de implementacao e contrato. | 2026-03-05 | referencia preservada da versao anterior |
| local-file | projects/praxis-dynamic-form/src/lib/praxis-dynamic-form.html | Evidencia de implementacao e contrato. | 2026-03-05 | referencia preservada da versao anterior |
| local-file | projects/praxis-dynamic-form/src/lib/config-editor/praxis-dynamic-form-config-editor.ts | Evidencia de implementacao e contrato. | 2026-03-05 | referencia preservada da versao anterior |
| local-file | projects/praxis-dynamic-fields/src/lib/directives/dynamic-field-loader.directive.ts | Evidencia de implementacao e contrato. | 2026-03-05 | referencia preservada da versao anterior |
| local-file | projects/praxis-core/src/lib/models/form/form-config.model.ts | Evidencia de implementacao e contrato. | 2026-03-05 | referencia preservada da versao anterior |
| local-file | projects/praxis-core/src/lib/models/form/form-layout.model.ts | Evidencia de implementacao e contrato. | 2026-03-05 | referencia preservada da versao anterior |
Presentation style projection and editor UX
contextSnapshot.presentationis the canonical style snapshot. The optional runtime inputpresentation: DynamicFormPresentationSnapshot | nullprojects it into page widgets independently of schema-generatedconfig. Explicit styles take precedence over stored style preferences;nullrestores defaults and blocks stale stored overrides; omission retains normal style resolution.- Runtime editor Apply/Save emits
presentationwithmodeandpresentationModeGlobalinconfigPatchChange.inputPatch. Widget save/reopen preserves the same snapshot; omitting the document block clears the widget projection withnull. - Numeric font sizes and label widths are pixels. Capturing a runtime
remsize converts it using the host root font size; opening and saving must not reinterpret0.78remas0.78px. - Geral → Dados do formulário separates Criar / Editar / Visualizar from Automático / Campos / Apresentação. Selecting presentation in Create/Edit keeps the operation unchanged and explains the inactive state with an explicit action to switch to View.
- Estilo da apresentação remains discoverable regardless of the current mode. It previews sample data and does not activate presentation by itself. Filter Form does not expose this tab because it has no presentation runtime.
- Applying or finishing widget editing updates the page draft. Salvar página persists the composition. Shortening sample text affects the preview only.
Orientação antes da seleção de um registro
O editor nativo, em Geral → Sem registro selecionado, materializa o contrato existente PraxisDynamicFormEmptyState em bindings.emptyState. O wrapper Page Builder projeta esse binding para inputs.emptyState; Apply, Save e JSON usam o mesmo documento. Não pertence a FormConfig nem substitui o modo dos dados.
title é obrigatório e não pode conter apenas espaços. description e icon são textos opcionais; a cópia de negócio permanece literal, sem ser interpretada automaticamente como chave i18n. O seletor usa o catálogo canônico de ícones. Restaurar o ícone padrão limpa a escolha explícita. Os controles do editor usam o catálogo i18n Form; a aparência runtime usa os tokens do empty state compartilhado.
As opções de aparência ficam em disclosure avançado: tone (neutral, primary, secondary), variant (card, inline, panel, transparent), alignment (start, center), density (compact, comfortable) e iconContainer (none, circle, soft). Ausência de opção herda o padrão do componente; JSON inválido produz diagnóstico.
A orientação aparece somente em mode=view, sem registro selecionado nem snapshot local. Criar e Editar preservam a configuração sem exibi-la. Desligar grava null, que impede reativação por uma preferência antiga; substituir um documento que omite o binding também limpa a orientação. Em input-first, a página governa o valor. Filter Form não expõe essa seção, pois não possui contexto de seleção equivalente.