Bevor Sie einen neuen Feldtyp erstellen, sollten Sie prüfen, ob eine der anderen Methoden zum Anpassen von Feldern Ihren Anforderungen entspricht. Wenn in Ihrer Anwendung ein neuer Werttyp gespeichert werden muss oder Sie eine neue Benutzeroberfläche für einen vorhandenen Werttyp erstellen möchten, müssen Sie wahrscheinlich einen neuen Feldtyp erstellen.
So erstellen Sie ein neues Feld:
- Implementieren Sie einen Konstruktor.
- JSON-Schlüssel registrieren und
fromJson
implementieren. - Initialisierung der On-Block-Benutzeroberfläche und Ereignis-Listener verarbeiten
- Entfernung von Event-Listenern verarbeiten (die Entfernung der Benutzeroberfläche wird für Sie übernommen).
- Wertverarbeitung implementieren
- Fügen Sie eine Textdarstellung des Feldwerts hinzu, um die Barrierefreiheit zu verbessern.
- Zusätzliche Funktionen hinzufügen, z. B.:
- Konfigurieren Sie zusätzliche Aspekte des Felds, z. B.:
In diesem Abschnitt wird davon ausgegangen, dass Sie den Inhalt von Aufbau eines Felds gelesen haben und damit vertraut sind.
Ein Beispiel für ein benutzerdefiniertes Feld finden Sie in der Demo zu benutzerdefinierten Feldern.
Konstruktor implementieren
Der Konstruktor des Felds ist für das Festlegen des Anfangswerts des Felds und optional für das Einrichten eines lokalen Validators verantwortlich. Der Konstruktor des benutzerdefinierten Felds wird während der Initialisierung des Quellblocks aufgerufen, unabhängig davon, ob der Quellblock in JSON oder JavaScript definiert ist. Das benutzerdefinierte Feld hat also während der Erstellung keinen Zugriff auf den Quellblock.
Im folgenden Codebeispiel wird ein benutzerdefiniertes Feld mit dem Namen GenericField
erstellt:
class GenericField extends Blockly.Field {
constructor(value, validator) {
super(value, validator);
this.SERIALIZABLE = true;
}
}
Methodensignatur
Feldkonstruktoren akzeptieren in der Regel einen Wert und einen lokalen Validator. Der Wert ist optional. Wenn Sie keinen Wert übergeben oder ein Wert übergeben wird, der die Klassenvalidierung nicht besteht, wird der Standardwert der Superklasse verwendet. Für die Standardklasse Field
ist dieser Wert null
. Wenn Sie diesen Standardwert nicht verwenden möchten, müssen Sie einen geeigneten Wert übergeben. Der Parameter „validator“ ist nur für bearbeitbare Felder vorhanden und wird in der Regel als optional gekennzeichnet. Weitere Informationen zu Validatoren
Struktur
Die Logik in Ihrem Konstruktor sollte diesem Ablauf folgen:
- Rufen Sie den geerbten Superkonstruktor auf (alle benutzerdefinierten Felder sollten von
Blockly.Field
oder einer seiner Unterklassen abgeleitet werden), um den Wert richtig zu initialisieren und den lokalen Validator für Ihr Feld festzulegen. - Wenn Ihr Feld serialisierbar ist, legen Sie die entsprechende Eigenschaft im Konstruktor fest. Bearbeitbare Felder müssen serialisierbar sein. Felder sind standardmäßig bearbeitbar. Sie sollten diese Property also wahrscheinlich auf „true“ setzen, sofern Sie nicht wissen, dass sie nicht serialisierbar sein sollte.
- Optional: Sie können zusätzliche Anpassungen vornehmen. Mit Label-Feldern kann beispielsweise eine CSS-Klasse übergeben werden, die dann auf den Text angewendet wird.
JSON und Registrierung
In JSON-Blockdefinitionen werden Felder durch einen String beschrieben (z.B. field_number
, field_textinput
). Blockly verwaltet eine Zuordnung dieser Strings zu Feldobjekten und ruft während der Konstruktion fromJson
für das entsprechende Objekt auf.
Rufen Sie Blockly.fieldRegistry.register
auf, um dieser Karte den Feldtyp hinzuzufügen. Übergeben Sie die Feldklasse als zweites Argument:
Blockly.fieldRegistry.register('field_generic', GenericField);
Sie müssen auch Ihre fromJson
-Funktion definieren. In Ihrer Implementierung sollten Sie zuerst alle Verweise auf Lokalisierungstokens mit replaceMessageReferences dereferenzieren und dann die Werte an den Konstruktor übergeben.
GenericField.fromJson = function(options) {
const value = Blockly.utils.parsing.replaceMessageReferences(
options['value']);
return new CustomFields.GenericField(value);
};
Wird initialisiert
Wenn Ihr Feld erstellt wird, enthält es im Grunde nur einen Wert. Bei der Initialisierung wird das DOM erstellt, das Modell erstellt (falls das Feld ein Modell enthält) und Ereignisse werden gebunden.
On-Block-Anzeige
Während der Initialisierung sind Sie dafür verantwortlich, alles zu erstellen, was für die On-Block-Anzeige des Felds erforderlich ist.
Standardeinstellungen, Hintergrund und Text
Mit der Standardfunktion initView
wird ein helles rect
-Element und ein text
-Element erstellt. Wenn Sie möchten, dass Ihr Feld beide Funktionen sowie einige zusätzliche Funktionen hat, rufen Sie die initView
-Funktion der Superklasse auf, bevor Sie die restlichen DOM-Elemente hinzufügen. Wenn Sie möchten, dass Ihr Feld nur eines dieser Elemente enthält, können Sie die Funktionen createBorderRect_
oder createTextElement_
verwenden.
DOM-Erstellung anpassen
Wenn Ihr Feld ein allgemeines Textfeld ist (z.B. Texteingabe), wird die DOM-Erstellung für Sie übernommen. Andernfalls müssen Sie die Funktion initView
überschreiben, um die DOM-Elemente zu erstellen, die Sie beim zukünftigen Rendern des Felds benötigen.
Ein Drop-down-Feld kann beispielsweise sowohl Bilder als auch Text enthalten. In initView
wird ein einzelnes Bild- und ein einzelnes Textelement erstellt. Während render_
wird dann das aktive Element angezeigt und das andere ausgeblendet, je nach Art der ausgewählten Option.
DOM-Elemente können entweder mit der Methode Blockly.utils.dom.createSvgElement
oder mit herkömmlichen DOM-Erstellungsmethoden erstellt werden.
Für die Anzeige eines Felds im Block gelten folgende Anforderungen:
- Alle DOM-Elemente müssen untergeordnete Elemente des
fieldGroup_
des Felds sein. Die Feldgruppe wird automatisch erstellt. - Alle DOM-Elemente müssen innerhalb der gemeldeten Abmessungen des Felds bleiben.
Weitere Informationen zum Anpassen und Aktualisieren der Anzeige auf dem Block finden Sie im Abschnitt Rendering.
Textsymbole hinzufügen
Wenn Sie dem Text eines Felds Symbole hinzufügen möchten, z. B. das Gradzeichen des Felds Winkel, können Sie das Symbolelement (normalerweise in einem <tspan>
) direkt an das textElement_
des Felds anhängen.
Eingabe-Ereignisse
Standardmäßig werden für Felder Tooltip-Ereignisse und mousedown-Ereignisse (zum Anzeigen von Editoren) registriert.
Wenn Sie auf andere Arten von Ereignissen reagieren möchten (z.B. wenn Sie das Ziehen in einem Feld verarbeiten möchten), sollten Sie die bindEvents_
-Funktion des Felds überschreiben.
bindEvents_() {
// Call the superclass function to preserve the default behavior as well.
super.bindEvents_();
// Then register your own additional event listeners.
this.mouseDownWrapper_ =
Blockly.browserEvents.conditionalBind(this.getClickTarget_(), 'mousedown', this,
function(event) {
this.originalMouseX_ = event.clientX;
this.isMouseDown_ = true;
this.originalValue_ = this.getValue();
event.stopPropagation();
}
);
this.mouseMoveWrapper_ =
Blockly.browserEvents.conditionalBind(document, 'mousemove', this,
function(event) {
if (!this.isMouseDown_) {
return;
}
var delta = event.clientX - this.originalMouseX_;
this.setValue(this.originalValue_ + delta);
}
);
this.mouseUpWrapper_ =
Blockly.browserEvents.conditionalBind(document, 'mouseup', this,
function(_event) {
this.isMouseDown_ = false;
}
);
}
Um ein Ereignis zu binden, sollten Sie im Allgemeinen die Funktion Blockly.utils.browserEvents.conditionalBind
verwenden. Bei dieser Methode zum Binden von Ereignissen werden sekundäre Berührungen während des Ziehens herausgefiltert. Wenn Ihr Handler auch während eines laufenden Drag-Vorgangs ausgeführt werden soll, können Sie die Funktion Blockly.browserEvents.bind
verwenden.
Entsorgung
Wenn Sie benutzerdefinierte Event-Listener in der bindEvents_
-Funktion des Felds registriert haben, müssen Sie sie in der dispose
-Funktion abmelden.
Wenn Sie die Ansicht Ihres Felds korrekt initialisiert haben (indem Sie alle DOM-Elemente an fieldGroup_
angehängt haben), wird das DOM des Felds automatisch verworfen.
Umgang mit Werten
→ Informationen zum Wert eines Felds im Vergleich zum Text finden Sie unter Aufbau eines Felds.
Validierungsreihenfolge
Klassenvalidator implementieren
In Felder sollten nur bestimmte Werte eingegeben werden können. In Zahlenfelder dürfen beispielsweise nur Zahlen eingegeben werden, in Farbfelder nur Farben usw. Das wird durch Klassen- und lokale Validatoren sichergestellt. Für den Klassenvalidator gelten dieselben Regeln wie für lokale Validatoren. Er wird jedoch auch im Konstruktor ausgeführt und sollte daher nicht auf den Quellblock verweisen.
Überschreiben Sie die Funktion doClassValidation_
, um den Klassenvalidator für Ihr Feld zu implementieren.
doClassValidation_(newValue) {
if (typeof newValue != 'string') {
return null;
}
return newValue;
};
Gültige Werte verarbeiten
Wenn der an ein Feld mit setValue
übergebene Wert gültig ist, erhalten Sie einen doValueUpdate_
-Callback. Standardmäßig gilt für die Funktion doValueUpdate_
:
- Legt das Attribut
value_
aufnewValue
fest. - Legt das Attribut
isDirty_
auftrue
fest.
Wenn Sie den Wert nur speichern und keine benutzerdefinierte Verarbeitung durchführen möchten, müssen Sie doValueUpdate_
nicht überschreiben.
Andernfalls können Sie Folgendes tun:
- Benutzerdefinierte Speicherung von
newValue
. - Ändern Sie andere Attribute basierend auf
newValue
. - Speichert, ob der aktuelle Wert gültig ist oder nicht.
Sie müssen doValueUpdate_
überschreiben:
doValueUpdate_(newValue) {
super.doValueUpdate_(newValue);
this.displayValue_ = newValue;
this.isValueValid_ = true;
}
Umgang mit ungültigen Werten
Wenn der an das Feld mit setValue
übergebene Wert ungültig ist, erhalten Sie einen doValueInvalid_
-Callback. Standardmäßig führt die Funktion doValueInvalid_
keine Aktion aus. Das bedeutet, dass ungültige Werte standardmäßig nicht angezeigt werden. Das Feld wird auch nicht neu gerendert, da die Eigenschaft isDirty_
nicht festgelegt wird.
Wenn Sie ungültige Werte anzeigen möchten, sollten Sie doValueInvalid_
überschreiben.
In den meisten Fällen sollten Sie für die Property displayValue_
den ungültigen Wert festlegen, isDirty_
auf true
setzen und override
render_ für die In-Block-Anzeige aktualisieren, damit sie auf displayValue_
statt auf value_
basiert.
doValueInvalid_(newValue) {
this.displayValue_ = newValue;
this.isDirty_ = true;
this.isValueValid_ = false;
}
Mehrteilige Werte
Wenn Ihr Feld einen mehrteiligen Wert enthält (z.B. Listen, Vektoren, Objekte), sollen die Teile möglicherweise wie einzelne Werte behandelt werden.
doClassValidation_(newValue) {
if (FieldTurtle.PATTERNS.indexOf(newValue.pattern) == -1) {
newValue.pattern = null;
}
if (FieldTurtle.HATS.indexOf(newValue.hat) == -1) {
newValue.hat = null;
}
if (FieldTurtle.NAMES.indexOf(newValue.turtleName) == -1) {
newValue.turtleName = null;
}
if (!newValue.pattern || !newValue.hat || !newValue.turtleName) {
this.cachedValidatedValue_ = newValue;
return null;
}
return newValue;
}
Im obigen Beispiel wird jede Eigenschaft von newValue
einzeln validiert. Wenn am Ende der doClassValidation_
-Funktion ein einzelnes Attribut ungültig ist, wird der Wert im Attribut cacheValidatedValue_
zwischengespeichert, bevor null
(ungültig) zurückgegeben wird. Durch das Zwischenspeichern des Objekts mit einzeln validierten Eigenschaften können diese von der Funktion doValueInvalid_
separat verarbeitet werden. Dazu ist lediglich eine !this.cacheValidatedValue_.property
-Prüfung erforderlich, anstatt jede Eigenschaft einzeln neu zu validieren.
Dieses Muster zum Validieren von mehrteiligen Werten kann auch in lokalen Validatoren verwendet werden, aber derzeit gibt es keine Möglichkeit, dieses Muster zu erzwingen.
isDirty_
isDirty_
ist ein Flag, das in der Funktion setValue
sowie in anderen Teilen des Felds verwendet wird, um anzugeben, ob das Feld neu gerendert werden muss. Wenn sich der Anzeigewert des Felds geändert hat, sollte isDirty_
in der Regel auf true
festgelegt werden.
Text
→ Informationen dazu, wo der Text eines Felds verwendet wird und wie er sich vom Wert des Felds unterscheidet, finden Sie unter Aufbau eines Felds.
Wenn sich der Text Ihres Felds vom Wert Ihres Felds unterscheidet, sollten Sie die Funktion getText
überschreiben, um den richtigen Text anzugeben.
getText() {
let text = this.value_.turtleName + ' wearing a ' + this.value_.hat;
if (this.value_.hat == 'Stovepipe' || this.value_.hat == 'Propeller') {
text += ' hat';
}
return text;
}
Editor erstellen
Wenn Sie die Funktion showEditor_
definieren, wartet Blockly automatisch auf Klicks und ruft showEditor_
zum richtigen Zeitpunkt auf. Sie können beliebigen HTML-Code in Ihrem Editor anzeigen, indem Sie ihn in eines von zwei speziellen Div-Elementen einfügen, die als „DropDownDiv“ und „WidgetDiv“ bezeichnet werden und über der restlichen Blockly-Benutzeroberfläche schweben.
DropDownDiv im Vergleich zu WidgetDiv
Mit DropDownDiv
werden Editoren bereitgestellt, die sich in einem Feld befinden. Es wird automatisch in der Nähe des Felds positioniert, bleibt aber innerhalb der sichtbaren Grenzen. Die Auswahl für Winkel und Farben sind gute Beispiele für die DropDownDiv
.
Mit dem WidgetDiv
können Sie Editoren bereitstellen, die nicht in einem Feld enthalten sind. In Zahlenfeldern wird das WidgetDiv verwendet, um das Feld mit einem HTML-Texteingabefeld zu überdecken. Während DropDownDiv die Positionierung für Sie übernimmt, ist das bei WidgetDiv nicht der Fall. Elemente müssen manuell positioniert werden. Das Koordinatensystem verwendet Pixelkoordinaten relativ zur oberen linken Ecke des Fensters. Der Texteditor ist ein gutes Beispiel für die WidgetDiv
.
Beispielcode für DropDownDiv
showEditor_() {
// Create the widget HTML
this.editor_ = this.dropdownCreate_();
Blockly.DropDownDiv.getContentDiv().appendChild(this.editor_);
// Set the dropdown's background colour.
// This can be used to make it match the colour of the field.
Blockly.DropDownDiv.setColour('white', 'silver');
// Show it next to the field. Always pass a dispose function.
Blockly.DropDownDiv.showPositionedByField(
this, this.disposeWidget_.bind(this));
}
Beispielcode für WidgetDiv
showEditor_() {
// Show the div. This automatically closes the dropdown if it is open.
// Always pass a dispose function.
Blockly.WidgetDiv.show(
this, this.sourceBlock_.RTL, this.widgetDispose_.bind(this));
// Create the widget HTML.
var widget = this.createWidget_();
Blockly.WidgetDiv.getDiv().appendChild(widget);
}
Bereinigen
Sowohl DropDownDiv als auch WidgetDiv kümmern sich um das Entfernen der Widget-HTML-Elemente. Sie müssen jedoch alle Event-Listener, die Sie auf diese Elemente angewendet haben, manuell entfernen.
widgetDispose_() {
for (let i = this.editorListeners_.length, listener;
listener = this.editorListeners_[i]; i--) {
Blockly.browserEvents.unbind(listener);
this.editorListeners_.pop();
}
}
Die Funktion dispose
wird in einem null
-Kontext für DropDownDiv
aufgerufen. Auf der WidgetDiv
wird sie im Kontext der WidgetDiv
aufgerufen. In beiden Fällen ist es am besten, die Funktion bind zu verwenden, wenn Sie eine Dispose-Funktion übergeben, wie in den obigen Beispielen für DropDownDiv
und WidgetDiv
gezeigt.
→ Informationen zum Verwerfen, die nicht speziell für das Verwerfen von Editoren gelten, finden Sie unter Verwerfen.
Anzeige auf dem Block aktualisieren
Mit der Funktion render_
wird die Blockanzeige des Felds aktualisiert, damit sie mit dem internen Wert übereinstimmt.
Beispiele:
- Text ändern (Dropdown-Menü)
- Farbe ändern (color)
Standardeinstellungen
Die Standardfunktion render_
legt den Anzeigetext auf das Ergebnis der Funktion getDisplayText_
fest. Die Funktion getDisplayText_
gibt die value_
-Eigenschaft des Felds als String zurück, nachdem sie entsprechend der maximalen Textlänge gekürzt wurde.
Wenn Sie die Standardanzeige im Block verwenden und das Standardtextverhalten für Ihr Feld geeignet ist, müssen Sie render_
nicht überschreiben.
Wenn das Standardverhalten für Text für Ihr Feld funktioniert, die Blockanzeige des Felds jedoch zusätzliche statische Elemente enthält, können Sie die Standardfunktion render_
aufrufen. Sie müssen sie jedoch weiterhin überschreiben, um die Größe des Felds zu aktualisieren.
Wenn das Standardtextverhalten für Ihr Feld nicht funktioniert oder die On-Block-Anzeige Ihres Felds zusätzliche dynamische Elemente enthält, müssen Sie die Funktion render_
anpassen.
Rendering anpassen
Wenn das Standard-Renderingverhalten für Ihr Feld nicht funktioniert, müssen Sie ein benutzerdefiniertes Renderingverhalten definieren. Das kann alles umfassen, von der Festlegung von benutzerdefiniertem Anzeigetext über das Ändern von Bildelementen bis hin zum Aktualisieren von Hintergrundfarben.
Alle Änderungen an DOM-Attributen sind zulässig. Sie müssen nur Folgendes beachten:
- Die Erstellung des DOM sollte während der Initialisierung erfolgen, da dies effizienter ist.
- Sie sollten die Eigenschaft
size_
immer an die Größe des On-Block-Displays anpassen.
render_() {
switch(this.value_.hat) {
case 'Stovepipe':
this.stovepipe_.style.display = '';
break;
case 'Crown':
this.crown_.style.display = '';
break;
case 'Mask':
this.mask_.style.display = '';
break;
case 'Propeller':
this.propeller_.style.display = '';
break;
case 'Fedora':
this.fedora_.style.display = '';
break;
}
switch(this.value_.pattern) {
case 'Dots':
this.shellPattern_.setAttribute('fill', 'url(#polkadots)');
break;
case 'Stripes':
this.shellPattern_.setAttribute('fill', 'url(#stripes)');
break;
case 'Hexagons':
this.shellPattern_.setAttribute('fill', 'url(#hexagons)');
break;
}
this.textContent_.nodeValue = this.value_.turtleName;
this.updateSize_();
}
Größe des Updates
Das Aktualisieren der size_
-Eigenschaft eines Felds ist sehr wichtig, da der Code zum Rendern des Blocks dadurch erfährt, wie das Feld positioniert werden soll. Am besten finden Sie heraus, was genau size_
sein sollte, indem Sie es ausprobieren.
updateSize_() {
const bbox = this.movableGroup_.getBBox();
let width = bbox.width;
let height = bbox.height;
if (this.borderRect_) {
width += this.constants_.FIELD_BORDER_RECT_X_PADDING * 2;
height += this.constants_.FIELD_BORDER_RECT_X_PADDING * 2;
this.borderRect_.setAttribute('width', width);
this.borderRect_.setAttribute('height', height);
}
// Note how both the width and the height can be dynamic.
this.size_.width = width;
this.size_.height = height;
}
Passende Blockfarben
Wenn die Elemente Ihres Felds mit den Farben des Blocks übereinstimmen sollen, an den sie angehängt sind, sollten Sie die Methode applyColour
überschreiben. Sie müssen über das style-Attribut des Blocks auf die Farbe zugreifen.
applyColour() {
const sourceBlock = this.sourceBlock_;
if (sourceBlock.isShadow()) {
this.arrow_.style.fill = sourceBlock.style.colourSecondary;
} else {
this.arrow_.style.fill = sourceBlock.style.colourPrimary;
}
}
Bearbeitbarkeit wird aktualisiert
Mit der Funktion updateEditable
können Sie ändern, wie Ihr Feld angezeigt wird, je nachdem, ob es bearbeitet werden kann oder nicht. Mit der Standardfunktion wird festgelegt, ob der Hintergrund eine Hover-Reaktion (Rahmen) hat, wenn er bearbeitbar ist.
Die Größe der Blockanzeige darf sich nicht je nach Bearbeitbarkeit ändern, alle anderen Änderungen sind jedoch zulässig.
updateEditable() {
if (!this.fieldGroup_) {
// Not initialized yet.
return;
}
super.updateEditable();
const group = this.getClickTarget_();
if (!this.isCurrentlyEditable()) {
group.style.cursor = 'not-allowed';
} else {
group.style.cursor = this.CURSOR;
}
}
Serialisierung
Bei der Serialisierung wird der Status des Felds gespeichert, damit er später wieder in den Arbeitsbereich geladen werden kann.
Der Status Ihres Arbeitsbereichs enthält immer den Wert des Felds, kann aber auch andere Statusinformationen enthalten, z. B. den Status der Benutzeroberfläche des Felds. Wenn Ihr Feld beispielsweise eine zoomfähige Karte war, auf der der Nutzer Länder auswählen konnte, könnten Sie auch die Zoomstufe serialisieren.
Wenn Ihr Feld serialisierbar ist, müssen Sie die Property SERIALIZABLE
auf true
setzen.
Blockly bietet zwei Sätze von Serialisierungshooks für Felder. Ein Hakenpaar funktioniert mit dem neuen JSON-Serialisierungssystem und das andere mit dem alten XML-Serialisierungssystem.
saveState
und loadState
saveState
und loadState
sind Serialisierungshooks, die mit dem neuen JSON-Serialisierungssystem funktionieren.
In einigen Fällen müssen Sie diese nicht angeben, da die Standardimplementierungen funktionieren. Wenn (1) Ihr Feld eine direkte Unterklasse der Basisklasse Blockly.Field
ist, (2) Ihr Wert ein JSON-serialisierbarer Typ ist und (3) Sie nur den Wert serialisieren müssen, funktioniert die Standardimplementierung einwandfrei.
Andernfalls sollte Ihre saveState
-Funktion ein JSON-serialisierbares Objekt/einen JSON-serialisierbaren Wert zurückgeben, das/der den Status des Felds darstellt. Ihre loadState
-Funktion sollte dasselbe JSON-serialisierbare Objekt/denselben JSON-serialisierbaren Wert akzeptieren und auf das Feld anwenden.
saveState() {
return {
'country': this.getValue(), // Value state
'zoom': this.getZoomLevel(), // UI state
};
}
loadState(state) {
this.setValue(state['country']);
this.setZoomLevel(state['zoom']);
}
Vollständige Serialisierung und Sicherungsdaten
saveState
erhält auch einen optionalen Parameter doFullSerialization
. Dies wird von Feldern verwendet, die normalerweise auf den Zustand verweisen, der von einem anderen Serializer (z. B. Sicherungsdatenmodelle) serialisiert wird. Der Parameter signalisiert, dass der referenzierte Status beim Deserialisieren des Blocks nicht verfügbar ist. Das Feld sollte also die gesamte Serialisierung selbst vornehmen. Das ist beispielsweise der Fall, wenn ein einzelner Block serialisiert oder ein Block kopiert und eingefügt wird.
Zwei häufige Anwendungsfälle dafür sind:
- Wenn ein einzelner Block in einen Arbeitsbereich geladen wird, in dem das zugrunde liegende Datenmodell nicht vorhanden ist, enthält das Feld genügend Informationen in seinem eigenen Status, um ein neues Datenmodell zu erstellen.
- Wenn ein Block kopiert und eingefügt wird, wird für das Feld immer ein neues zugrunde liegendes Datenmodell erstellt, anstatt auf ein vorhandenes zu verweisen.
Ein Feld, in dem diese Funktion verwendet wird, ist das integrierte Feld für Variablen. Normalerweise wird die ID der Variablen serialisiert, auf die verwiesen wird. Wenn doFullSerialization
„true“ ist, wird der gesamte Status serialisiert.
saveState(doFullSerialization) {
const state = {'id': this.variable_.getId()};
if (doFullSerialization) {
state['name'] = this.variable_.name;
state['type'] = this.variable_.type;
}
return state;
}
loadState(state) {
const variable = Blockly.Variables.getOrCreateVariablePackage(
this.getSourceBlock().workspace,
state['id'],
state['name'], // May not exist.
state['type']); // May not exist.
this.setValue(variable.getId());
}
Das Variablenfeld sorgt dafür, dass eine neue Variable erstellt werden kann, auf die verwiesen werden kann, wenn das Feld in einen Arbeitsbereich geladen wird, in dem die zugehörige Variable nicht vorhanden ist.
toXml
und fromXml
toXml
und fromXml
sind Serialisierungshooks, die mit dem alten XML-Serialisierungssystem funktionieren. Verwenden Sie diese Hooks nur, wenn es unbedingt erforderlich ist, z. B. wenn Sie an einer alten Codebasis arbeiten, die noch nicht migriert wurde. Andernfalls verwenden Sie saveState
und loadState
.
Ihre toXml
-Funktion sollte einen XML-Knoten zurückgeben, der den Status des Felds darstellt. Ihre fromXml
-Funktion sollte denselben XML-Knoten akzeptieren und auf das Feld anwenden.
toXml(fieldElement) {
fieldElement.textContent = this.getValue();
fieldElement.setAttribute('zoom', this.getZoomLevel());
return fieldElement;
}
fromXml(fieldElement) {
this.setValue(fieldElement.textContent);
this.setZoomLevel(fieldElement.getAttribute('zoom'));
}
Bearbeitbare und serialisierbare Eigenschaften
Mit der Property EDITABLE
wird festgelegt, ob das Feld eine Benutzeroberfläche haben soll, die angibt, dass es interaktiv ist. Der Standardwert ist true
.
Die Property SERIALIZABLE
bestimmt, ob das Feld serialisiert werden soll. Der Standardwert ist false
. Wenn diese Property true
ist, müssen Sie möglicherweise Serialisierungs- und Deserialisierungsfunktionen bereitstellen (siehe Serialisierung).
Mit CSS anpassen
Sie können das Feld mit CSS anpassen. Fügen Sie in der Methode initView
eine benutzerdefinierte Klasse zum fieldGroup_
des Felds hinzu und verweisen Sie dann in Ihrem CSS auf diese Klasse.
So verwenden Sie beispielsweise einen anderen Cursor:
initView() {
...
// Add a custom CSS class.
if (this.fieldGroup_) {
Blockly.utils.dom.addClass(this.fieldGroup_, 'myCustomField');
}
}
.myCustomField {
cursor: cell;
}
Cursor anpassen
Standardmäßig wird für Klassen, die FieldInput
erweitern, ein text
-Cursor verwendet, wenn ein Nutzer den Mauszeiger über das Feld bewegt. Für Felder, die gezogen werden, wird ein grabbing
-Cursor verwendet und für alle anderen Felder ein default
-Cursor. Wenn Sie einen anderen Cursor verwenden möchten, legen Sie ihn mit CSS fest.