
Eine React -Komponente zum Bearbeiten oder Betrachten von JSON/Object -Daten

Wichtig
Veränderungen brechen:
theme . Integrierte Themen müssen jetzt separat importiert und eingegeben werden, anstatt nur das Thema als Zeichenfolge zu benennen. Dies ist besser für Baumschütteln, daher werden nicht verwendete Themen mit Ihrem Build nicht gebündelt. Sehen Sie Themen und Stile ansetData -Requisite bereitzustellen und onUpdate nicht zur Aktualisierung Ihrer Daten extern zu verwenden. Siehe Verwaltungsstaat. npm i json-edit-react
oder
yarn add json-edit-react
import { JsonEditor } from 'json-edit-react'
// In your React component:
return
< JsonEditor
data = { jsonData }
setData = { setJsonData } // optional
{ ... otherProps } /> (für Endbenutzer)
Es ist ziemlich selbsterklärend (klicken Sie auf das Symbol "Bearbeiten" zum Bearbeiten usw.), aber es gibt einige nicht so offensichtliche Möglichkeiten, mit dem Editor zu interagieren:
Cmd/Ctrl/Shift-Enter , um eine neue Zeile hinzuzufügen (geben Enter den Wert ein.Enter und Cmd/Ctrl/Shift-Enter für SendenEscape um die Bearbeitung abzusagenCmd/Ctrl den Pfad eher zum ausgewählten Knoten als in seinen WertjsonParse Prop. Der einzige erforderliche Wert sind data (obwohl Sie eine setData -Methode zur Aktualisierung Ihrer Daten bereitstellen müssen).
| Stütze | Typ | Standard | Beschreibung |
|---|---|---|---|
data | object|array | Die zu angezeigten / bearbeiteten Daten | |
setData | object|array => void | Methode zur Aktualisierung Ihres data . Weitere Notizen finden Sie weiter unten. | |
rootName | string | "data" | Ein Name, der im Editor als Stamm des Datenobjekts angezeigt wird. |
onUpdate | UpdateFunction | Eine Funktion zum Ausführen, wenn ein Wert im Editor aktualisiert wird (bearbeiten, löschen oder hinzufügen). Siehe Update -Funktionen. | |
onEdit | UpdateFunction | Eine Funktion zum Ausführen, wenn ein Wert bearbeitet wird. | |
onDelete | UpdateFunction | Eine Funktion zum Ausführen, wenn ein Wert gelöscht wird. | |
onAdd | UpdateFunction | Eine Funktion zum Ausführen, wenn eine neue Eigenschaft hinzugefügt wird. | |
onChange | OnChangeFunction | Eine Funktion zum Ändern/Einschränken der Benutzereingabe, wenn sie eingeben - siehe Onchange -Funktionen. | |
onError | OnErrorFunction | Eine Funktion zum Ausführen, wenn die Komponente einen Fehler meldet - siehe OnErrorfunction. | |
showErrorMessages | boolean | true | Unabhängig davon, ob die Komponente ihre eigenen Fehlermeldungen anzeigen sollte (Sie möchten dies wahrscheinlich nur deaktivieren, wenn Sie Ihre eigene onError -Funktion zur Verfügung gestellt haben) |
enableClipboard | boolean|CopyFunction | true | Ob die Schaltfläche "In die Zwischenablage kopieren" in der Benutzeroberfläche aktiviert werden soll. Wenn eine Funktion bereitgestellt wird, wird true angenommen und diese Funktion wird ausgeführt, wenn ein Element kopiert wird. |
indent | number | 3 | Geben Sie den Einklimmzusatz für jede Nesting -Ebene in den angezeigten Daten an. |
collapse | boolean|number|FilterFunction | false | Definiert, welche Knoten des JSON -Baums in der Benutzeroberfläche "geöffnet" werden. Wenn boolean , wird es entweder alles oder keine sein. Eine number gibt eine Nisttiefe an, wonach die Knoten geschlossen werden. Für eine bessere Steuerung kann eine Funktion bereitgestellt werden - siehe Filterfunktionen. |
collapseAnimationTime | number | 300 | Zeit (in Millisekunden) für die Übergangsanimation beim Zusammenbruch der Sammlungsknoten. |
restrictEdit | boolean|FilterFunction | false | Wenn true , ist keine Bearbeitung erlaubt. Eine Funktion kann für mehr Spezifität bereitgestellt werden - siehe Filterfunktionen |
restrictDelete | boolean|FilterFunction | false | Wie bei restrictEdit , aber zum Löschen |
restrictAdd | boolean|FilterFunction | false | Wie bei restrictEdit , aber zum Hinzufügen neuer Eigenschaften |
restrictTypeSelection | boolean|DataType[]|TypeFilterFunction | true | Zur Einschränkung der Datentypen, die der Benutzer auswählen kann. Kann eine Liste von Datentypen sein (z. B. [ 'string', 'number', 'boolean', 'array', 'object', 'null' ] oder ein Booleschen. Es kann eine Funktion bereitgestellt werden - sie sollte den gleichen Eingang wie die oben genannten FilterFunction s erfordern, aber die Ausgabe sollte boolean | DataType[] . |
restrictDrag | boolean|FilterFunction | true | Setzen Sie auf false um Drag & Drop -Funktionen zu aktivieren. Siehe Drag-N-Drop |
searchText | string | undefined | Die Sichtbarkeit der Daten wird durch Übereinstimmung mit dem Wert unter Verwendung der unten in searchFilter definierten Methode gefiltert |
searchFilter | "key"|"value"|"all"|SearchFilterFunction | undefined | Definieren Sie, wie searchText angepasst werden sollte, um die sichtbaren Elemente zu filtern. Siehe Suche/Filterung |
searchDebounceTime | number | 350 | Entdecken Sie die Zeit, wenn sich searchText ändert |
keySort | boolean|CompareFunction | false | Wenn true , werden Objektschlüssel bestellt (unter Verwendung von Standard JS .sort() ). Eine Vergleichenfunktion kann auch bereitgestellt werden, um das Sortierverhalten zu definieren. |
showArrayIndices | boolean | true | Ob der Index (als Eigenschaftstaste) für Array -Elemente angezeigt wird oder nicht. |
showStringQuotes | boolean | true | Ob Sie Stringwerte in "Zitate" anzeigen sollen oder nicht. |
showCollectionCount | boolean|"when-closed" | true | Ob die Anzahl der Elemente in jeder Sammlung (Objekt oder Array) angezeigt wird oder nicht. |
defaultValue | any|DefaultValueFilterFunction | null | Wenn eine neue Eigenschaft hinzugefügt wird, wird sie mit diesem Wert initialisiert. Eine Funktion kann mit der gleichen Eingabe wie der FilterFunction s geliefert werden, sollte jedoch einen Wert ausgeben. Auf diese Weise kann ein anderer Standardwert je nach Datenzustand verwendet werden (z. B. Standard für die oberste Ebene ist ein Objekt, aber eine Zeichenfolge an anderer Stelle.) |
stringTruncate | number | 250 | Stringwerte länger als viele Zeichen werden angezeigt (mit ... ) angezeigt. Die vollständige Saite wird bei der Bearbeitung immer sichtbar sein. |
translations | LocalisedStrings Stringsobjekt | { } | UI -Zeichenfolgen (z. B. Fehlermeldungen) können übersetzt werden, indem ein Objekt mit lokalisierten Zeichenfolgenwerten bestanden wird (es gibt nur wenige). Siehe Lokalisierung |
theme | ThemeInput | default | Entweder eines der integrierten Themen (separat importiert) oder ein Objekt, das einige oder alle Themeneigenschaften angibt. Sehen Sie Themen. |
className | string | Name einer CSS -Klasse, die für die Komponente angewendet wird. In den meisten Fällen ist die Angabe von theme einfacher. | |
id | string | Name für das HTML id -Attribut im Hauptkomponenten -Container. | |
icons | {[iconName]: JSX.Element, ... } | { } | Ersetzen Sie die integrierten Symbole, indem Sie sie hier angeben. Sehen Sie Themen. |
minWidth | number|string (CSS -Wert) | 250 | Mindestbreite für den Editorbehälter. |
maxWidth | number|string (CSS -Wert) | 600 | Maximale Breite für den Editorbehälter. |
rootFontSize | number|string (CSS -Wert) | 16px | Die Schriftgröße "Basis", aus der alle anderen Ansiedlungen abgeleitet werden (in em S). Wenn Sie dies ändern, skalieren Sie die gesamte Komponente. Container. |
customNodeDefinitions | CustomNodeDefinition[] | Sie können angepasste Komponenten zur Übergabe bestimmter Knoten im Datenbaum entsprechend einer Bedingungsfunktion bereitstellen. Weitere Informationen finden Sie unter benutzerdefinierten Knoten. (Eine einfache benutzerdefinierte Komponente, um URL -Zeichenfolgen in aktive Links zu verwandeln, finden Sie im Hauptpaket - siehe hier) | |
customText | CustomTextDefinitions | Zusätzlich zur Lokalisierung der Komponententext -Zeichenfolgen können Sie sie je nach Daten dynamisch ändern. Weitere Details finden Sie in benutzerdefinierten Text. | |
customButtons | CustomButtonDefinition[] | [] | Sie können Ihre eigene Schaltflächen zum Panel der Bearbeitungsschaltfläche hinzufügen, wenn Sie einen benutzerdefinierten Vorgang für die Daten ausführen möchten. Siehe benutzerdefinierte Tasten |
jsonParse | (input: string) => JsonData | JSON.parse | Wenn Sie direkt einen JSON -Block bearbeiten, möchten Sie möglicherweise einige "lockerere" Eingaben - z. B. "einzelne Zitate", nachfolgende Kommas oder nicht geeignete Feldnamen zulassen. In diesem Fall können Sie eine JSON-Parsing-Methode von Drittanbietern bereitstellen. Ich empfehle JSON5, was in der Demo verwendet wird |
jsonStringify | (data: JsonData) => string | (data) => JSON.stringify(data, null, 2) | In ähnlicher Weise können Sie die Standardpräsentation der JSON -String überschreiben, wenn Sie mit dem Bearbeiten von JSON beginnen. Sie können dem nativen JSON.stringify() unterschiedliche Formatierungsparameter liefern oder eine Option Dritter wie den oben genannten JSON5 bereitstellen. |
errorMessageTimeout | number | 2500 | Zeit (in Millisekunden), die Fehlermeldung in der Benutzeroberfläche anzuzeigen. |
keyboardControls | KeyboardControls | Wie oben erläutert | Überschreiben Sie einige oder alle Tastatursteuerungen. Einzelheiten finden Sie in der Tastaturanpassung. |
insertAtTop | boolean| "object | "array" | false | Wenn true , fügt oben als unten neue Werte ein. Kann das Verhalten nur für Arrays oder Objekte festlegen, indem sie auf "object" bzw. "array" einstellen. |
Es wird empfohlen, den data selbst außerhalb dieser Komponente selbst zu verwalten. Geben Sie einfach eine setData -Methode über, die intern aufgerufen wird, um Ihre data zu aktualisieren. Dies ist jedoch nicht obligatorisch. Wenn Sie keine setData -Methode angeben, werden die Daten intern verwaltet, was in Ordnung wäre, wenn Sie mit den Daten nichts tun. Die Alternative besteht darin, die Aktualisierungsfunktionen zu verwenden, um Ihre data extern zu aktualisieren. Dies wird jedoch unter besonderen Umständen nur empfohlen, da Sie Probleme mit dem Inhalt der Synchronisierung Ihrer Daten mit dem internen Zustand (was angezeigt wird) sowie unnötige Neuanbieter. Aktualisierungsfunktionen sollten idealerweise nur zur Implementierung von Nebenwirkungen, zur Überprüfung von Fehlern oder zur Mutation der Daten verwendet werden, bevor sie mit setData festgelegt werden.
Ein Rückruf, der ausgeführt werden soll, wenn ein Daten -Update (bearbeiten, löschen oder hinzufügen) ausgeführt werden kann. Möglicherweise möchten Sie dies verwenden, um einen externen Zustand zu aktualisieren, einen API -Anruf zu tätigen, die Daten vor dem Speichern zu ändern oder die Datenstruktur gegen ein JSON -Schema zu validieren. Wenn Sie die gleiche Funktion für alle Updates wünschen, reicht nur die onUpdate -Requisite aus. Sollten Sie jedoch etwas anderes für Bearbeitung, Löschung und Ergänzung benötigen, können Sie über die onEdit , onDelete und onAdd -Requisiten separate Aktualisierungsfunktionen bereitstellen.
Die Funktion empfängt das folgende Objekt als Parameter:
{
newData , // data state after update
currentData , // data state before update
newValue , // the new value of the property being updated
currentValue , // the current value of the property being updated
name , // name of the property being updated
path // full path to the property being updated, as an array of property keys
// (e.g. [ "user", "friends", 1, "name" ] ) (equivalent to "user.friends[1].name")
}Die Funktion kann nichts zurückgeben (in diesem Fall werden die Daten normal aktualisiert) oder ein Wert, um Erfolg/Ausfall, Fehlerwert oder geänderte Daten darzustellen. Der Rückgabewert kann einer der folgenden sein und entsprechend behandelt werden:
true / void / undefined : Die Daten werden wie normal aktualisiertfalse : Betrachtet das Update einen Fehler, sodass die Daten nicht aktualisiert werden (um den vorherigen Wert zurückzukehren), und eine generische Fehlermeldung wird in der Benutzeroberfläche angezeigtstring : Auch als Fehler berücksichtigt, also keine Datenaktualisierung, aber die UI -Fehlermeldung ist Ihre bereitgestellte Zeichenfolge[ "value", <value> ] : Gibt der Komponente an, die zurückgegebene <value> anstelle der Eingabedaten zu verwenden. Sie können dies verwenden, um die Benutzereingabe automatisch zu ändern - beispielsweise das Sortieren eines Arrays oder das Einfügen eines Zeitstempels in ein Objekt.[ "error", <value> ] : Gleich wie string , aber im längeren Tupelformat. Ähnlich wie bei den Aktualisierungsfunktionen wird die onChange -Funktion ausgeführt, wenn sich die Benutzereingabe ändert. Sie können dies verwenden, um die Benutzereingabe einzuschränken oder einzuschränken - z. B. die Begrenzung der Zahlen auf positive Werte oder die Verhinderung von Linienbrüchen in Saiten. Die Funktion muss einen Wert zurückgeben, um das Feld des Benutzereingabediums zu aktualisieren. Wenn also keine Änderungen vorgenommen werden sollen, geben Sie ihn einfach unmodifiziert zurück.
Das Eingabeobjekt ähnelt der Aktualisierungsfunktionseingabe, jedoch ohne newData -Feld (da dieser Vorgang vor der Aktualisierung der Daten erfolgt).
// in <JsonEditor /> props
onChange = ( { newValue , name } ) => {
if ( name === "age" && newValue < 0 ) return 0 ;
if ( name === "age" && newValue > 100 ) return 100 ;
return newValue
} onChange = ( { newValue , name } ) => {
if ( name === 'name' && typeof newValue === "string" )
return newValue . replace ( / [^a-zA-Zs]|n|r / gm , '' ) ;
return newValue ;
} Normalerweise zeigt die Komponente einfache Fehlermeldungen an, wenn eine Fehlerbedingung erkannt wird (z. B. ungültige JSON -Eingabe, doppelte Schlüssel oder benutzerdefinierte Fehler, die von den onUpdate -Funktionen zurückgegeben werden)). Sie können jedoch Ihren eigenen onError -Rückruf bereitstellen, um Ihre eigene Fehler Benutzeroberfläche zu implementieren oder zusätzliche Nebenwirkungen auszuführen. (Im ersteren Fall möchten Sie wahrscheinlich auch die showErrorMessages -Requisit deaktivieren.) Die Eingabe in den Rückruf ähnelt den anderen Rückernständen:
{
currentData , // data state before update
currentValue , // the current value of the property being updated
errorValue , // the erroneous value that failed to update the property
name , // name of the property being updated
path , // full path to the property being updated, as an array of property keys
// (e.g. [ "user", "friends", 1, "name" ] ) (equivalent to "user.friends[1].name"),
error : {
code , // one of 'UPDATE_ERROR' | 'DELETE_ERROR' | 'ADD_ERROR' | 'INVALID_JSON' | 'KEY_EXISTS'
message // the (localised) error message that would be displayed
}
}(Ein Beispiel für eine benutzerdefinierte Fehler -Benutzeroberfläche ist in der Demo mit dem Datensatz "benutzerdefinierte Knoten" zu sehen. Wenn Sie ungültige JSON -Eingabetaste ein "Toast" -Meldung eingeben, wird anstelle der normalen Komponentenfehlermeldung angezeigt.)
Ein ähnlicher Rückruf wird ausgeführt, wenn ein Element in die Zwischenablage kopiert wird (wenn sie an die enableClipboard -Requisite übergeben wird), jedoch mit einem anderen Eingabeparameter:
key // name of the property being copied
path // path to the property
value // the value copied to the clipboard
type // Either "path" or "value" depending on whether "Cmd/Ctrl" was pressed
stringValue // A nicely stringified version of `value`
// (i.e. what the clipboard actually receives)Da beim Klicken auf "Kopie" nur sehr wenig Benutzerfeedback vorhanden ist, wäre eine gute Idee, eine Art Benachrichtigung in diesem Rückruf vorzulegen.
Zusätzlich zu den Schaltflächen "Kopieren", "Bearbeiten" und "Löschen", die nach jedem Wert angezeigt werden, können Sie Ihre eigenen Schaltflächen hinzufügen, wenn Sie einige benutzerdefinierte Operationen für die Daten zulassen müssen. Geben Sie in der folgenden Definitionsstruktur eine Reihe von Schaltflächendefinitionen in der customButtons -Requisition an:
{
Element : React . FC ,
onClick : ( nodeData : NodeData , e : React . MouseEvent ) => void
} Wobei NodeData dieselbe Datenstruktur ist, die von den vorherigen "Aktualisierungsfunktionen" empfangen wird.
Sie können steuern, welche Knoten der Datenstruktur bearbeitet, gelöscht oder zu dem Datentyp geändert werden können, indem Sie Filterfunktionen übergeben. Diese werden auf jeder Eigenschaft in den Daten aufgerufen und das Attribut wird durchgesetzt, je nachdem, ob die Funktion true oder false zurückgibt ( true Mittel können nicht bearbeitet werden).
Die Funktion empfängt das folgende Objekt:
{
key , // name of the property
path , // path to the property (as an array of property keys)
level , // depth of the property (with 0 being the root)
index , // index of the node within its collection (based on display order)
value , // value of the property
size , // if a collection (object, array), the number of items (null for non-collections)
parentData , // parent object containing the current node
fullData // the full (overall) data object
collapsed // whether or not the current node is in a
// "collapsed" state (only for Collection nodes)
} Eine Filterfunktion ist auch für die collapse -Requisite verfügbar, sodass Sie Ihre Daten bei beispielsweise beispielsweise zusammengebundenen Sammlungen erscheint, während Sie beispielsweise alles andere zusammenbrechen.
Für die Einschränkung von Datentypen ist die (Typ-) Filterfunktion etwas anspruchsvoller. Die Eingabe ist gleich, aber der Ausgang kann entweder ein boolean haben (der die verfügbaren Typen für einen bestimmten Knoten entweder auf alle oder keine beschränken würde) oder ein Array von Datentypen, auf die eingeschränkt werden soll. Die verfügbaren Werte sind:
"string""number""boolean""null""object""array" Es gibt keine spezifische Einschränkungsfunktion für die Bearbeitung von Schlüsselnamen von Objektschlüsseln, sie müssen jedoch sowohl für restrictEdit als auch für restrictDelete (und restrictAdd für Sammlungen) true , da das Ändern eines Schlüsselnamens dem Löschen einer Eigenschaft und dem Hinzufügen einer neuen gleichwertig entspricht.
Sie können auch einen dynamischen Standardwert festlegen, indem Sie eine Filterfunktion an die defaultValue -Prop übergeben - die Eingabe ist mit dem oben genannten Eingang übereinstimmt, nimmt jedoch auch den neuen key als zweiter Parameter an, sodass der neue Wert von der neuen Taste abhängen kann.
Durch die Verwendung all dieser Einschränkungsfilter gemeinsam können Sie ein einigermaßen ausgefeilter Datenschema durchsetzen.
// in <JsonEditor /> props
restrictEdit = { ( { level } ) => level === 0 }id -Feld nicht bearbeitet: restrictEdit = { ( { key } ) => key === "id" }
// You'd probably want to include this in `restrictDelete` as well restrictDelete = { ( { size } ) => size !== null } restrictAdd = { ( { key } ) => key !== "address" && key !== "users" }
// "Adding" is irrelevant for non-collection nodesstring können nur in Zeichenfolgen oder Objekte geändert werden (zum Nisten)null ist nirgendwo erlaubtboolean Werte müssen boolean bleiben restrictTypeSelection = { ( { path , value } ) => {
if ( path . includes ( 'user' ) ) return [ 'string' , 'number' , 'boolean' ]
if ( typeof value === 'boolean' ) return false
if ( typeof value === 'string' ) return [ 'string' , 'object' ]
return [ 'string' , 'number' , 'boolean' , 'array' , 'object' ] // no "null"
} }Es ist nicht nur dynamisch, den Zugriff auf die verschiedenen Bearbeitungswerkzeuge zu steuern, wie oben beschrieben, und es ist möglich, eine vollständige JSON-Schema-Validierung durchzuführen, indem eine Aktualisierungsfunktion erstellt wird, die die Daten an eine 3rd-Party-Schema-Validierungsbibliothek (z. B. AJV) übergibt. Dies lehnt dann jede ungültige Eingabe ab und zeigt einen Fehler in der Benutzeroberfläche (oder über eine benutzerdefinierte Onerror -Funktion) an. Sie können ein Beispiel dafür in der Demo mit dem Datensatz "JSON -Schema -Validierung" (und dem Datensatz "benutzerdefinierte Knoten") sehen.
Ein Beispiel für onUpdate -Validierungsfunktion (mit AJV) könnte ungefähr so sein:
import { JsonEditor } from 'json-edit-react'
import Ajv from 'ajv'
import schema from './my-json-schema.json'
const ajv = new Ajv ( )
const validate = ajv . compile ( schema )
/// Etc....
// In the React component:
return
< JsonEditor
data = { jsonData }
onUpdate = { ( { newData } ) => {
const valid = validate ( newData )
if ( ! valid ) {
console . log ( 'Errors' , validate . errors )
const errorMessage = validate . errors
?. map ( ( error ) => ` ${ error . instancePath } ${ error . instancePath ? ': ' : '' } ${ error . message } ` )
. join ( 'n' )
// Send detailed error message to an external UI element, such as a "Toast" notification
displayError ( {
title : 'Not compliant with JSON Schema' ,
description : errorMessage ,
status : 'error' ,
} )
// This string returned to and displayed in json-edit-react UI
return 'JSON Schema error'
}
} }
{ ... otherProps } />Notiz
Dies ist ein neues Merkmal und sollte als "experimentell" angesehen werden. Bitte geben Sie Feedback oder Vorschläge zur Verbesserung.
Die Eigenschaft restrictDrag steuert, welche Elemente (falls vorhanden) in neue Positionen gezogen werden können. Standardmäßig ist dies ausgeschaltet , sodass Sie restrictDrag = false festlegen müssen, um diese Funktionalität zu ermöglichen. Wie die obigen Bearbeitungsbeschränkungen kann diese Eigenschaft auch eine Filterfunktion für die feinkörnige Kontrolle übernehmen. Es gibt jedoch einige zusätzliche Überlegungen:
jsonb -Typ (Binary JSON) ist beispielsweise die Schlüsselreihenfolge bedeutungslos. Wenn das Objekt das nächste Mal geladen wird, werden die Tasten alphabetisch aufgeführt.restrictDrag -Filter gilt für das Quellelement (dh der zugezogene Knoten), nicht für das Ziel.restrictDelete Requisite) auch gelöscht werden, da das Ziehen eines Knotens zu einem neuen Ziel im Wesentlichen nur löscht und an anderer Stelle zurückgefügt wird. Die angezeigten Daten können basierend auf der Sucheingabe eines Benutzers gefiltert werden. Die Benutzereingabe sollte unabhängig voneinander erfasst werden (wir geben hier keine Benutzeroberfläche an) und mit der searchText -Requisite übergeben. Dieser Eingang wird intern ausgebildet (die Zeit kann mit der searchDebounceTime -Requisite festgelegt werden), so dass dies auch nicht erforderlich ist. Die Werte, gegen die der searchText getestet wird, werden mit der searchFilter -Prop angegeben. Standardmäßig (kein searchFilter definiert) stimmt mit den Datenwerten überein (mit unempfindlicher Teilanpassung-dh Eingabe "ILB" entspricht dem Wert "Bilbo").
Sie können angeben, was übereinstimmen soll, indem searchFilter auf "key" (übereinstimmen Eigenschaftennamen), "value" (die oben beschriebene Standardeinstellung) oder "all" (sowohl Eigenschaften als auch Werte übereinstimmen) festgelegt werden. Dies sollte für die meisten Anwendungsfälle ausreichen, aber Sie können Ihre eigene SearchFilterFunction angeben. Die Suchfunktion ist dieselbe Signatur wie die obigen Filterfunktionen, nimmt jedoch ein zusätzliches Argument für den searchText an
( { key , path , level , value , ... etc } : FilterFunctionInput , searchText : string ) => boolean Es gibt zwei Helferfunktionen ( matchNode() und matchNodeKey() ), die mit dem Paket exportiert wurden und das Erstellen Ihrer Suchfunktion möglicherweise erleichtert (dies sind die oben beschriebenen Funktionen für den "key" und "value" ). Sie können sehen, was sie hier tun.
Eine Beispiel für benutzerdefinierte Suchfunktion ist in der Demo mit dem Datensatz "Client -Liste" angezeigt - die Suchfunktion stimmt mit Namen und Benutzername überein und macht das gesamte "Client" -Objekt sichtbar, wenn eine dieser Übereinstimmungen entspricht, sodass sie verwendet werden kann, um eine bestimmte Person zu finden und ihre spezifischen Details zu bearbeiten:
( { path , fullData } , searchText ) => {
// Matches *any* node that shares a path (i.e. a descendent) with a matching name/username
if ( path ?. length >= 2 ) {
const index = path ?. [ 0 ]
return (
matchNode ( { value : fullData [ index ] . name } , searchText ) ||
matchNode ( { value : fullData [ index ] . username } , searchText )
)
} else return false
} Es gibt eine kleine Auswahl an eingebauten Themen (wie in der Demo-App). Um eines davon zu verwenden, importieren Sie es einfach aus dem Paket und geben Sie es als Themen -Requisite ein:
import { JsonEditor , githubDarkTheme } from 'json-edit-react'
// ...other imports
const MyApp = ( ) => {
const [ data , setData ] = useState ( { one : 1 , two : 2 } )
return < JsonEditor
data = { data }
setData = { setData }
theme = { githubDarkTheme }
// other props...
/>
}Die folgenden Themen sind im Paket erhältlich (obwohl realistisch gesehen mehr existieren, um die Fähigkeiten zu präsentieren-ich bin offen für bessere integrierte Themen. Sie können also gerne ein Problem mit Vorschlägen erstellen):
githubDarkThemegithubLightThememonoDarkThememonoLightThemecandyWrapperThemepsychedelicThemeSie können jedoch Ihr eigenes Themenobjekt oder einen Teil davon übergeben. Die Themenstruktur lautet wie folgt (dies ist die "Standard" -Thema -Definition):
{
displayName : 'Default' ,
fragments : { edit : 'rgb(42, 161, 152)' } ,
styles : {
container : {
backgroundColor : '#f6f6f6' ,
fontFamily : 'monospace' ,
} ,
collection : { } ,
collectionInner : { } ,
collectionElement : { } ,
dropZone : { } ,
property : '#292929' ,
bracket : { color : 'rgb(0, 43, 54)' , fontWeight : 'bold' } ,
itemCount : { color : 'rgba(0, 0, 0, 0.3)' , fontStyle : 'italic' } ,
string : 'rgb(203, 75, 22)' ,
number : 'rgb(38, 139, 210)' ,
boolean : 'green' ,
null : { color : 'rgb(220, 50, 47)' , fontVariant : 'small-caps' , fontWeight : 'bold' } ,
input : [ '#292929' , { fontSize : '90%' } ] ,
inputHighlight : '#b3d8ff' ,
error : { fontSize : '0.8em' , color : 'red' , fontWeight : 'bold' } ,
iconCollection : 'rgb(0, 43, 54)' ,
iconEdit : 'edit' ,
iconDelete : 'rgb(203, 75, 22)' ,
iconAdd : 'edit' ,
iconCopy : 'rgb(38, 139, 210)' ,
iconOk : 'green' ,
iconCancel : 'rgb(203, 75, 22)' ,
} ,
} Die styles -Eigenschaft ist die wichtigste, auf die man sich konzentrieren kann. Jeder Schlüssel ( property , bracket , itemCount ) bezieht sich auf einen Teil der Benutzeroberfläche. Der Wert für jeden Schlüssel lautet entweder :
string , in diesem Fall wird sie als Farbe (oder Hintergrundfarbe im Fall von container und inputHighlight ) interpretiert)null ) zurückgibt. Auf diese Weise können Sie dynamisch das Styling verschiedener Elemente auf der Grundlage von Inhalten oder Struktur verändern.null zurückgibt. (Im Array haben die späteren Elemente höhere Vorrang)Wenn Sie das Thema "GithubDark" verwenden möchten, aber nur ein paar kleine Dinge ändern möchten, würden Sie so etwas spezifizieren:
// in <JsonEditor /> props
theme = { [
githubDarkTheme ,
{
iconEdit : 'grey' ,
boolean : { color : 'red' , fontStyle : 'italic' , fontWeight : 'bold' , fontSize : '80%' } ,
} ,
] } Dies würde das Symbol und die booleschen Werte "Bearbeiten" ändern: 
in dieses: 
Oder Sie können Ihr eigenes Thema von Grund auf erstellen und das gesamte Themenobjekt überschreiben.
Zusammenfassend lässt sich sagen, dass die theme -Requisite beide annehmen können:
"candyWrapperTheme"fragments , styles , displayName usw. oder nur dem styles (auf der Wurzelebene) strukturiert werden.[ "<themeName>, {...overrides } ]Sie können mit der Live -Bearbeitung der Themen in der Demo -App rund spielen, indem Sie "dieses Thema bearbeiten!" Aus dem Selektor "Demo -Daten" (obwohl Sie keine Funktionen in JSON erstellen können).
Eine andere Möglichkeit, die Komponente zu stylen, besteht darin, die CSS -Klassen direkt abzuzielen. Jedes Element in der Komponente hat einen eindeutigen Klassennamen, sodass Sie sie in Ihrem Browserinspektor lokalisieren und entsprechend überschreiben können. Alle Klassennamen beginnen mit jer-value-string Präfix jer- , z jer-collection-header-row
Die obige fragments -Eigenschaft ist nur ein Bequemlichkeit, damit ein einmaliger Stil "Fragmente" definiert und die Verwendung eines Alias verwiesen wird. Wenn Sie beispielsweise alle Ihre Symbole blau und etwas größer und verteilt haben möchten, können Sie ein Fragment wie SO definieren:
fragments: { iconAdjust : { color : "blue" , fontSize : "110%" , marginRight : "0.6em" } }Verwenden Sie dann im Themenobjekt einfach:
{
... ,
iconEdit : "iconAdjust" ,
iconDelete : "iconAdjust" ,
iconAdd : "iconAdjust" ,
iconCopy : "iconAdjust" ,
}Wenn Sie es später optimieren möchten, müssen Sie es nur an einem Ort aktualisieren!
Fragmente können auch mit zusätzlichen Eigenschaften und sogar anderen Fragmenten wie SO gemischt werden:
iconEdit: [ "iconAdjust" , "anotherFragment" , { marginLeft : "1em" } ] Intern werden alle Größen und Abstand in em S, niemals px (abgesehen von der rootFontSize , die die "Basis" -Größe festlegt). Dies erleichtert die Skalierung erheblich - ändern Sie einfach die rootFontSize -Requisite (oder setzen Sie fontSize auf dem Hauptcontainer, indem Sie die Klasse abzielen oder das Thema optimieren) und sehen Sie sich die gesamte Komponentenskala entsprechend an.
Die Standardsymbole können ersetzt werden, müssen sie jedoch als React/HTML -Elemente bereitstellen. Definieren Sie einfach irgendwelche oder alle von ihnen in der icons -Requisiten wie folgt:
icons = { {
add : < YourIcon />
edit : < YourIcon / >
delete : < YourIcon />
copy : < YourIcon / >
ok : < YourIcon / >
cancel : < YourIcon / >
chevron : < YourIcon / >
} }Die Symbolkomponenten müssen ihre eigenen Stile definieren, da die Themenstile nicht zu den benutzerdefinierten Elementen hinzugefügt werden.
Lokalisieren Sie Ihre Implementierung, indem Sie ein translations übergeben, um die Standardzeichenfolgen zu ersetzen. Die Schlüsseln- und Standardwerte (englische) Werte sind wie folgt:
{
ITEM_SINGLE : '{{count}} item' ,
ITEMS_MULTIPLE : '{{count}} items' ,
KEY_NEW : 'Enter new key' ,
ERROR_KEY_EXISTS : 'Key already exists' ,
ERROR_INVALID_JSON : 'Invalid JSON' ,
ERROR_UPDATE : 'Update unsuccessful' ,
ERROR_DELETE : 'Delete unsuccessful' ,
ERROR_ADD : 'Adding node unsuccessful' ,
DEFAULT_STRING : 'New data!' ,
DEFAULT_NEW_KEY : 'key' ,
} Sie können bestimmte Knoten im Datenbaum durch Ihre eigenen benutzerdefinierten Komponenten ersetzen. Ein Beispiel für eine Bildanzeige oder einen benutzerdefinierten Datumseditor oder nur um ein visuelles Bling hinzuzufügen. Siehe den Datensatz "benutzerdefinierte Knoten" in der interaktiven Demo, um ihn in Aktion zu sehen. (Es gibt auch eine benutzerdefinierte Datumswählerin, die beim Bearbeiten von ISO -Zeichenfolgen in den anderen Datensätzen angezeigt wird.)
Benutzerdefinierte Knoten finden Sie in der customNodeDefinitions -Requisition als Array von Objekten der folgenden Struktur:
{
condition , // a FilterFunction, as above
element , // React Component
customNodeProps , // object (optional)
hideKey , // boolean (optional)
defaultValue , // JSON value for a new instance of your component
showOnEdit // boolean, default false
showOnView // boolean, default true
showEditTools // boolean, default true
name // string (appears in Types selector)
showInTypesSelector , // boolean (optional), default false
// Only affects Collection nodes:
showCollectionWrapper // boolean (optional), default true
wrapperElement // React component (optional) to wrap *outside* the normal collection wrapper
wrapperProps // object (optional) -- props for the above wrapper component
} Die condition ist nur eine Filterfunktion mit denselben Eingabeparametern ( key , path , value usw.), und element ist eine React -Komponente. Jeder Knoten in der Datenstruktur wird durch jede Bedingungsfunktion ausgeführt, und jede Übereinstimmung wird durch Ihre benutzerdefinierte Komponente ersetzt. Beachten Sie, dass, wenn ein Knoten mehr als eine benutzerdefinierte Definitionsbedingungen (aus mehreren Komponenten) übereinstimmt, der erste verwendet wird. Stellen Sie sie daher in der Prioritätsreihenfolge in das Array ein.
Die Komponente empfängt alle gleichen Requisiten wie eine Standard -Knotenkomponente (siehe Codebasis), aber Sie können zusätzliche Requisiten an Ihre Komponente übergeben, falls dies über das customNodeProps -Objekt erforderlich ist. Ein gründliches Beispiel für einen benutzerdefinierten Datumswähler wird in der Demo verwendet (zusammen mit einigen anderen grundlegenderen Präsentationsdarstellern), die Sie überprüfen können, um zu sehen, wie die Standard -Requisiten und einige benutzerdefinierte Requisiten verwendet werden. Zeigen Sie den Quellcode hier an
Standardmäßig wird Ihre Komponente rechts von dem Eigenschaftschlüssel präsentiert, zu dem sie wie jeder andere Wert gehört. Sie können jedoch den Schlüssel selbst ausblenden, indem Sie hideKey: true einstellen, und die benutzerdefinierte Komponente nimmt die gesamte Zeile ein. (Siehe den Datensatz "benutzerdefinierte Knoten" im "präsentierten" Box ".) Ein Beispiel.)
Standardmäßig wird Ihre Komponente als "Anzeige" -Element behandelt, dh es wird im JSON -Betrachter angezeigt. Bei der Bearbeitung wird es jedoch zur Standardbearbeitungsschnittstelle zurückkehren. Dies kann jedoch mit den Requisiten showOnEdit , showOnView und showEditTools Aufgaben geändert werden. Beispielsweise kann ein Datumspicker möglicherweise nur beim Bearbeiten erforderlich sein und als IS zum Anzeigen gelassen werden. Die Requisite showEditTools bezieht sich auf die Bearbeitungssymbole (kopieren, hinzufügen, bearbeiten, löschen), die rechts von jedem Wert für den Schwebes erscheinen. Wenn Sie diese deaktivieren möchten, aber Sie möchten immer noch Ihre Komponente, um einen "Bearbeitungs" -Modus zu haben, müssen Sie Ihren eigenen UI -Mechanismus bereitstellen, um die Bearbeitung umzuschalten.
Sie können Benutzern ermöglichen, neue Instanzen Ihrer speziellen Knoten zu erstellen, indem Sie sie beim Bearbeiten/Hinzufügen von Werten als "Typ" im Selektor der Typen auswählen. SET showInTypesSelector: true , um dies zu aktivieren. Wenn dies jedoch aktiviert ist, müssen Sie auch einen name angeben (wie der Benutzer im Selektor angezeigt wird) und einen defaultValue , der die Daten sind, die eingefügt werden, wenn der Benutzer diesen "Typ" auswählt. (Der defaultValue muss true zurückgeben, wenn die condition übergeben wird, damit sie sofort mit Ihrer benutzerdefinierten Komponente angezeigt werden kann.)
Eine einfache benutzerdefinierte Komponente und eine einfache Definition, um URL -Zeichenfolgen in klickbare Links zu verwandeln, wird mit dem Hauptpaket zur Verfügung gestellt, damit Sie das Box verwenden können. Importieren und benutzen Sie einfach:
import { JsonEditor , LinkCustomNodeDefinition } from 'json-edit-react'
// ...Other stuff
return (
< JsonEditor
{ ... otherProps }
customNodeDefinitions = { [ LinkCustomNodeDefinition , ... otherCustomDefinitions ] }
/>
) In den meisten Fällen ist es vorzuziehen (und einfacher) , benutzerdefinierte Knoten zu erstellen, um Wertungsknoten (dh keine array oder object Knoten) zu entsprechen, was alle Demo -Beispiele anzeigen. Wenn Sie jedoch einen ganzen Sammlungsknoten ansprechen möchten , gibt es einige andere Dinge zu wissen:
children -Eigenschaft angezeigt werden, es wird einfach zur Verantwortung Ihrer Komponente, damit zu handhaben.element -Requisiten, die in den Sammlungsklammern angezeigt wird (dh sie erscheint als Inhalt der Sammlung)wrapperElement , die außerhalb der Sammlung angezeigt wird (Requisiten können wie oben beschrieben mit wrapperProps geliefert werden). Auch hier kann der innere Inhalt (einschließlich Ihres benutzerdefinierten element ) mit React children angezeigt werden. In diesem Beispiel zeigt der blaue Rand die wrapperElement und der rote Rand zeigt das innere element : 
showCollectionWrapper (Standard true ), die, wenn sie auf false festgelegt sind, die umgebenden Sammlungselemente (nämlich das Hide/Show Chevron und die Klammern) verbirgt. In diesem Fall müssten Sie in Ihrer Komponente Ihren eigenen Ausblenden-/Showmechanismus bereitstellen, falls Sie es möchten. Es ist möglich, die verschiedenen von der Komponente angezeigten Textketten zu ändern. Sie können es lokalisieren, aber Sie können auch Funktionen angeben, um den angezeigten Text basierend auf bestimmten Bedingungen zu überschreiben. Angenommen, wir möchten, dass der Eigenschaftszähltext (z. B. 6 items standardmäßig) eine Zusammenfassung eines bestimmten Knotentyps enthält, der beim Zusammenbruch gut aussehen kann. Zum Beispiel (aus der Demo entnommen):

Die customText -Eigenschaft nimmt ein Objekt mit einem der lokalisierbaren Schlüssel als Schlüssel mit einer Funktion, die eine Zeichenfolge zurückgibt (oder null , die es zum Rückfall in die lokalisierte oder standardmäßige Zeichenfolge zurückgibt). Die Eingabe für diese Funktionen ist die gleiche wie bei den Filterfunktionen. In diesem Beispiel würde sie also so definiert:
// The function definition
const itemCountReplacement = ( { key , value , size } ) => {
// This returns "Steve Rogers (Marvel)" for the node summary
if ( value instanceof Object && 'name' in value )
return ` ${ value . name } ( ${ ( value ) ?. publisher ?? '' } )`
// This returns "X names" for the alias lists
if ( key === 'aliases' && Array . isArray ( value ) )
return ` ${ size } ${ size === 1 ? 'name' : 'names' } `
// Everything else as normal
return null
}
// And in component props...
. . . otherProps ,
customText = {
ITEM_SINGLE : itemCountReplacement ,
ITEMS_MULTIPLE : itemCountReplacement ,
} Die standardmäßigen Tastatursteuerungen sind oben beschrieben, es ist jedoch möglich, diese anzupassen/zu überschreiben. Geben Sie einfach eine keyboardControls -Requisition mit den von Ihnen vorgelegten Aktionen ein. Das Standardkonfigurationsobjekt lautet:
{
confirm : 'Enter' , // default for all Value nodes, and key entry
cancel : 'Escape' ,
objectConfirm : { key : 'Enter' , modifier : [ 'Meta' , 'Shift' , 'Control' ] } ,
objectLineBreak : 'Enter' ,
stringConfirm : 'Enter' ,
stringLineBreak : { key : 'Enter' , modifier : 'Shift' } ,
numberConfirm : 'Enter' ,
numberUp : 'ArrowUp' ,
numberDown : 'ArrowDown' ,
booleanConfirm : 'Enter' ,
clipboardModifier : [ 'Meta' , 'Control' ] ,
collapseModifier : 'Alt' ,
}Wenn (zum Beispiel) Sie nur die allgemeine "Bestätigungs" -Aktion in "CMD-Enter" (auf Mac) oder "Strg-Inter" ändern möchten, geben Sie einfach ein:
keyboardControls = {
confirm : {
key : "Enter" ,
modifier : [ "Meta" , "Control" ]
}
}Überlegungen :
stringConfirm , numberConfirm und booleanConfirm angeben, wenn sie sich von Ihrem confirm unterscheiden sollten.clipboardModifier ). Auch wenn die Funktionalität der Rückgänger in den meisten Fällen wahrscheinlich wünschenswert ist, ist dies aus zwei Hauptgründen nicht in der Komponente eingebaut:
Einige Helferfunktionen, Komponenten und Typen, die in Ihren eigenen Implementierungen nützlich sein können (aus dem Erstellen von Filter- oder Aktualisierungsfunktionen oder benutzerdefinierten Komponenten), werden aus dem Paket exportiert:
themes : Ein Objekt, das alle integrierten Themendefinitionen enthältLinkCustomComponent : Die Komponente, die zum Rendern von Hyperlinks verwendet wirdLinkCustomNodeDefinition : benutzerdefinierte Knotendefinition für HyperlinksIconAdd , IconEdit , IconDelete , IconCopy , IconOk , IconCancel , IconChevron : alle integrierten SymbolkomponentenmatchNode , matchNodeKey : Helfer zum Definieren benutzerdefinierter Suchfunktionentruncate : Funktion zum Abschneiden einer Zeichenfolge auf eine bestimmte Länge. Siehe hierextract : Funktion zum extrahieren einen tief verschachtelten Objektwert aus einem String -Pfad. Siehe hierassign : Funktion zum Festlegen eines tiefen Objektwerts von einem String -Pfad. Siehe hierThemeName : String Literalliste der integrierten ThemennamenTheme : Ein vollständiges ThemenobjektThemeInput : Eingabetyp für die theme -RequisiteJsonEditorProps : Alle Eingabequellen für die JSON -Editor -KomponenteJsonData : data - jede gültige JSON -StrukturUpdateFunction , OnChangeFunction , OnErrorFunction FilterFunction , CopyFunction , SearchFilterFunction , CompareFunction , TypeFilterFunction , LocalisedString , CustomNodeDefinition , CustomTextDefinitions , CustomTextFunction ,TranslateFunction : Funktion, die einen Lokalisierungsschlüssel übernimmt und eine übersetzte Zeichenfolge zurückgibtIconReplacements : Eingabetyp für die icons -RequisiteCollectionNodeProps : Alle Requisiten übergeben intern an "Sammlung" -Knoten (dh Objekte/Arrays)ValueNodeProps : Alle Requisiten übergeben intern an "Wert" -Knoten (dh keine Objekte/Arrays)CustomNodeProps : Alle Requisiten übergeben intern an benutzerdefinierte Knoten; Grundsätzlich das Gleiche wie CollectionNodeProps mit einem extra customNodeProps -Feld für die Übergabe von Requisiten, die für Ihre Komponente einzigartig sindDataType : "string" | "number" | "boolean" | "null" | "object" | "array"KeyboardControls : Struktur für die Tastaturanpassungsqualifizierung Bitte öffnen Sie ein Problem: https://github.com/carlosnz/json-edit-react/issues
Die Hauptmerkmale, die ich vorstellen möchte, sind:
This component is heavily inspired by react-json-view, a great package that I've used in my own projects. However, it seems to have been abandoned now, and requires a few critical fixes, so I decided to create my own from scratch and extend the functionality while I was at it.
defaultValue function takes the new key as second parameteroverflow: clip setting based on animating statetrue to represent successsetData prop to discourage reliance on internal data state managementuseEffect hooksnull #90onError callback available for custom error handlingrootFontSize prop to set the "base" size for the componentonChange prop to allow validation/restriction of user input as they typedata if user hasn't actually changed a value (prevents Undo from being unnecessarily triggered)wrapperElement propid propindex in Filter (and other) function inputdefaultValue prop