# Chapitre 3 : Formulaires
## Form
Le composant `Form` gère la soumission et la validation des formulaires.
### Syntaxe de base
```javascript
import { Form, Input, Button } from '@cap-rel/smartcommon';
function ContactForm() {
const handleSubmit = (values) => {
console.log(values);
// { name: 'Jean', email: 'jean@example.com' }
};
return (
);
}
```
### Avec valeurs initiales
```javascript
function EditProductForm({ product }) {
const handleSubmit = async (values) => {
await api.private.put(`products/${product.id}`, { json: values });
};
return (
);
}
```
## Input
Champ de saisie texte polyvalent.
### Props principales
^ Prop ^ Type ^ Description ^
| name | string | Nom du champ (obligatoire) |
| label | string | Libellé affiché |
| type | string | 'text', 'email', 'password', 'number', 'tel' |
| placeholder | string | Texte indicatif |
| required | boolean | Champ obligatoire |
| disabled | boolean | Champ désactivé |
| error | string | Message d'erreur |
### Exemples
```javascript
// Texte simple
// Email avec validation
// Mot de passe
// Nombre
// Téléphone
// Avec placeholder
// Désactivé
```
## Textarea
Zone de texte multiligne.
```javascript
import { Textarea } from '@cap-rel/smartcommon';
```
## Select
Liste déroulante.
```javascript
import { Select } from '@cap-rel/smartcommon';
// Options simples
// Avec valeur vide
// Options depuis une API
function ProductForm() {
const [categories, setCategories] = useState([]);
useEffect(() => {
api.private.get('categories').json().then(data => {
setCategories(data.map(c => ({
value: c.id,
label: c.name
})));
});
}, []);
return (
);
}
```
## Boolean
Interrupteur on/off.
```javascript
import { Boolean } from '@cap-rel/smartcommon';
```
## Checker
Case à cocher.
```javascript
import { Checker } from '@cap-rel/smartcommon';
// Groupe de cases
```
## Calendar
Sélecteur de date.
```javascript
import { Calendar } from '@cap-rel/smartcommon';
// Date simple
// Avec contraintes
// Date et heure
```
## Timer
Sélecteur d'heure.
```javascript
import { Timer } from '@cap-rel/smartcommon';
```
## Range
Slider de valeur.
```javascript
import { Range } from '@cap-rel/smartcommon';
```
## ColorPicker
Sélecteur de couleur.
```javascript
import { ColorPicker } from '@cap-rel/smartcommon';
```
## FilesUploader
Upload de fichiers.
```javascript
import { FilesUploader } from '@cap-rel/smartcommon';
```
## PhotosUploader
Upload de photos avec prévisualisation.
```javascript
import { PhotosUploader } from '@cap-rel/smartcommon';
```
## SignaturePad
Zone de signature manuscrite.
```javascript
import { SignaturePad } from '@cap-rel/smartcommon';
```
## Exemple complet : Formulaire produit
```javascript
import { useEffect } from 'react';
import {
Page,
Block,
Form,
Input,
Textarea,
Select,
Boolean,
Calendar,
PhotosUploader,
Button
} from '@cap-rel/smartcommon';
import { useApi, useNavigation, useStates } from '@cap-rel/smartcommon';
export const ProductFormPage = ({ productId }) => {
const api = useApi();
const navigate = useNavigation();
const isEdit = !!productId;
const st = useStates({
initialStates: {
product: null,
categories: [],
loading: isEdit,
submitting: false
}
});
// Charger les catégories
useEffect(() => {
api.private.get('categories').json().then(data => {
st.set('categories', data.map(c => ({
value: c.id,
label: c.name
})));
});
}, []);
// Charger le produit si édition
useEffect(() => {
if (isEdit) {
api.private.get(`products/${productId}`).json().then(data => {
st.set('product', data);
st.set('loading', false);
});
}
}, [productId]);
const handleSubmit = async (values) => {
st.set('submitting', true);
try {
if (isEdit) {
await api.private.put(`products/${productId}`, { json: values });
} else {
await api.private.post('products', { json: values });
}
navigate('/products');
} catch (err) {
alert('Erreur : ' + err.message);
} finally {
st.set('submitting', false);
}
};
if (st.get('loading')) {
return ;
}
return (
);
};
```
## Validation avec Zod
```javascript
import { z } from 'zod';
import { Form, Input, Button } from '@cap-rel/smartcommon';
import { useForm } from '@cap-rel/smartcommon';
const schema = z.object({
email: z.string().email('Email invalide'),
password: z.string().min(8, 'Minimum 8 caractères'),
confirmPassword: z.string()
}).refine(data => data.password === data.confirmPassword, {
message: 'Les mots de passe ne correspondent pas',
path: ['confirmPassword']
});
function RegisterForm() {
const form = useForm({ schema });
const handleSubmit = async (data) => {
// data est validé
console.log(data);
};
return (
);
}
```
## Points clés à retenir
1. **Form** gère la soumission et collecte les valeurs
2. **name** est obligatoire sur chaque champ
3. **defaultValues** pour pré-remplir (édition)
4. **required** pour les champs obligatoires
5. **Zod** pour la validation avancée
[[:15_training:module6-smartcommon-composants:navigation|← Chapitre précédent]] | [[:15_training:module6-smartcommon-composants:start|Retour au module]] | [[:15_training:module6-smartcommon-composants:affichage|Chapitre suivant : Affichage →]]