Ana içeriğe geç

Dinamik Form Birleşeni

Çoğu projede NvsDynamicForm konfigürasyonunu her sayfada tekrar tekrar yazmak istemezsiniz.

Onun yerine proje seviyesinde bir DynamicForm component’i oluşturup şunları tek yerde sabitleyin:

  • formElements registry (field type → renderer + field model class)
  • buttonComponent
  • submit button varsayılan ayarları

Böylece sayfalar sadece fields ve onSubmit verir.

Bu sayfada ayrıca minimal Input ve Textarea field implementasyonları da var.

1) Field model class’ları + renderer’lar

Input

components/dynamic-form/fields/input.tsx
import React, { type ChangeEvent } from 'react';

import { FieldBase } from '@nvs-dynamic-form/react-core';

export class InputField extends FieldBase<string> {
override readonly fieldType? = 'input';

placeholder?: string;
type?: 'email' | 'number' | 'password' | 'tel' | 'text' | 'url';

constructor(options: InputField) {
super(options, '');
this.placeholder = options.placeholder ?? '';
this.type = options.type ?? 'text';
}
}

export function InputElement(props: any) {
return (
<input
{...props}
style={{ width: '100%', boxSizing: 'border-box' }}
placeholder={props.placeholder}
type={props.type ?? 'text'}
onChange={(e: ChangeEvent<HTMLInputElement>) => {
props.onChange?.(e);
props.field?.onChange?.(e);
}}
/>
);
}

Textarea

components/dynamic-form/fields/textarea.tsx
import React from 'react';

import { FieldBase } from '@nvs-dynamic-form/react-core';

export class TextareaField extends FieldBase<string> {
override readonly fieldType? = 'textarea';

placeholder?: string;
minRowSize?: number;
maxRowSize?: number;

constructor(options: TextareaField) {
super(options, '');
this.placeholder = options.placeholder ?? '';
this.minRowSize = options.minRowSize ?? 3;
this.maxRowSize = options.maxRowSize ?? 10;
}
}

export function TextareaElement(props: any) {
return (
<textarea
{...props}
style={{ width: '100%', boxSizing: 'border-box' }}
rows={props.minRowSize ?? 3}
placeholder={props.placeholder}
/>
);
}

2) Birleşeni oluştur

components/dynamic-form/DynamicForm.tsx
import React from 'react';

import {
NvsDynamicForm,
type INvsDynamicForm,
} from '@nvs-dynamic-form/react-core';

import { InputElement, InputField } from './fields/input';
import { TextareaElement, TextareaField } from './fields/textarea';

import { Button } from './ui/Button';

export type DynamicFormProps = Pick<
INvsDynamicForm,
| 'fields'
| 'onSubmit'
| 'formClass'
| 'submitButtonVisible'
| 'submitButtonLabel'
| 'submitButtonIsFullWidth'
| 'submitButtonPosition'
| 'doubleSubmitProtection'
>;

export function DynamicForm(props: DynamicFormProps) {
return (
<NvsDynamicForm
{...props}
buttonComponent={Button}
submitButtonDefaultOptions={{
label: 'Kaydet',
isFullWidth: true,
position: 'right',
}}
formElements={{
input: {
component: InputElement,
class: InputField,
},
textarea: {
component: TextareaElement,
class: TextareaField,
},
}}
/>
);
}

3) Bir sayfada kullan

pages/ProfileForm.tsx
import React from 'react';
import * as Yup from 'yup';

import { DynamicForm } from '../components/dynamic-form/DynamicForm';
import { InputField } from '../components/dynamic-form/fields/input';
import { TextareaField } from '../components/dynamic-form/fields/textarea';

export function ProfileFormPage() {
const fields = [
new InputField({
id: 'firstName',
label: 'Ad',
placeholder: 'Jane',
validate: Yup.string().required(),
screenSize: { desktop: 6, mobile: 12 },
}),
new InputField({
id: 'lastName',
label: 'Soyad',
placeholder: 'Doe',
screenSize: { desktop: 6, mobile: 12 },
}),
new TextareaField({
id: 'about',
label: 'Hakkında',
placeholder: 'Kendinden biraz bahset…',
minRowSize: 6,
screenSize: 12,
}),
];

return (
<DynamicForm
fields={fields}
onSubmit={(values) => {
console.log(values);
}}
/>
);
}