Zum Inhalt springen

Backend Module schreiben

Erstellt am 8. Januar 2009 · 11 Antworten · letzte Antwort am 4. Dezember 2009

Tags: Frage

nomawie ·

Hallo zusammen,
ich schreibe gerade ein Backend Modul mit dem ich komplexere Datensätze, in meinem Fall Formulare, erstellen kann. Mit Hilfe von Javascript kann ich beliebig viele Textfelder und Text-Inputs hinzufügen. Das klappt alles wunderbar. Nur würde ich jetzt gerne anstatt der html-Elemente textarea und input die Typo Elemente verwenden. Beispielsweise den Rich Text Editor. Hab schon viel gesucht, konnte bisher aber nichts finden. Gibts ausführliche Tutorials für die Erstellung von Backend Modulen. Oder könnt ihr mir ein paar Extensions nennen, die umfangreiche BackendModule beinhalten, insbesondere den RTE?

Viele Grüße

froemken ·

Ich hab mir dieses englische Buch gekauft, dass just2b hier empfolen hat.
Dort steht:
Types:
Special configuration:
This can be used to disable wrap on the text element or to convert a text area into the RTE text field. See the TYPO3 Core API | Special Configuration options section.

Link habe ich Dir rausgesucht:
https://docs.typo3.org/m/typo3/reference-tca/main/en-us/Index.html

Bin leider noch in Kapitel 5. Backend Module werden aber erst in Kapitel 7 erklärt. Kann Dir also nicht weiter helfen, als mit den paar Infos hier.

Stefan

digedag ·

TYPO3 verwendet für das Rendern von Formularelemente im BE die Klasse t3lib_TCEforms. Diese kann dir grundsätzlich auch in deinen eigenen Modulen diese Felder zur Verfügung stellen. Leider ist die Bedienung der Klasse nicht ganz einfach, weil es ne Menge externe Abhängigkeiten gibt. #paralyzed#

So erstellst du eine Instanz:

$form = t3lib_div::makeInstance('t3lib_TCEforms');
$form->initDefaultBEmode();
$form->backPath = $BACK_PATH;

Dann muss etwas JS-Code in den Content:

$content .= $form->printNeededJSFunctions_top();

Jetzt wird es tricky. Der Datensatz, den du darstellen willst, muss aus der DB geladen und richtig vorbereitet werden. Die Vorbereitung ist z.B. für Selectboxen mit MM-Relationen notwendig. Da steht ja im Record selbst nur die Anzahl der Relationen drin. Für die Auswahlbox braucht es aber die aufgelösten Relationen. Aber TYPO3 hat auch dafür was vorbereitet, man muss es nur wissen. 🙂 Am besten verwendest du diese Methode:

function getTCEFormArray($table,$theUid, $isNew = false) {
  $trData = t3lib_div::makeInstance('t3lib_transferData');
  $trData->addRawData = TRUE;
  $trData->fetchRecord($table,$theUid,$isNew?'new':'');	// 'new'
  reset($trData->regTableItems_data);
  return $trData->regTableItems_data;
}

Damit ausgestattet, kannst du so den Record vorbereiten:

$dataArr = $this->getTCEFormArray($table, $uid);

$table ist ein String mit dem Tabellennamen und $uid natürlich die UID des Records.
Und jetzt können wir schon das Feld generieren lassen:

$field = $form->getSoloField($table,$dataArr[$table.'_'.$uid],$fieldname);

Der Key im $dataArr wird also aus Tabellennamen und UID zusammengesetzt. Und bei $fieldname setzt du einfach das gewünscht Feld rein. Die tceForms schaut jetzt automatisch in der TCA nach der Konfiguration für das Feld und liefert den fertigen HTML-Code.

Jetzt sind wir fast fertig. Es fehlt nur noch etwas Javascript:

$content .= $form->printNeededJSFunctions();

Wenn ich nichts vergessen habe, dann sollten sich damit alle Felder, die in der TCA beschrieben sind, rendern lassen. 🙂
Falls JS-Fehler kommen, weil irgendwelche JS-Bibliotheken fehlen, dann sollten diese über die template-Instanz geladen werden:

$this->doc->loadJavascriptLib('contrib/prototype/prototype.js');

Ab TYPO3 4.2 muss man übrigens immer die Template-Instanz aus der globalen Variable $GLOBALS['TBE_TEMPLATE'] verwenden. Wenn man sie selbst anlegt, streikt die t3lib_TCEforms. Dort darf auch folgender Aufruf am Ende des Moduls nicht fehlen:

$content = $this->doc->insertStylesAndJS($content);

Leider macht es einem TYPO3 nicht gerade einfach "systemkonform" im BE zu programmieren. Wer schön, wenn das mal in einem Buch beschrieben würde, ich hab da aber so meine Zweifel. 😉

nomawie ·

Klasse. Vielen vielen Dank für diese sehr ausführliche Antwort. Ich werd mich das Wochenende mal dransetzen und dann Rückmeldung geben 🙂

digedag ·

Also ich hab's grad mal ausprobiert. Es hat funktioniert. Allerdings man höllisch bei der Reihenfolge der Aufrufe aufpassen!

Zuerst müssen die Felder gerendert werden. Das Ergebnis darf aber nicht sofort in den Output-String, weil vorher noch die NeededJSFunctions_top eingebunden werden müssen. Dieser JS-Code wiederum stimmt aber nur, wenn vorher die Felder erzeugt wurden. Die TCEforms muss ja wissen, welche Felder überhaupt angezeigt werden... 8-)

Also der Code muss grob so aussehen:

// Den Record wie beschrieben vorbereiten und dann die Felder erzeugen
$modContent = $form->getSoloField($table,$dataArr[$table.'_'.$uid],$fieldname); 
// Jetzt die JS functions
$content .= $form->printNeededJSFunctions_top();
// Nun die Felder reinsetzen
$content .= $modContent
// Und nun der AbschlussCode für die Feld-Validierung
$content .= $form->printNeededJSFunctions();

Bin mal gespannt, ob es bei dir klappt! 🙂

nomawie ·

Hat leider etwas länger gedauert da ich lange in der Core Documentation gelesen habe. Bisher hab ich nur aus einem Buch gelernt, aber das geht nicht soweit ins Detail. Bin bisher leider auch nicht erfolgreich gewesen. Folgendes hab ich gemacht: Mit dem Kickstarter ein Backendmodul angelegt und dann direkt in der index.php unter function 2 testweise folgenden Code eingetragen:

$form = t3lib_div::makeInstance('t3lib_TCEforms');
$form->initDefaultBEmode();
$form->backPath = $BACK_PATH;
							
$dataArr = $this->getTCEFormArray('tx_designer_form', '1');
$field = $form->getSoloField('tx_designer_form',$dataArr['tx_designer_form'.'_'.'1'],'form');
$content .= $form->printNeededJSFunctions_top();
$content .= $field;
$content .= $form->printNeededJSFunctions();

Ein Datensatz in der Tabelle tx_designer_form und der uid=1 existiert bereits. Anschließend hab ich die TCA.php editiert und folgendes reingeschrieben:

$TCA["tx_designer_form"] = array (
	"ctrl" => $TCA["tx_designer_form"]["ctrl"],
	"interface" => array (
		"showRecordFieldList" => "hidden,name,form"
	),
	"feInterface" => $TCA["tx_designer_form"]["feInterface"],
	"columns" => array (
		'hidden' => array (		
			'exclude' => 1,
			'label'   => 'LLL:EXT:lang/locallang_general.xml:LGL.hidden',
			'config'  => array (
				'type'    => 'check',
				'default' => '0'
			)
		),
		"name" => Array (		
			"exclude" => 1,		
			"label" => "LLL:EXT:designer/locallang_db.xml:tx_designer_form.name",		
			"config" => Array (
				"type" => "input",	
				"size" => "30",
			)
		),
		"form" => Array (		
			"exclude" => 1,		
			"label" => "LLL:EXT:designer/locallang_db.xml:tx_designer_form.form",		
			"config" => Array (
				"type" => "text",
				"cols" => "30",	
				"rows" => "5",
			)
		),
	),
	"types" => array (
		"0" => array("showitem" => "hidden;;1;;1-1-1, name, form")
	),
	"palettes" => array (
		"1" => array("showitem" => "")
	)
);

Das was später im RTE eingegeben wird, soll also im Feld form gespeichert werden. Bisher hab ich den RTE im TCA noch gar nicht angegeben, aber sollte nicht zumindest ein editierbares Textfeld erscheinen?

Viele Grüße

nomawie ·

#angry#

Ich war so schlau denn folgende Zeile zu vergessen:

$this->content.=$this->doc->section('Text:',$content,0,1);

Mensch, Mensch. Da such ich ewig wo mein Fehler liegt und 2 Minuten nachdem Posten fällts mir auf. Das Textfeld ist da 🙂 Dann schau ich mal ob ich den RTE auch hinbekomme. Aber erstmal was essen

edit:
hab jetzt noch eine Zeile in der tca.php erweitert so dass ich folgendes da stehen haben:

...
"form" => Array (		
			"exclude" => 1,		
			"label" => "LLL:EXT:designer/locallang_db.xml:tx_designer_form.form",		
			"config" => Array (
				"type" => "text",
				"cols" => "30",	
				"rows" => "5",
			),
			"defaultExtras" => "richtext[*]"
		),
...

leider ist es aber bei dem textfeld geblieben...

digedag ·

Das RTE-Textfeld muss im types-Array definiert werden:

'types' => Array (
  '0' => Array('showitem' => 'hidden;;1;;1-1-1, name,form;;;richtext[paste|bold|italic|underline|formatblock|class|left|center|right|orderedlist|unorderedlist|outdent|indent|link|image]:rte_transform[mode=ts],...')
),

Ohne diese Angabe ist das Feld aber auch im normalen Datenblatt des Records kein RTE. Weiter ist dann nichts notwendig.

Bücher helfen übrigens meistens nur für den Einstieg in die Materie. Wenn man es genau wissen will, dann muss man in den Code schauen. Dafür ist es ja OpenSource! 🙂
Die Core Documentation ist allerdings extrem lesenswert!

metaxos ·

Hallo

Habe die Anleitung von digedag befolgt und es klappt fast alles. Leider werden bei mir die Werte nur im hidden input Feld _hr angezeigt. Wenn ich den Feldtyp von String nach Textarea umwandle sehe ich den Wert auch im 'normalen' input Feld.

Ich habe testhalber im Moment bloss ein Textfeld welches ich speichern und anzeigen möchte. BTW: Wenn ich das _hr Feld überschreibe (FF Webdeveloper) und spreicher wird der Datensatz korrekt in der DB abgespeichert.

Was mache ich falsch?

Vielen Dank.

Gruss
metaxos

Synap ·

Hallo,

ich habe dies versucht umzusetzen ... Allerdings wird bei mir immer angezeigt "Der Editor wird geladen. Bitte warten..." ... Sobald ich auf den Button für Fullscreen klicke, zeigt er mir den Editor an. Weiss jemand woran das liegen kann?

Danke!