@stackhouseos/flower-json
v1.3.2
Published
Json to react
Downloads
168
Readme
FlowerJson
Libreria per la creazione di form e layout avanzati, è integrabile su qualsiasi progetto react/redux.
Table of Contents
Peer Dependencies
| Peer Dependency | Version | | --------------- | -------- | | react | ^16.11.0 | | react-redux | ^7.1.3 | | redux | ^4.0.4 |
Installation
npm install @stackhouseos/flower-json
Getting Started
• Basic
import FlowerJson from '@stackhouseos/flower-json';
const model = [{
type: 'input',
placeholder: 'Name',
id: 'name'
}]
<FlowerJson prefix="nomereducer" data={model} />
import FlowerJson from '@stackhouseos/flower-json';
const CustomInput = ({onChange, value, placeholder}) => {
return (
<input
value={value}
onChange={(evt) => onChange(evt.target.value)} placeholder={placeholder}
/>
)
}
FlowerJson.registerComponents({CustomInput});
const model = [
{
type: 'CustomInput',
placeholder: 'Name',
id: 'name'
}
]
<FlowerJson prefix="nomereducer" data={model} />
Attenzione per poter usare FlowerJson ricordati di estendere il tuo reducer con quello di FlowerJson
Esempio Reducer
Configs
FlowerJson
| Prop Name | Type | Is Required | Default Value | Description |
| ------------ | -------- | ----------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| data | array
| yes | | Schema del modello da visualizzare |
| prefix | string
| yes | | Path (dotStyle) è il nome del reducer in cui salvare e leggere i dati, es. tickets.detail |
| destroyValue | bool
| optional | false | Regola di default per tutti i child del modello, se true svuota il dato se il componente viene distrutto, utile quando ci sono le regole, si evita di lasciare dati sporchi nel form |
| selectors | object
| optional | null | Selettori validi da sostituire agli id o _id |
| replacer | object
| optional | null | Replacer dei valori da sostituire a replaceValue |
Child schema
| Prop Name | Type | Is Required | Default Value | Description |
| ----------------- | -------- | ------------------------ | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| type | string | component
| optional | div
| Componente da visualizzare |
| id | string | reselect
| optional | | redux path selector per leggere o salvare i dati |
| (?)_id | string | reselect
| optional | | permette di leggere i dati da un selettore diverso da id, in quetso caso id viene utilizzato solo per salvare, utile quando si usano le select, che devono salvare su id ma prendere i dati da un'altro selettore, name_id |
| (?)_default | string | reselect
| optional | | permette di impostare un valore di default ad un selettore dinamico _id |
| (?)_replaceValue | string
| optional | | permette di modificare il value finale che viene passato al componente |
| children | array
| optional | | Recursive children |
| (?)_children | array
| optional | | Recursive children |
| onChange | string | func({value, dispatch})
| optional, id
required | | Viene scatenata ad ogni aggiornamento dell'id corrispondente, se viene usata una stringa deve corrispondere ad una azione di redux |
| (?)_change | string
| optional | | Viene creata una nuova props per l'aggiornamento dello stato redux |
| onLoad | string | func({value, dispatch})
| optional,id
required | | Viene scatenata ad mount del compomente, se viene usata una stringa deve corrispondere ad una azione di redux |
| prefix | string
| optional | | Path (dotStyle) aggiunge un prefisso a tutti gli id successivi |
| container | string | object
| optional | | Wrappa il componente dentro un'altro componente |
| rules | array | object
| optional | | vedi lib [json-rules] |
| ruleModeDisable | bool
| optional | | Aggiunge la props disable nel componente, con false non si esegue il render del componente in base alle rules |
| validate | array | object
| optional | | vedi lib [json-rules] |
| required | bool
| optional | | campo obbligatorio, solo se presente id |
| pattern | string | regex
| optional | | es. "^[1-9][0-9]*$" |
| novalidate | bool
| optional | | esclude la validazione del campo |
| errorMessages | string | object
| optional | | es. Il campo è obbligatorio, oppure {required:'Richiesto', min: 'Lunghezza minima 5'}
|
| destroyValue | bool
| optional | false | se true svuota il dato se il componente viene distrutto, utile quando ci sono le regole, si evita di lasciare dati sporchi nel form |
| action | string | func
| optional | | Se stringa scatena un dispatch sul nome dell'azione, se funzione passa il dispatch per poter invocare azioni custom |
Child Component
I tuoi componenti custom riceveranno in automatico le seguenti props, oltre al tutte le proprietà che userai nel tuo schema
| Prop Name | Type | Description |
| -------------- | -------- | ---------------------------------------------------------------------------- |
| onChange | func
| Metodo per aggiornare i dati nell'id indicato |
| value | any
| Valore recuperato dal selettore |
| id | string
| Id child, obbligatorio se si vogliono leggere o salvare i dati su redux |
| child | object
| Schema del child corrente |
| onAction | func
| Da utilizzare per invocare il dispatch |
| disabled | bool
| in base alla rules |
| error | string
| in base a validation |
| onBlur | func
| Necessario per attivare la validazione degli input |
| renderChildren | func
| Utile per renderizzare nuovi componenti nello stesso contesto di validazione |
Id
Il campo id viene utilizzato per recuperare i dati da redux o context, allo stesso modo viene utilizzato per salvare i dati su redux
const model = [
{
type: 'CustomInput',
placeholder: 'Name',
id: 'name',
},
{
type: 'CustomInput',
placeholder: 'tipologia',
id: 'dettagli.tipologia',
}
]
<FlowerJson prefix="nomereducer" data={model} />
i dati potranno essere recuperati usando come id direttamente name, FlowerJson salverà i dati su redux nel reducer nomereducer.name
e nomereducer.dettagli.tipologia
Può essere utile anche recuperare i dati da altri reducer che non sono al livello di nomereducer
, tramite l'utilizzo del carattere ^ come prefisso dell'id, es:
• Redux state
const initialState = {
attivita: {items: [1,2,3]},
ticket: {name: 'Andrea', dettagli: {tipologia: 'dev'}}
}
import FlowerJson, { FlowerJsonContextProvider } from '@stackhouseos/box-core';
const model = [
{
type: 'Lista',
id: '^attivita.items', // print [1,2,3]
},
{
type: 'Testo',
id: 'ticket.dettagli.tipologia', // print 'dev'
},
{
type: 'Testo',
id: '^role', // print 'user'
}
]
<FlowerJsonContextProvider value={{ role: 'user' }}>
<FlowerJson prefix="ticket" data={model} />
</FlowerJsonContextProvider>
Questa convenzione sarà utilizzata anche per la gestione delle rules e validazioni
const model = [
{
type: 'Testo',
placeholder: 'Name',
id: 'name',
rules: {
'^role': {eq: 'user'} // appare solo se il ruolo utente è uguale a 'user'
},
validation: {
'name': { min: 10 } // verrà validato solo se rules è valido
}
}
]
Methods
• Add components
FlowerJson.extendComponents({ ...components });
• Set components
FlowerJson.setComponents({ ...onlyThiscomponents });
• Extends data with Context, per aggiungere dati che non sono su redux
import FlowerJson, { FlowerJsonContextProvider } from '@stackhouseos/box-core';
const model = [
{
type: 'Testo',
id: '^role', // print 'user'
}
]
<FlowerJsonContextProvider value={{ role: 'user' }}>
<FlowerJson prefix="ticket" data={model} />
</FlowerJsonContextProvider>
Rules and validation
| Key | Type | Description |
| --------- | -------- | ------------------------------------------------------------------------ |
| ^hasError | bool
| E' presente un errore nel form, vengono analizzati solo i child visibili |
| ^isValid | bool
| Il form è valido, vengono analizzati solo i child visibili |
| ^childId | string
| Valore della chiave |
Utile quando si vuole disabilitare il tasto salva se nel form sono presenti errori
• example
{
type: 'button',
title: 'SALVA',
ruleModeDisable: true,
rules: { '^hasError': { eq: false } }
}
• Child con regole
Tutti i child passati nel modello possono esser gestiti tramite rules, basterà appendere al nome _rules
{
type: 'button',
title_default: 'Salva', // titolo se non si trova nessuna corrispondenza con le regole
title_rules: {
'Aggiungi': {
'id' : {ex: false}, // il titolo sarà "Aggiungi" se id non esiste
},
'Salva': {
'id' : {ex: true}, // il titolo sarà "Salva" se id esiste, questa regola può essere omessa usando il title_default
}
},
}
• Root reducer
^
utilizare l'accento circonflesso, per recuperare i dati dalla root di reducer, questo ignora un qualasi prefix indicato
Prefissi
E' possibile aggiungere un prefisso a livello di componente
<FlowerJson prefix="nomereducer" />
oppure dentro un qualsiasi children. Aggiungendo un prefisso al padre sarà aggiunto in automatico a tutti i children figli.
const modello = [
{
id: 'name', // selector nomereducer.name
type: 'input'
},
{
type: 'grid',
prefix: 'dati',
children:[
{
id: 'name' // selector nomereducer.dati.name
},
{
id: 'lastname' // selector nomereducer.dati.lastname
}
]
}
]
<FlowerJson prefix="nomereducer" data={modello} />
Container
Capiterà molto spesso di dover mettere attorno ai tuoi children un componente di layout, questa operazione si potrà fare in 2 modi:
• Modalità normale
const model = [{
type: 'Paper',
children:[{type: 'text', text: 'ciao'}]
}]
// esempio da compilato
<Paper>
<Text>Ciao</Text>
</Paper>
• Modalità container base
const model = [{
container: 'Paper',
type: 'text',
text: 'ciao'
}]
// esempio da compilato
<Paper>
<Text>Ciao</Text>
</Paper>
• Modalità container con props
const model = [{
container: {type: 'Paper', color: 'red'},
type: 'text',
text: 'ciao'
}]
// esempio da compilato
<Paper color="red">
<Text>Ciao</Text>
</Paper>
Visualizzare tutti gli errori
Passare al context il campo showErrors: true, per visualizzare tutti gli errori
<FlowerJsonContextProvider value={{ showErrors: true }}>
<FlowerJson prefix="ticket" data={model} />
</FlowerJsonContextProvider>
Redux reducer
Se vuoi usare FlowerJson su un progetto esistente, ti basterà estendere il tuo reducer con l'azione di default
• Reducer example
import { boxReducer } from '@stackhouseos/box-core';
const ticketReducer = (state = initialState, action) =>
produce(state, () => {
switch (action.type) {
case DEFAULT_ACTION:
break;
case TUE_AZIONI:
break;
default:
// necessario per fare comunicare il tuo redux con FlowerJson
return boxReducer('folder', state, action);
}
});
• Reducer example Redux Toolkit
const slice = createSlice({
name: 'categories',
initialState,
reducers: {
// ... actions
},
extraReducers: {
// necessario per fare comunicare il tuo redux con FlowerJson
'@box/categories/update': (state, action) => _set(state, action.payload.id, action.payload.value),
},
});