New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@praxisui/dynamic-form

Package Overview
Dependencies
Maintainers
1
Versions
66
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@praxisui/dynamic-form

Angular dynamic form engine for Praxis UI: metadata-driven forms, hooks, and services integrating @praxisui/* packages.

latest
Source
npmnpm
Version
1.0.0-beta.28
Version published
Maintainers
1
Created
Source

@praxisui/dynamic-form

Standalone dynamic form component with schema-driven UI, native field cascades, settings integration, and a built-in configuration editor.

🔰 Exemplos / Quickstart

Para ver esta biblioteca em funcionamento em uma aplicação completa, utilize o projeto de exemplo (Quickstart):

  • Repositório: https://github.com/codexrodrigues/praxis-ui-quickstart
  • O Quickstart demonstra a integração das bibliotecas @praxisui/* em um app Angular, incluindo instalação, configuração e uso em telas reais.

Install

npm i @praxisui/dynamic-form

Peer dependencies (Angular v20):

  • @angular/core ^20.0.0
  • @angular/common ^20.0.0
  • @angular/cdk ^20.0.0
  • @praxisui/core ^0.0.1
  • @praxisui/specification-core ^0.0.1
  • @praxisui/specification ^0.0.1
  • @praxisui/visual-builder ^0.0.1
  • @praxisui/settings-panel ^0.0.1
  • @praxisui/cron-builder ^0.0.1

Quick Start

1) PraxisDynamicForm (standalone)

import { Component } from '@angular/core';
import { PraxisDynamicForm } from '@praxisui/dynamic-form';
import type { FormConfig } from '@praxisui/core';

@Component({
  selector: 'app-form-demo',
  standalone: true,
  imports: [PraxisDynamicForm],
  template: `
    <praxis-dynamic-form
      [config]="config"
      [mode]="'create'"
      [editModeEnabled]="true"
      (formSubmit)="onSubmit($event)"
    ></praxis-dynamic-form>
  `,
})
export class FormDemoComponent {
  config: FormConfig = {
    sections: [
      {
        id: 'main',
        label: 'Employee',
        rows: [
          {
            columns: [
              { fields: [{ name: 'fullName', label: 'Full Name', controlType: 'text' }] },
              { fields: [{ name: 'email', label: 'E-mail', controlType: 'email' }] },
            ],
          },
        ],
      },
    ],
  } as any;

  onSubmit(evt: any) {
    console.log('Submitted:', evt);
  }
}

Tip: connect to a backend resource by setting resourcePath/resourceId. The component can fetch schemas and reconcile local layout with server metadata when editModeEnabled is true.

2) Config Editor component

Use the standalone editor directly to edit and reconcile the form configuration.

import { Component } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { PraxisDynamicFormConfigEditor } from '@praxisui/dynamic-form';
import type { FormConfig } from '@praxisui/core';

@Component({
  selector: 'app-form-editor-launcher',
  standalone: true,
  template: `<button (click)="openEditor()">Open Config Editor</button>`,
})
export class FormEditorLauncherComponent {
  constructor(private dialog: MatDialog) {}

  openEditor() {
    const initial: FormConfig = { sections: [] } as any;
    this.dialog.open(PraxisDynamicFormConfigEditor, {
      width: '1024px',
      data: { formConfig: initial, formId: 'employees-form', mode: 'edit' },
    });
  }
}

Alternatively, when editModeEnabled is true, praxis-dynamic-form renders a gear button that opens the editor internally.

API Surface

  • Components: PraxisDynamicForm, PraxisDynamicFormConfigEditor, JsonConfigEditorComponent, LayoutEditorComponent
  • Services: FormConfigService, FormLayoutService, DynamicFormLayoutService, FormContextService
  • Utilities: form rule converters, normalize date arrays
  • Metadata helpers: providePraxisDynamicFormMetadata

See public exports: projects/praxis-dynamic-form/src/public-api.ts.

Layout padrão (sem FormConfig)

Quando o componente não recebe uma FormConfig prévia (primeira execução), ele gera um layout padrão a partir do metadata do backend:

  • Linhas/colunas: 2 campos por linha (padrão). Em telas pequenas (xs/sm) os campos empilham (1 por linha), e a partir de md ficam lado a lado.
  • Responsividade do grid (12 colunas):
    • xs: 12, sm: 12, md: 6, lg: 6, xl: 6 (para 2 por linha). Para outros valores, a regra é base = floor(12 / fieldsPerRow).
  • Largura dos campos: mat-form-field { width: 100% } dentro do praxis-dynamic-form, garantindo que o campo ocupe toda a coluna.
  • Editor de Configuração: ao abrir a aba “Layout”, o editor reflete esse layout padrão; ao aplicar/salvar, persiste a FormConfig no storage do host.
  • Personalização: você pode ajustar o layout pelo Editor (arrastar/seções/linhas/colunas, alterar spans) ou fornecer uma FormConfig completa via [config].

Form Actions — Layout & Styling

A barra de ações (onde ficam "ENVIAR", "Cancelar", etc.) é configurável via config.actions e pelo Editor (aba "Ações").

Defaults

  • Rótulo do botão principal: ENVIAR.
  • Posição estrutural: afterSections (renderiza abaixo da última seção).
  • Alinhamento: right.
  • Orientação: horizontal.
  • Espaçamento: normal.
  • Background: sem cor por padrão (herda da superfície). Configure via containerStyles ou containerClassName se desejar uma superfície própria.

Estrutura (parcial)

interface FormActionsLayout {
  submit: FormActionButton;     // id, label, color, type, variant, shortcut, etc.
  cancel: FormActionButton;
  reset: FormActionButton;
  custom?: FormActionButton[];  // botões extras

  // Layout/posicionamento
  placement?: 'afterSections' | 'insideLastSection' | 'top';
  position?: 'left' | 'center' | 'right' | 'justified' | 'split';
  orientation?: 'horizontal' | 'vertical';
  spacing?: 'compact' | 'normal' | 'spacious';
  sticky?: boolean; // fixa a barra (bottom)

  // Estilização do container
  containerClassName?: string;      // adiciona classe ao container
  containerStyles?: { [k: string]: any }; // estilos inline (camelCase)

  // Mobile
  mobile?: { position?: 'left'|'center'|'right'|'justified'; orientation?: 'horizontal'|'vertical'; collapseToMenu?: boolean };
}

Exemplo (config)

config.actions = {
  submit: { visible: true, label: 'ENVIAR', type: 'submit', color: 'primary', variant: 'raised', shortcut: 'ctrl+s' },
  cancel: { visible: true, label: 'Cancelar', type: 'button', color: 'basic' },
  reset:  { visible: false, label: 'Reset' },
  placement: 'afterSections',
  position: 'right',
  orientation: 'horizontal',
  spacing: 'normal',
  sticky: false,
  containerClassName: 'my-form-actions',
  containerStyles: {
    background: 'var(--md-sys-color-surface-container)',
    border: '1px solid var(--md-sys-color-outline-variant)',
    borderRadius: '12px',
    padding: '12px 16px'
  },
  mobile: { collapseToMenu: true }
};

CSS por classe (opcional)

.my-form-actions {
  background: var(--md-sys-color-surface-container);
  border: 1px solid var(--md-sys-color-outline-variant);
  border-radius: 12px;
  padding: 12px 16px;
}

Dicas

  • Cores do botão: use color = primary|accent|warn|basic (respeitam o tema Material).
  • Tokens M3: prefira --mat-sys-* / --md-sys-* para cores/superfícies.
  • Mobile: ative collapseToMenu para colapsar botões extras em menu nas telas pequenas.

Section titles — espaçamento global

O título de seção usa por padrão margin: 0 0 6px 0. Você pode ajustar globalmente via CSS var:

/* Global (app host) */
:root { --pfx-section-title-mb: 10px; } // ex.: 10px abaixo do título

Ou por seção, via metadado titleGapBottom (em pixels), que aplica inline somente naquela seção.

Compatibility

  • @praxisui/dynamic-form 0.0.x → Angular 20.x
  • Module format: ESM2022

License

Apache-2.0 – see the LICENSE packaged with this library or the repository root.

Praxis Dynamic Form — Cascata vs Connections

Concept Usage

Quando usar cada mecanismo

  • Connections (dot‑path)

    • Para orquestração “externa” (entre widgets, tabs, tabelas ou fora do formulário).
    • Escrevem em inputs.config.* do widget do formulário, inclusive metadados de campos (ex.: inputs.config.fieldMetadata[i].filterCriteria).
    • Escala bem para cenários de página e integração cross‑widget.
  • Cascata nativa (campo→campo, intra‑form)

    • Declarativa via metadata (dependencyFields, resetOnDependentChange, etc.).
    • Observa FormControl.valueChanges dos campos dependentes, aplica filterCriteria e recarrega conforme estratégia (loadOn, dependencyLoadOnChange).
    • Elimina código ad hoc na página.

Convivência e fonte de verdade

  • Se Connections atualizam filterCriteria de um campo, considere desativar a cascata nativa nesse campo (enableDependencyCascade: false) ou usar dependencyLoadOnChange: 'manual' (cascata só atualiza filtros e Connections disparam o load).
  • Estratégia de merge recomendada: dependencyMergeStrategy: 'merge' para preservar chaves vindas de Connections.
  • Fluxo de Schema (ETag/304, schemaId, reconciliação): docs/schemas/fluxo-schema.md
  • Guia de implementação e metadados da cascata: docs/CASCADE-NATIVA.md
  • Padrões de endpoints (Options vs Filter) para selects: docs/DEVS-GENERIC-CRUD-SERVICE.md

Verificação de Schema (ETag/If-None-Match)

  • Inputs (opcionais; ativos apenas com editModeEnabled=true):
    • notifyIfOutdated: 'inline' | 'snackbar' | 'both' | 'none' = 'both'
    • snoozeMs: number = 86400000
    • autoOpenSettingsOnOutdated: boolean = false
  • Output:
    • schemaStatusChange: { outdated: boolean; serverHash?: string; lastVerifiedAt?: string; formId?: string }
  • Persistência (ConfigStorage):
    • form-schema-meta:{formId}{ serverHash?: string; lastVerifiedAt?: string }
    • form-schema-prefs:{formId}{ notifyIfOutdated?, snoozeMs?, autoOpenSettingsOnOutdated? }
    • Por hash (suppress): schemaIgnore:{formId}:{hash}, schemaSnooze:{formId}:{hash}, schemaNotified:{formId}:{hash}
  • Comportamento:
    • Quando já existe base local (ex.: config.sections.length > 0), o componente faz uma verificação leve via /schemas/filtered com If-None-Match.
    • 304 → apenas atualiza lastVerifiedAt e emite schemaStatusChange(outdated=false).
    • 200 → atualiza serverHash/lastVerifiedAt, define schemaOutdated = editModeEnabled && hadBase, emite schemaStatusChange. Não aplica schema automaticamente.
    • Primeira vez (sem base): baixa o corpo do schema para gerar o layout; persiste form-schema-meta:{formId}.
    • Notificações respeitam preferências e são one‑shot por hash; o banner/snackbar oferecem ações para Reconciliar, Lembrar depois (snooze) e Ignorar.

URL da API (absoluto vs relativo)

  • Quando API_URL.default.baseUrl for relativo (ex.: '/api'), a lib resolve a origem a partir de location.origin no browser. Isso cobre o cenário comum com proxy de dev (/api, /schemas).
  • Em SSR (sem location.origin), configure baseUrl absoluto (ex.: https://api.acme.com/api) para evitar erros do tipo “Invalid URL” ao construir chamadas de /schemas/filtered.
  • O GenericCrudService.getSchemasFilteredBaseUrl() retorna sempre uma URL absoluta; o SchemaMetadataClient também aceita baseUrl relativo quando há origin disponível.

Keywords

angular

FAQs

Package last updated on 07 Nov 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts