Teile eines Formulars wiederverwenden

Das Forum soll der Ablage von Lösungen für immer wieder auftauchende Problemstellungen dienen. // This forum contains solutions to problems that frequently occur.
Well
Beiträge: 263
Registriert: 25.10.2009, 11:00:19
Wohnort: Beuren
Kontaktdaten:

Teile eines Formulars wiederverwenden

Beitrag von Well » 24.03.2010, 15:53:27

moin,

mit core:appendnode kann ich ja z.B.: ein Formular wiederverwenden. Aber wie kann ich einen Teil eines Formulars auslagern ? Ich würde gerne ein - mehr oder weniger - komfortables Eingabefeld für Texte verwenden, dass ich in mehreren Seiten in verschiedenen Formularen benötige. Wie kann ich das lösen ? In jedes Formular das Textfeld inkl. allen Buttons zur Textbearbeitung zu definieren scheint mir etwas "unhandlich"?!

Benutzeravatar
dr.e.
Administrator
Beiträge: 4525
Registriert: 04.11.2007, 16:13:53

Re: Teile eines Formulars wiederverwenden

Beitrag von dr.e. » 24.03.2010, 16:58:05

Hallo Well,

du kannst im Prinzip den gleichen Mechanismus wiederverwenden. Da es sich hier allerdings um Objekte handelt, die eine bestimmte Umgebung (=Formular) brauchen, ist die Implementierung etwas aufwendiger. Da es noch nichts fertiges gibt (frag mal Screeze, er hat das glaube ich auch schon mal gemacht?), skizziere ich dir mal die Vorgehensweise:

  • Zunächst muss eine Taglib erstellt werden, die im Formular-Kontext eingesetzt werden kann. Diese hat dann gemäß der Namens-Konvention den Klassen-Namen form_taglib_appendnode.
  • Die Taglib muss die einzubindenen Elemente "kennen", sonst können sie nicht initialisiert werden. Daher müssen diese im Konstruktur bekannt gemacht werden.
  • In der onParseTime() müssen die Elemente analysiert und das DOM aufgebaut werden. Das kann durch Aufruf der __extractTagLibTags() passieren.
  • In der onAfterAppend() kannst du dann die Elemente in das Vater-Objekt umhängen. Wie das geht, siehst du in der Klasse core_taglib_appendnode.
Wichtig dabei ist jedoch zu beachten, dass es dann nicht mehr möglich ist, Validatoren auf die Felder zu hängen, da diese zur Zeit der Ausführung der onAfterAppend() noch nicht im DOM vorhanden sind.

Wie komplex sind denn die Felder? Vielleicht macht es sogar Sinn, den oben beschriebenen Aufwand nicht zu treiben und statt dessen, die Felder in einem einzigen Control zu abstrahieren. Dies ist dann eine ähnliche Vorgehensweise wie auch beim Date-Control. Dies vereinigt 3 Select-Controls.
Viele Grüße,
Christian

Benutzeravatar
Screeze
Beiträge: 1920
Registriert: 05.08.2009, 09:49:04
Kontaktdaten:

Re: Teile eines Formulars wiederverwenden

Beitrag von Screeze » 24.03.2010, 17:29:45

Hi,
(frag mal Screeze, er hat das glaube ich auch schon mal gemacht?)


Nicht wirklich ;)

Im Gegenteil, mich würde die Umsetzung einer komponente, welche Formularteile auslagern kann selber interessieren, da ich seit ein paar Tagen mit dem Gedanken spiele, Teile von sehr großen, stark frequentierten Formularen zu cachen. Allerdings bräuchte ich eine möglichkeit auch validatoren etc. dabei zu verwenden (wobei die auch jeweils im selben cache-teil liegen können wie das entsprechende feld). Die Idee mit der ich seit paar Tagen gedanklich spiele beinhaltet einen RAM/filecache, welcher zum einen das fertige html, und zum anderen die entsprechenden,fertig generierten, formular-Kindobjekte , die nurnoch ins elternelement eingehängt werden sollten, enthält. Aber ob das umsetzbar ist weis ich noch nicht... (v.a. bräuchte ich dann noch eine möglichkeit vom formular bestimmte attribute auf serverseite zu editieren, welche zwar nicht im html, aber bei den validatoren benötigt werden)

Also wenns da auslagerungsmöglichkeiten gibt, sollte auch mein cache machbar und ähnlich umsetzbar sein ;)

Benutzeravatar
dr.e.
Administrator
Beiträge: 4525
Registriert: 04.11.2007, 16:13:53

Re: Teile eines Formulars wiederverwenden

Beitrag von dr.e. » 24.03.2010, 20:08:14

Hallo Ralf,

die kompletten Formulare oder auch Teile zu cachen funktioniert IMHO nicht, denn du hast dann keine Möglichkeit die Server-seitigen Validatoren auszuführen. Man könnte vielleicht die Methode transformForm() überschreiben, das würde aber nur die Transformation cachen und du hättest den Nachteil, dass das Formular - einmal befüllt - immer die gleichen Werte enthält. Sofern die Formular-Validatoren oder allgemein das Formular-Handling zu einem Performance-Problem werden, sollte man die Architektur überdenken.

Welcher konkrete Anwendungsfall steckt bei dir dahinter? Vielleicht ist view based caching für alle anderen Bereiche sinnvoll?!

@Well: je mehr ich drüber nachdenke, macht die zweite Option - sprich Implementieren eines generischen Controls - immer mehr Sinn. Kannst du ein bischen näher beschreiben, welche Funktionen dort inkludiert sein sollen.
Viele Grüße,
Christian

Well
Beiträge: 263
Registriert: 25.10.2009, 11:00:19
Wohnort: Beuren
Kontaktdaten:

Re: Teile eines Formulars wiederverwenden

Beitrag von Well » 24.03.2010, 20:58:41

Wie komplex sind denn die Felder? Vielleicht macht es sogar Sinn, den oben beschriebenen Aufwand nicht zu treiben und statt dessen, die Felder in einem einzigen Control zu abstrahieren. Dies ist dann eine ähnliche Vorgehensweise wie auch beim Date-Control. Dies vereinigt 3 Select-Controls.

Ich soll bei dieser Option also den "HTML-Teil" in einem Controller definieren und dann in das Template einsetzen? Wenn ich das richtig aufgenommen habe - wäre das nicht irgendwie "unschön"?

dr.e. hat geschrieben:@Well: je mehr ich drüber nachdenke, macht die zweite Option - sprich Implementieren eines generischen Controls - immer mehr Sinn. Kannst du ein bischen näher beschreiben, welche Funktionen dort inkludiert sein sollen.

Ich denke ich verstehe dich jetzt nur falsch - Mir geht es nicht um die Auswertung von diesem Teil des Formulars sondern leidiglich darum, dass ich die Eingabemaske + sämtliche Buttons die zur Textbearbeitung dabei sind nicht an mehreren Stellen implentieren muss.

Benutzeravatar
Screeze
Beiträge: 1920
Registriert: 05.08.2009, 09:49:04
Kontaktdaten:

Re: Teile eines Formulars wiederverwenden

Beitrag von Screeze » 24.03.2010, 21:37:55

Hallo Ralf,

die kompletten Formulare oder auch Teile zu cachen funktioniert IMHO nicht, denn du hast dann keine Möglichkeit die Server-seitigen Validatoren auszuführen. Man könnte vielleicht die Methode transformForm() überschreiben, das würde aber nur die Transformation cachen und du hättest den Nachteil, dass das Formular - einmal befüllt - immer die gleichen Werte enthält. Sofern die Formular-Validatoren oder allgemein das Formular-Handling zu einem Performance-Problem werden, sollte man die Architektur überdenken.

Welcher konkrete Anwendungsfall steckt bei dir dahinter? Vielleicht ist view based caching für alle anderen Bereiche sinnvoll?!


Sowas hab ich schon befürchtet, war auch nur ein Gedankenspiel ;)
In anderen Bereichen wird caching verwendet.

Ich denke ich verstehe dich jetzt nur falsch - Mir geht es nicht um die Auswertung von diesem Teil des Formulars sondern leidiglich darum, dass ich die Eingabemaske + sämtliche Buttons die zur Textbearbeitung dabei sind nicht an mehreren Stellen implentieren muss.

Well, ich glaube was Christian meint ist folgendes:
(ich gehe mal davon aus du redest von einer art rich-text-/BB-code-editor)
Statt alle buttons etc. im formular einzufügen, erstellst du dir eine <form:richtext />-taglib, welche du dann in die formulare einbindest.
In diesem Taglib machst du die benötigten Felder etc. bekannt, und verlagerst die generierung in diese taglib.
(wobei ich in einem fall von einer art RT-editor vermutlich die meisten elemente statisch als html in diesen speziellen tag schreiben würde, und nurnoch z.b. den feldname und class-angaben an passender stelle einfüge, aber das kommt auf die anwendung an)

Well
Beiträge: 263
Registriert: 25.10.2009, 11:00:19
Wohnort: Beuren
Kontaktdaten:

Re: Teile eines Formulars wiederverwenden

Beitrag von Well » 24.03.2010, 23:38:18

Well, ich glaube was Christian meint ist folgendes:
(ich gehe mal davon aus du redest von einer art rich-text-/BB-code-editor)
Statt alle buttons etc. im formular einzufügen, erstellst du dir eine <form:richtext />-taglib, welche du dann in die formulare einbindest.
In diesem Taglib machst du die benötigten Felder etc. bekannt, und verlagerst die generierung in diese taglib.
(wobei ich in einem fall von einer art RT-editor vermutlich die meisten elemente statisch als html in diesen speziellen tag schreiben würde, und nurnoch z.b. den feldname und class-angaben an passender stelle einfüge, aber das kommt auf die anwendung an)

Okay, so macht das schon mehr Sinn.

Ich erstelle also ein neues TagLib alâ ->
<form:richtext name="..." /> -> TextArea
<form:richtext_colors control="..." /> -> Alle Buttons zur Farbauswahl
<form:richtext_smilies control="..." /> -> Alle Smilies
usw.

-> ?

Auf diesem Weg sind die Buttons dann aber was die Positionierung betrifft noch immer recht gebunden - Gäbe es dort keine flexiblere Möglichkeit? (Obwohl, ich denke, das ist zu verkraften)

Benutzeravatar
dr.e.
Administrator
Beiträge: 4525
Registriert: 04.11.2007, 16:13:53

Re: Teile eines Formulars wiederverwenden

Beitrag von dr.e. » 24.03.2010, 23:43:52

Hallo ihr beiden,

Ralf hat es schon erkannt, ich will keine HTML-Definitionen in Controllern erzeugen, sondern eine "komplexe" Taglib auf Basis von bestehenden aufbauen. Ich mach mal ein Beispiel, dann wir es klar:

Ein Formular für die Eingabe von Geo-Koordinaten besitzt u.a. 2 Felder für die Eingabe der Breiten- und Längen-Grade. Dieses Element soll in mehreren Formularen (Eingabe Restaurants, Eingabe Tankstellen, ...) verwendet werden. Für die beiden Felder gibt es eine definierte Validierung, die auf die beiden Felder gelegt wird. Das Ganze sieht in etwa so in Rohform aus:

Code: Alles auswählen

<html:form name="restaurants">
   <form:text name="latitude" />
   <form:text name="longitude" />
   <form:addvalidator
      namespace="..."
      class="GeoCoordValidator"
      control="latitude|longitude"
      button="send"
   />
   <form:button name="send" value="GO" />
</html:form>

Damit man nun die Elemente nicht immer neu tippen und mit einem Validator belegen muss, kann man diese zusammenzufassen:

Code: Alles auswählen

<html:form name="restaurants">
   <form:addtaglib namespace="..." prefix="form" class="geo" />
   <form:geo name="geo" />
   <form:addvalidator
      namespace="..."
      class="GeoValidator"
      control="geo"
      button="send"
   />
   <form:button name="send" value="GO" />
</html:form>

Dieses Control übernimmt dann die Darstellung der jeweiligen Komponenten und lässt sich über den entsprechenden Validator validieren. Damit lässt sich eine sehr gute Wiederverwendung erreichen. Sollte das Control an einigen Stellen spezielle Verhaltens-Muster haben, kann man das ganz einfach mit einem Tag-Attribut wie z.B.

Code: Alles auswählen

<form:geo name="geo" doit="true"/>

erreichen.

@Well: sollen wir mal ein konkretes Beispiel zusammen implementieren?
Viele Grüße,
Christian

Benutzeravatar
Screeze
Beiträge: 1920
Registriert: 05.08.2009, 09:49:04
Kontaktdaten:

Re: Teile eines Formulars wiederverwenden

Beitrag von Screeze » 24.03.2010, 23:47:09

wieso kapselst du nicht alles in einer taglib, sondern trennst buttons und smilies ab? Hat das einen tieferen sinn?
(@well)

Benutzeravatar
dr.e.
Administrator
Beiträge: 4525
Registriert: 04.11.2007, 16:13:53

Re: Teile eines Formulars wiederverwenden

Beitrag von dr.e. » 24.03.2010, 23:47:32

Hallo Well,

Ich erstelle also ein neues TagLib alâ ->

Das klingt gut! Sofern die aufgezeigten Taglibs zusammen gehören, könnte man sich auch überlegen, diese zusammenzufassen oder diese als "Konfiguration" mitzugeben. Z.B. so:

Code: Alles auswählen

<form:richtext ...>
   <richtext:text ... />
   <richtext:colors ... />
   <richtext:smilies ... />
</form:richtext>


Auf diesem Weg sind die Buttons dann aber was die Positionierung betrifft noch immer recht gebunden - Gäbe es dort keine flexiblere Möglichkeit? (Obwohl, ich denke, das ist zu verkraften)

Die Formatierung selbst solltest du über CSS erledigen. Wenn dein Markup solide gebaut ist, kannst du ganz einfach per CSS-Regel die unterschiedlichen Formulare unterschiedlich formatieren.

EDIT: damn ich war schon wieder langsamer. :D
Viele Grüße,
Christian

Well
Beiträge: 263
Registriert: 25.10.2009, 11:00:19
Wohnort: Beuren
Kontaktdaten:

Re: Teile eines Formulars wiederverwenden

Beitrag von Well » 25.03.2010, 18:10:20

Screeze hat geschrieben:wieso kapselst du nicht alles in einer taglib, sondern trennst buttons und smilies ab? Hat das einen tieferen sinn?
(@well)

hm, wenn ich es recht verstehe wäre ja sonst die anordnung bzw das layout des editors fest vorgegeben ?!

Das klingt gut! Sofern die aufgezeigten Taglibs zusammen gehören, könnte man sich auch überlegen, diese zusammenzufassen oder diese als "Konfiguration" mitzugeben. Z.B. so:

ok, dann versuche ich das nun so umzusetzen

Die Formatierung selbst solltest du über CSS erledigen. Wenn dein Markup solide gebaut ist, kannst du ganz einfach per CSS-Regel die unterschiedlichen Formulare unterschiedlich formatieren.

stimmt natürlich. daran hab ich nun gar nicht gedacht :)

-> dann bedanke ich mich mal soweit, werde mich bei problemen melden :D

Well
Beiträge: 263
Registriert: 25.10.2009, 11:00:19
Wohnort: Beuren
Kontaktdaten:

Re: Teile eines Formulars wiederverwenden

Beitrag von Well » 30.03.2010, 21:29:35

Nachdem ich am Wochenende sowie gestern nicht wirklich viel Zeit hatte, hab ich mich nun weiters damit beschäftigt. Ich habe nun folgende Taglib-Konstruktion:

Code: Alles auswählen

<form:richtext name="...">
  <richtext:area /> // *
  <richtext:preview />
  <richtext:defaults />
  <richtext:smileys />
  <richtext:textcolors />
  ...
</form:richtext>

Die Id der Textarea, die mittels einer Instanz von form_taglib_area in richtext_taglib_area erzeugt wird, setzt sich durch folgendes Schema zusammen: [name des editors]_area.
Nun ist aber mein Problem, dass ich nicht weiß, wie ich im Controller an diese Textarea komme. Wenn ich dort mittels getFormElementByName den Editor hole, also <form:richtext name="..."> hole, müsste ich dadurch ja irgendwie an das "richtext_taglib_area-Objekt" kommen und von da aus dann an die eigentliche Textarea? Aber wie kann ich an das "richtext_taglib_area-Objekt" kommen, wenn ich im XML-Tag weder name noch id angebe? Habe ich mich da nun etwas verplant?

Benutzeravatar
dr.e.
Administrator
Beiträge: 4525
Registriert: 04.11.2007, 16:13:53

Re: Teile eines Formulars wiederverwenden

Beitrag von dr.e. » 30.03.2010, 23:05:57

Hallo Well,

da du einen Zugriff auf "interne" Elemente des Richtext-Elements brauchst, würde ich die API der Taglib so gestalten, dass du die relevanten Informationen auch beziehen kannst. Dazu bietet sich eine Methode

Code: Alles auswählen

richtext_taglib_area form_taglib_richtext::getTextArea()

an. Diese gibt - wie die Signatur schon sagt - die Text-Area zurück. Sofern du nur den Text darin benötigst, kannst du auch etwas in der Art

Code: Alles auswählen

string form_taglib_richtext::getText()

anbieten. In der Taglib intern ist der Zugriff dann wie folgt möglich:

Code: Alles auswählen

public function getTextArea(){
   foreach($this->__Children as $objectId => $DUMMY){
      if(get_class($this->__Children[$objectId]) === 'richtext_taglib_area'){
         return $this->__Children[$objectId];
      }
   }
   return null;
}

Den Text daraus kannst du dann mit

Code: Alles auswählen

getTextArea()->getContent()

(1.12) oder mit

Code: Alles auswählen

getTextArea()->get('Content')

(1.11) beziehen. Im Prinzip kannst du im DOM-Baum genauso navigieren (über jeweils die Kinder und das Vater-Objekt), wie die Tags definiert sind.

Im Controller hast du mit der internen Klassen-Variable $this->__Document auf das DOM-Element. Dieses beinhaltet dann als Kind die Instanz der Taglib <form:richtext />. Ein Beispiel für den Zugriff findest du in der Methoden base_controller::__getTemplate() (1.12) oder baseController::__getTemplate() (1.11) in der pagecontroller.php. Prinzip ist auch hier: Kinder des DOM-Knotens ausgeben lassen, darüber iterieren und das "richtige" Objekt raussuchen.

Ich denke, damit kommst du weiter. Falls nicht, mache ich dir noch ein Beispiel.
Viele Grüße,
Christian

Well
Beiträge: 263
Registriert: 25.10.2009, 11:00:19
Wohnort: Beuren
Kontaktdaten:

Re: Teile eines Formulars wiederverwenden

Beitrag von Well » 31.03.2010, 14:32:11

Okay, dankeschön - das geht dann soweit. Nun mein hoffentlich letztes Problem: Wie komme ich an den Inhalt der Textarea? Wenn ich mir alle Attribute des Elements ausgeben lasse, bekomme ich nur style und id ausgegeben. Ich denke, dass ich da noch einen Fehler in der Implentierung gemacht habe? (Zudem beleibt der Inhalt nach dem Absenden nicht erhalten. :()

Die onParseTime-Methode in der Klasse richtext_taglib_area sieht wie folgt aus:

Code: Alles auswählen

   public function onParseTime() {
      // Name des Editors holen
      $richtextName = $this->__ParentObject->getAttribute('name');
      
      // TextArea erstellen
      $this->__area = new form_taglib_area();
      
      // CSS-Klasse übertragen
      if(isset($this->__Attributes['class'])) {
         $this->__area->setAttribute('class', $this->__Attributes['class']);
      }
      
      // Inline CSS übertragen
      if(isset($this->__Attributes['style'])) {
         $this->__area->setAttribute('style', $this->__Attributes['style']);
      }
      
      // ID setzen
      $this->__area->setAttribute('id', $richtextName.'_area');
      
      // Area parsen
      $this->__area->onParseTime();
      
      // Area als Kind setzen
      $this->__area->setParentObject($this);
      $this->__Children['area'] = $this->__area;

      $this->__area->onAfterAppend();
   }

Benutzeravatar
Screeze
Beiträge: 1920
Registriert: 05.08.2009, 09:49:04
Kontaktdaten:

Re: Teile eines Formulars wiederverwenden

Beitrag von Screeze » 31.03.2010, 14:43:44

Der inhalt ist nicht in einem Attribut zu finden, wie es bei normalen textfeldern der fall ist.
Bei textareas wird der eingegebene text zwischen das open und das end tag geschrieben.
Aus diesem Grund findest du den Inhalt hier, wie Christian bereits sagte:

Den Text daraus kannst du dann mit

Code: Alles auswählen
getTextArea()->getContent()


(1.12) oder mit

Code: Alles auswählen
getTextArea()->get('Content')


(1.11) beziehen. Im Prinzip kannst du im DOM-Baum genauso navigieren (über jeweils die Kinder und das Vater-Objekt), wie die Tags definiert sind.

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast