Search the FirstSpirit Knowledge Base
Hallo Zusammen,
Ich möchte per Script ein schon befülltes FS_REFERENCE-Formularfeld in den globalen Inhalten durch eine per UID ermitteltes Pageref neu befüllen.
So schaut das Formularfeld aus:
<FS_REFERENCE name="ps_speciallink" hFill="yes" imagePreview="no" sections="no" useLanguages="no">
<FILTER>
<ALLOW type="pageref"/>
<HIDE type="documentgroup"/>
</FILTER>
<LANGINFOS>
<LANGINFO lang="DE" label="Verweis" description="."/>
<LANGINFO lang="*" label="Link" description=""/>
</LANGINFOS>
<PROJECTS>
<LOCAL name=".">
<SOURCES>
<FOLDER name="root" store="sitestore"/>
</SOURCES>
</LOCAL>
</PROJECTS>
</FS_REFERENCE>
Auf den entsprechenden Formularbereich in der globalen Seite kann ich zugreifen:
StoreElementAgent storeElementAgent = context.requestSpecialist(StoreElementAgent.TYPE);
GCAPage gcanewpagests = (GCAPage) storeElementAgent.loadStoreElement(gcaPageSTSuid, GCAPage.UID_TYPE, false);
if (gcanewpagests instanceof GCAPage) {
// ### Formdata der GCAPAge holen
FormData formdatagcanewpage = gcanewpagests.getFormData();
try {
gcanewpagests.setLock(true);
try {
formElement = formdatagcanewpage.get(null, "ps_speciallink“);
// ###############
/*
Hier sind mir die Schritte zum Befüllen des FS_REFERENCE-Formularfeldes nicht klar.
Ich habe eine PageRef schon mir über ein Script geholt und will diese jetzt dem schon belegten
FS_REFERENCE-Formularfeldes zuweisen.
formElement.getClass() liefert mir folgendes: class de.espirit.firstspirit.store.access.DataWrappingFormData$EditorValueWrappingFormField
Wie geht es hier weiter?
ReferenceEditorValue? , TargetReference?
*/
// ###############
gcanewpagests.setFormData(formdatagcanewpage);
gcanewpagests.save();
}
catch (Exception e) {
// catch handling
} finally {
gcanewpagests.setLock(false);
}
} catch (LockException e) {
// catch handling
}
}
Könnt ihr mir hier weiterhelfen?
Viele Grüße v.
Ralf
Hallo Michael,
danke für deine ausführliche Erklärung.
Jetzt ist es mir klar. Perfekt.
Hier dann also die Lösung, für alle die es interessiert, die funktioniert:
StoreElementAgent storeElementAgent = context.requestSpecialist(StoreElementAgent.TYPE);
GCAPage gcanewpagests = (GCAPage) storeElementAgent.loadStoreElement(gcaPageSTSuid, GCAPage.UID_TYPE, false);
if (gcanewpagests instanceof GCAPage) {
// ### Formdata der GCAPAge holen
FormData formdatagcanewpage = gcanewpagests.getFormData();
try {
gcanewpagests.setLock(true);
try {
TargetReference targetReferenceNew = TargetReferences.newInstance(null, pageRefTmp, "");
formdatagcanewpage.get(null, "ps_speciallink").set(targetReferenceNew);
gcanewpagests.setFormData(formdatagcanewpage);
gcanewpagests.save();
}
catch (Exception e) {
// catch handling
} finally {
gcanewpagests.setLock(false);
}
} catch (LockException e) {
// catch handling
}
}
Hallo Ralf,
ist hier die entsprechende Doku nicht ausreichend?
https://docs.e-spirit.com/odfs/access/de/espirit/firstspirit/access/editor/ReferenceEditorValue.html
Wenn etwas fehlt oder unverständlich ist, sag bitte kurz Bescheid, wie wir die Doku dort verbessern können 🙂
Viele Grüße
Holger
Hallo Holger,
danke für deine schnelle Antwort.
Mir ist leider nicht klar wie ich das Objekt vom Typ 'de.espirit.firstspirit.store.access.DataWrappingFormData$EditorValueWrappingFormField' siehe oben weiter behandle um daraus mit der Klasse / Objekt .ReferenceEditorValue weiterarbeiten zu können.
ReferenceEditorValue refSearch = formdatagcanewpage.get(null, "ps_searchresult_link");
erzeugt folgenden Fehler:
java.lang.ClassCastException: Cannot cast de.espirit.firstspirit.store.access.DataWrappingFormData$EditorValueWrappingFormField to de.espirit.firstspirit.access.editor.ReferenceEditorValue
Wäre klasse, wenn mir da jemand einen Tip geben könnte.
Hallo Ralf,
habs gerade mal ausprobiert. Für mich klappt es (in einer Beanshell Konsole) so:
import de.espirit.firstspirit.agency.StoreElementAgent;
import de.espirit.firstspirit.access.store.mediastore.Media;
import de.espirit.firstspirit.access.editor.value.TargetReference;
import de.espirit.firstspirit.access.editor.value.TargetReference.TargetReferences;
storeElementAgent = context.requestSpecialist(StoreElementAgent.TYPE);
myMedia = storeElementAgent.loadStoreElement(<mediaUid>,Media.UID_TYPE,false);
targetReference = TargetReferences.newInstance(null, myMedia, "");
<section>.page.setLock(true,true);
fd = <section>.getFormData();
ff = fd.get(null,<FS_REFERENCE name>);
ff.set(targetReference);
<section>.setFormData(fd);
<section>.page.save(true);
<section>.page.setLock(false,true);
ich gehe hierbei von einem Absatz (<section>) aus. Ich versuche dabei, in die FS_REFERENCE Eingabekomponente mit dem name <FS_REFERENCE name> das Medium mit der UID <mediaUID> zu setzen. Die Eingabekomponente ist sprachunabhängig, sonst müsste ich mit aus dem formData die sprachabhängige Variante holen, statt dort einfach "null" zu verwenden.
Und ja, das Beispiel ist unbrauchbar 😞
Sorry, das hatte ich mir vor dem Antworten nicht angesehen.
Ich hoffe, dass das Beispiel weiterhilft.
Viele Grüße
Holger
Hallo Holger,
danke für deine Antwort.
Mit der ging es deutlich besser.
Ich habe zwar keine Medien sondern Referenzen auf PageRefs, aber ich denke das Verhalten ist ähnlich.
Ich habe jetzt eine Lösung gefunden, die zumindest die Reference wie gewünscht tauscht.
Ich gehe über TargetReference.
StoreElementAgent storeElementAgent = context.requestSpecialist(StoreElementAgent.TYPE);
GCAPage gcanewpagests = (GCAPage) storeElementAgent.loadStoreElement(gcaPageSTSuid, GCAPage.UID_TYPE, false);
if (gcanewpagests instanceof GCAPage) {
// ### Formdata der GCAPAge holen
FormData formdatagcanewpage = gcanewpagests.getFormData();
try {
gcanewpagests.setLock(true);
try {
TargetReference targetReferenceTmp = (TargetReference) formdatagcanewpage.get(null, "ps_speciallink").get();
targetReferenceTmp.set(pageRefVariable);
gcanewpagests.setFormData(formdatagcanewpage);
gcanewpagests.save();
}
catch (Exception e) {
// catch handling
} finally {
gcanewpagests.setLock(false);
}
} catch (LockException e) {
// catch handling
}
}
Hoffe diese Lösung geht auch?!
Viele Grüße v.
Ralf
Hallo Ralf,
im Unterschied zu Holgers Vorschlag „manipulierst“ du die vorhandene TargetReference anstatt eine neue Instanz zu erzeugen. Ich meine mich daran zu erinnern, dass das so nicht immer funktioniert, weiß aber nicht mehr was da der Hintergrund oder das konkrete Problem war…
Von daher würde ich „aus dem Bauch heraus“ eher die Nutzung von TargetReferences.newInstance(…) empfehlen. So groß ist der Unterschied ja nicht.
Viele Grüße
Michael
Hallo Michael,
danke für deinen Tip.
Dann bau ich es mal um.
Viele Grüße v.
Ralf
Hallo Michael,
also irgendwie stehe ich auf dem Schlauch.
Jetzt bin ich wieder bei der selben Problematik vom Anfang.
Wenn ich über den von dir vorgeschlagenen Weg gehe müsste ich ja folgendes machen:
StoreElementAgent storeElementAgent = context.requestSpecialist(StoreElementAgent.TYPE);
GCAPage gcanewpagests = (GCAPage) storeElementAgent.loadStoreElement(gcaPageSTSuid, GCAPage.UID_TYPE, false);
if (gcanewpagests instanceof GCAPage) {
// ### Formdata der GCAPAge holen
FormData formdatagcanewpage = gcanewpagests.getFormData();
try {
gcanewpagests.setLock(true);
try {
TargetReference targetReferenceNew = TargetReferences.newInstance(null, pageRefTmp, "");
// ### Diese müsste ich ja dann einer Klasse vom Typ ReferenceEditorValue mit set zuweisen? Oder? An die komme ich aber nicht ran. Abgesehen, dass die Methode set() auf die Klasse EditorValue deprecated ist, ist mir nicht klar wie ich aus dem Aufruf formdatagcanewpage.get(null, "ps_speciallink") eine Klasse erhalte die korrekt per set und einer neuen Istance von TargetReference gefüllt werden kann.
?? = formdatagcanewpage.get(null, "ps_speciallink");
// Liefert die Klasse : de.espirit.firstspirit.store.access.DataWrappingFormData$EditorValueWrappingFormField
??.set(targetReferenceNew);
gcanewpagests.setFormData(formdatagcanewpage);
gcanewpagests.save();
}
catch (Exception e) {
// catch handling
} finally {
gcanewpagests.setLock(false);
}
} catch (LockException e) {
// catch handling
}
}
Das klappt auch in Beanshell bei der Ausführung.
In meinem Java-Editor allerdings kann er die Zuweisung nicht machen. Da sagt er die Klassen passen nicht zusammen und wenn ich davon ausgehe, dass Beanshell über die Klasse EditorValue geht verwende ich ja eine deprecated Funktion mit set() auf ReferenceEditorValue? Oder bezieht sich das 'Set()' hier auf eine andere Klasse?
Hallo Ralf,
du kannst die TargetReference direkt in das Formfield.set(...) werfen.
Also
formdatagcanewpage.get(null, "ps_speciallink“).set(targetReferenceNew);
Relevant ist hier nicht das ReferenceEditorValue (das ist quasi nur die "Kapsel" bzw. ein Tagging interface). Das (komplette) Beispiel in der Doku beruht hier tatsächlich auch noch auf dem "alten" Weg, über die "Editoren" zu gehen. Ich glaube aber, es ging Holger hier lediglich um den Weg (bzw. die eine Zeile), wie man sich eine TargetReference-Instanz erzeugt.
Allgemein (kleiner Exkurs zum Thema "Datentypen bei Eingabekomponenten")
Man kann in ein FormField (genau das bekommst du ja, wenn du xyz.getFormData().get(lang, name) aufrufst) immer mit .set(...) den Typ rein werfen, der im ODFS bei der entsprechenden Eingabekomponente (hier: FS_REFERENCE) oben in der grauen Box bei "zu den Methoden" steht.
Das ist sozusagen der "Eingebekomponenten-Inhalts-Datentyp". In einigen Fällen müssen dann auch noch weitere Voraussetzungen erfüllt sein (der Inhalt der Daten muss insbesondere "zur Konfiguration der Eingabekomponente passen" - man kann also z.B. in eine INPUT_COMBOBOX, die auf Datensätzen basiert keine Option werfen, die auf festen Werten basiert.
Es gibt dann noch einige "Spezialfälle", wo man sogar noch andere Typen benutzen kann, die dann automatisch passend "umgewandelt" werden. Zwar nicht im Fall einer FS_REFERENCE, aber z.B. bei den sog. "Option-basierten" EKs (INPUT_COMBOBOX, INPUT_LIST, INPUT_CHECKBOX, INPUT_RADIOBUTTON). Dort muss man nicht zwingend eine Option benutzen (auch weil es da keinen "schönen" Weg gibt, die zu erzeugen), sondern kann den Typ nutzen, auf dem wiederum die "Option" basieren würde. Das hängt dann vom benutzten INCLUDE_TYPE ab. Ist der z.B. "database", darf man auch ein Dataset oder eine Entity benutzen (bzw. bei den mehrwertigen dann ein Set<Dataset> oder Set<Entity>).
Das ist übrigens auch der Grund, warum in der API zum FormField-Interface (das eben genau mit dem "Inhalts-Datentyp" (T) typisiert ist), zwar beim .get() ein T zurück geliefert wird (in deinem Fall eine TargetReference), die .set(...)-Methode aber nicht auf einem T "besteht" sondern ein Object bekommen kann.
Ich hoffe, das macht es etwas klarer.
Viele Grüße
Michael
Hallo Michael,
danke für deine ausführliche Erklärung.
Jetzt ist es mir klar. Perfekt.
Hier dann also die Lösung, für alle die es interessiert, die funktioniert:
StoreElementAgent storeElementAgent = context.requestSpecialist(StoreElementAgent.TYPE);
GCAPage gcanewpagests = (GCAPage) storeElementAgent.loadStoreElement(gcaPageSTSuid, GCAPage.UID_TYPE, false);
if (gcanewpagests instanceof GCAPage) {
// ### Formdata der GCAPAge holen
FormData formdatagcanewpage = gcanewpagests.getFormData();
try {
gcanewpagests.setLock(true);
try {
TargetReference targetReferenceNew = TargetReferences.newInstance(null, pageRefTmp, "");
formdatagcanewpage.get(null, "ps_speciallink").set(targetReferenceNew);
gcanewpagests.setFormData(formdatagcanewpage);
gcanewpagests.save();
}
catch (Exception e) {
// catch handling
} finally {
gcanewpagests.setLock(false);
}
} catch (LockException e) {
// catch handling
}
}