Skip to content

Alles für WordPress, Webentwicklung — und mehr

🛠 So erstellst du ein Widget-Plugin für WordPress: eine Schritt-für-Schritt-Anleitung

🛠 So erstellst du ein Widget-Plugin für WordPress: eine Schritt-für-Schritt-Anleitung

💡 So erstellen Sie ein WordPress-Widget-Plugin

  • Erstellen Sie einen Ordner my-widget-plugin innerhalb von wp-content/plugins/ und eine Datei my-widget-plugin.php mit dem Plugin-Header, und aktivieren Sie diese anschließend im Admin-Bereich
  • Deklarieren Sie eine Klasse, die WP_Widget erweitert, und überschreiben Sie die Methoden __construct(), form(), update() und widget()
  • Registrieren Sie das Widget mit der Funktion register_widget() am Hook widgets_init, damit WordPress es in der Liste sehen kann
  • Geben Sie in der Methode form() die Einstellungsfelder aus; in update() bereinigen und speichern Sie die Daten mit sanitize_text_field()
  • Geben Sie in der Methode widget() den Inhalt auf der Website aus und escapen Sie Werte mit esc_html() und wp_kses_post()

Schritt 1: Das Plugin-Grundgerüst erstellen

Ein Widget in WordPress ist nicht nur eine Zeile in der functions.php. Wenn Einstellungen erhalten bleiben, das Admin-Formular funktionieren und das Widget selbst den nächsten Theme-Wechsel überleben soll, müssen Sie es als Plugin paketieren. Das isoliert den Code und macht das Widget unabhängig von jedem Theme-Wechsel.

Beginnen Sie mit einem leeren Ordner. Navigieren Sie zu wp-content/plugins/ und erstellen Sie ein Verzeichnis namens my-widget-plugin. Erstellen Sie darin eine Datei mit dem Namen my-widget-plugin.php. Das ist die Datei, die WordPress bei der Aktivierung zuerst liest. Öffnen Sie die Datei und fügen Sie den standardmäßigen Plugin-Header ein:

1<?php
2/*
3Plugin Name: My Widget Plugin
4Plugin URI: https://www.wpexplorer.com/create-widget-plugin-wordpress/
5Description: Adds a customizable widget with text, textarea, checkbox, and dropdown.
6Version: 1.0
7Author: AJ Clarke
8Author URI: https://www.wpexplorer.com/
9License: GPL2
10*/

Speichern Sie die Datei. Gehen Sie nun ins WordPress-Admin-Panel → Plugins. Wenn das Plugin in der Liste erscheint, ist das Grundgerüst fertig. Klicken Sie auf „Aktivieren". Es tut noch nichts Nützliches; wir haben nur seine Existenz bekannt gegeben. Aber WordPress weiß bereits, dass dieses Plugin existiert und bereit ist, seinen Code auszuführen. Das ist ein wichtiges Prinzip: zuerst die Registrierung, dann die Logik.

Wie das Plugin intern funktioniert, welche Hooks bei der Aktivierung ausgelöst werden und wie WordPress Ihre Datei findet, wird im obigen Video behandelt. Kommen wir nun zum interessantesten Teil: der Widget-Klasse.

Schritt 2: Das Widget über WP_Widget registrieren

WordPress bietet eine eingebaute Klasse namens WP_Widget; sie ist seit Version 2.8 Teil des Kerns und bleibt die Grundlage für alle benutzerdefinierten Widgets. Sie müssen keine Speicherlogik, Feldgenerierung oder Registrierung von Grund auf neu schreiben: Erweitern Sie einfach die Klasse und überschreiben Sie vier Methoden.

Fügen Sie diesen Code direkt nach dem Plugin-Header, vor dem schließenden ?>, in Ihre my-widget-plugin.php ein:

1// Widget class
2class My_Custom_Widget extends WP_Widget {
3
4 public function __construct() {
5 parent::__construct(
6 'my_custom_widget',
7 __( 'My Custom Widget', 'text_domain' ),
8 array(
9 'customize_selective_refresh' => true,
10 )
11 );
12 }
13
14 public function form( $instance ) {
15 /* ... admin form ... */
16 }
17
18 public function update( $new_instance, $old_instance ) {
19 /* ... saving settings ... */
20 }
21
22 public function widget( $args, $instance ) {
23 /* ... frontend output ... */
24 }
25}
26
27// Widget registration
28function my_register_custom_widget() {
29 register_widget( 'My_Custom_Widget' );
30}
31add_action( 'widgets_init', 'my_register_custom_widget' );

Lassen Sie uns aufschlüsseln, was hier passiert. Die Klasse My_Custom_Widget erweitert WP_Widget, was Ihnen fertige Methoden wie get_field_id() und get_field_name() zur Generierung von Formularfeld-Attributen liefert. Im Konstruktor übergeben wir drei Dinge an die Elternklasse: eine eindeutige Widget-ID (lateinische Kleinbuchstaben, keine Leerzeichen, my_custom_widget), ihren lesbaren Namen (die Funktion __() macht sie übersetzbar) und ein Options-Array. Der Parameter customize_selective_refresh => true erlaubt es dem Widget, sich im Customizer zu aktualisieren, ohne die gesamte Seite neu zu laden, ein kleines Detail, das während der Einrichtung viel Frustration erspart.

Die Funktion my_register_custom_widget() ruft register_widget() am Hook widgets_init auf. So erfährt WordPress von Ihrem Widget. Ohne diese Zeile erscheint nichts im Admin-Bereich.

Nun füllen wir die Methoden form(), update() und widget() mit echter Logik.

Schritt 3: Das Widget-Formular im Admin-Bereich erstellen

Das Formular ist das, was der Administrator sieht, wenn er das Widget in eine Seitenleiste zieht. Es besteht aus Feldern: Texteingaben, Dropdowns, Checkboxen. Jedes Feld muss in der Lage sein, seinen Wert zu speichern und den aktuellen Wert beim erneuten Öffnen anzuzeigen.

3.1. Die Funktion form() und Eingabefelder

Fügen Sie diesen Code in die Methode form() Ihrer Klasse ein. Er erstellt fünf Felder: einen Titel, eine Texteingabe, eine Textarea, eine Checkbox und ein Dropdown.

1public function form( $instance ) {
2
3 $defaults = array(
4 'title' => '',
5 'text' => '',
6 'textarea' => '',
7 'checkbox' => '',
8 'select' => '',
9 );
10
11 $args = wp_parse_args( (array) $instance, $defaults );
12 $title = $args['title'];
13 $text = $args['text'];
14 $textarea = $args['textarea'];
15 $checkbox = $args['checkbox'];
16 $select = $args['select'];
17 ?>
18
19 <p>
20 <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">
21 <?php _e( 'Widget Title', 'text_domain' ); ?>
22 </label>
23 <input class="widefat"
24 id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
25 name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
26 type="text"
27 value="<?php echo esc_attr( $title ); ?>" />
28 </p>
29
30 <p>
31 <label for="<?php echo esc_attr( $this->get_field_id( 'text' ) ); ?>">
32 <?php _e( 'Text:', 'text_domain' ); ?>
33 </label>
34 <input class="widefat"
35 id="<?php echo esc_attr( $this->get_field_id( 'text' ) ); ?>"
36 name="<?php echo esc_attr( $this->get_field_name( 'text' ) ); ?>"
37 type="text"
38 value="<?php echo esc_attr( $text ); ?>" />
39 </p>
40
41 <p>
42 <label for="<?php echo esc_attr( $this->get_field_id( 'textarea' ) ); ?>">
43 <?php _e( 'Textarea:', 'text_domain' ); ?>
44 </label>
45 <textarea class="widefat"
46 id="<?php echo esc_attr( $this->get_field_id( 'textarea' ) ); ?>"
47 name="<?php echo esc_attr( $this->get_field_name( 'textarea' ) ); ?>"><?php
48 echo wp_kses_post( $textarea );
49 ?></textarea>
50 </p>
51
52 <p>
53 <input id="<?php echo esc_attr( $this->get_field_id( 'checkbox' ) ); ?>"
54 name="<?php echo esc_attr( $this->get_field_name( 'checkbox' ) ); ?>"
55 type="checkbox"
56 value="1"
57 <?php checked( '1', $checkbox ); ?> />
58 <label for="<?php echo esc_attr( $this->get_field_id( 'checkbox' ) ); ?>">
59 <?php _e( 'Show additional block', 'text_domain' ); ?>
60 </label>
61 </p>
62
63 <p>
64 <label for="<?php echo $this->get_field_id( 'select' ); ?>">
65 <?php _e( 'Display variant', 'text_domain' ); ?>
66 </label>
67 <select name="<?php echo $this->get_field_name( 'select' ); ?>"
68 id="<?php echo $this->get_field_id( 'select' ); ?>"
69 class="widefat">
70 <?php
71 $options = array(
72 '' => __( '— Select —', 'text_domain' ),
73 'option_1' => __( 'Option 1', 'text_domain' ),
74 'option_2' => __( 'Option 2', 'text_domain' ),
75 'option_3' => __( 'Option 3', 'text_domain' ),
76 );
77 foreach ( $options as $key => $name ) {
78 printf(
79 '<option value="%s" %s>%s</option>',
80 esc_attr( $key ),
81 selected( $select, $key, false ),
82 esc_html( $name )
83 );
84 }
85 ?>
86 </select>
87 </p>
88
89<?php }

Achten Sie auf zwei Dinge. Erstens haben wir die veraltete Funktion extract() durch direkten Array-Zugriff ersetzt. extract() ist seit langem aus den WordPress-Codierungsstandards ausgeschlossen; es erstellt Variablen, die nach Array-Schlüsseln benannt sind, was unsicher ist und die Fehlersuche erschwert. Zweitens wird jeder Ausgabewert durch esc_attr(), wp_kses_post() oder esc_html() geleitet. Das ist keine Paranoia: Daten aus der Datenbank können von überall herkommen, und die Bereinigung ist obligatorisch.

3.2. Die Funktion update() zum Speichern

Die Methode update() wird aufgerufen, wenn im Widget-Formular auf „Speichern" geklickt wird. Ihre Aufgabe ist es, jedes Feld zu validieren und ein bereinigtes Array zum Schreiben in die Datenbank zurückzugeben.

1public function update( $new_instance, $old_instance ) {
2 $instance = $old_instance;
3
4 $instance['title'] = isset( $new_instance['title'] )
5 ? sanitize_text_field( $new_instance['title'] ) : '';
6 $instance['text'] = isset( $new_instance['text'] )
7 ? sanitize_text_field( $new_instance['text'] ) : '';
8 $instance['textarea'] = isset( $new_instance['textarea'] )
9 ? wp_kses_post( $new_instance['textarea'] ) : '';
10 $instance['checkbox'] = isset( $new_instance['checkbox'] ) ? 1 : false;
11 $instance['select'] = isset( $new_instance['select'] )
12 ? sanitize_text_field( $new_instance['select'] ) : '';
13
14 return $instance;
15}

Hier verwenden wir sanitize_text_field() anstelle von wp_strip_all_tags(), weil es auch Leerzeichen normalisiert, unsichtbare Steuerzeichen entfernt und den String in sicheres UTF-8 konvertiert. Das ist eine gründlichere Bereinigung. wp_strip_all_tags() hinterlässt „rohen" Text mit allen Leerzeichen-Artefakten. Wählen Sie für Textformularfelder immer sanitize_text_field().

Die Textarea behält wp_kses_post(): Es erlaubt grundlegendes HTML (Links, Fettdruck, Listen), entfernt aber Skripte. Die Checkbox gibt 1 oder false zurück, was lesbar und in der Datenbank eindeutig ist.

Schritt 4: Das Widget auf der Website ausgeben

Die Funktion widget() ist das, was der Besucher sieht. Sie erhält zwei Parameter: $args (den Widget-Wrapper, Tags vor und nach dem Titel und der Seitenleiste) und $instance (die gespeicherten Einstellungen für diese spezifische Instanz).

1public function widget( $args, $instance ) {
2
3 $title = isset( $instance['title'] )
4 ? apply_filters( 'widget_title', $instance['title'] ) : '';
5 $text = isset( $instance['text'] ) ? $instance['text'] : '';
6 $textarea = isset( $instance['textarea'] ) ? $instance['textarea'] : '';
7 $select = isset( $instance['select'] ) ? $instance['select'] : '';
8 $checkbox = ! empty( $instance['checkbox'] ) ? $instance['checkbox'] : false;
9
10 echo $args['before_widget'];
11
12 echo '<div class="widget-text wp_widget_plugin_box">';
13
14 if ( $title ) {
15 echo $args['before_title'] . esc_html( $title ) . $args['after_title'];
16 }
17
18 if ( $text ) {
19 echo '<p>' . esc_html( $text ) . '</p>';
20 }
21
22 if ( $textarea ) {
23 echo '<div class="widget-textarea">' . wp_kses_post( $textarea ) . '</div>';
24 }
25
26 if ( $select ) {
27 echo '<p class="widget-select">' . esc_html( $select ) . '</p>';
28 }
29
30 if ( $checkbox ) {
31 echo '<p class="widget-checkbox-result">' . esc_html__( 'Additional block activated', 'text_domain' ) . '</p>';
32 }
33
34 echo '</div>';
35
36 echo $args['after_widget'];
37}

Der entscheidende Punkt hier: Wir haben extract( $args ) durch direkten Zugriff via $args['before_widget'] ersetzt. Der Grund ist derselbe: extract() ist veraltet und unsicher. Wir haben die Ausgabe auch mit esc_html() umschlossen, wo Klartext erwartet wird (der Titel, der Text-String, der Select-Wert). Die Textarea wird durch wp_kses_post() ausgegeben, sodass ein Link oder Fettdruck erhalten bleibt, falls der Administrator sie eingefügt hat.

Die CSS-Klasse wp_widget_plugin_box erlaubt es Ihnen, den Block aus dem Stylesheet des Themes zu stylen. Sie können sie gerne umbenennen, stellen Sie nur sicher, dass die Klasse eindeutig ist und nicht mit Theme-Klassen kollidiert.

Vollständiger Plugin-Code

Fügen wir alles zusammen. Hier ist die vollständige Datei my-widget-plugin.php, bereit zum Kopieren und Aktivieren:

1<?php
2/*
3Plugin Name: My Widget Plugin
4Plugin URI: https://www.wpexplorer.com/create-widget-plugin-wordpress/
5Description: Adds a customizable widget with text, textarea, checkbox, and dropdown.
6Version: 1.0
7Author: AJ Clarke
8Author URI: https://www.wpexplorer.com/
9License: GPL2
10*/
11
12class My_Custom_Widget extends WP_Widget {
13
14 public function __construct() {
15 parent::__construct(
16 'my_custom_widget',
17 __( 'My Custom Widget', 'text_domain' ),
18 array( 'customize_selective_refresh' => true )
19 );
20 }
21
22 public function form( $instance ) {
23 $defaults = array(
24 'title' => '', 'text' => '', 'textarea' => '',
25 'checkbox' => '', 'select' => ''
26 );
27 $args = wp_parse_args( (array) $instance, $defaults );
28 $title = $args['title'];
29 $text = $args['text'];
30 $textarea = $args['textarea'];
31 $checkbox = $args['checkbox'];
32 $select = $args['select'];
33 ?>
34 <p>
35 <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">
36 <?php _e( 'Widget Title', 'text_domain' ); ?>
37 </label>
38 <input class="widefat"
39 id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
40 name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
41 type="text" value="<?php echo esc_attr( $title ); ?>" />
42 </p>
43 <p>
44 <label for="<?php echo esc_attr( $this->get_field_id( 'text' ) ); ?>">
45 <?php _e( 'Text:', 'text_domain' ); ?>
46 </label>
47 <input class="widefat"
48 id="<?php echo esc_attr( $this->get_field_id( 'text' ) ); ?>"
49 name="<?php echo esc_attr( $this->get_field_name( 'text' ) ); ?>"
50 type="text" value="<?php echo esc_attr( $text ); ?>" />
51 </p>
52 <p>
53 <label for="<?php echo esc_attr( $this->get_field_id( 'textarea' ) ); ?>">
54 <?php _e( 'Textarea:', 'text_domain' ); ?>
55 </label>
56 <textarea class="widefat"
57 id="<?php echo esc_attr( $this->get_field_id( 'textarea' ) ); ?>"
58 name="<?php echo esc_attr( $this->get_field_name( 'textarea' ) ); ?>"><?php
59 echo wp_kses_post( $textarea );
60 ?></textarea>
61 </p>
62 <p>
63 <input id="<?php echo esc_attr( $this->get_field_id( 'checkbox' ) ); ?>"
64 name="<?php echo esc_attr( $this->get_field_name( 'checkbox' ) ); ?>"
65 type="checkbox" value="1" <?php checked( '1', $checkbox ); ?> />
66 <label for="<?php echo esc_attr( $this->get_field_id( 'checkbox' ) ); ?>">
67 <?php _e( 'Show additional block', 'text_domain' ); ?>
68 </label>
69 </p>
70 <p>
71 <label for="<?php echo $this->get_field_id( 'select' ); ?>">
72 <?php _e( 'Display variant', 'text_domain' ); ?>
73 </label>
74 <select name="<?php echo $this->get_field_name( 'select' ); ?>"
75 id="<?php echo $this->get_field_id( 'select' ); ?>" class="widefat">
76 <?php
77 $options = array(
78 '' => __( '— Select —', 'text_domain' ),
79 'option_1' => __( 'Option 1', 'text_domain' ),
80 'option_2' => __( 'Option 2', 'text_domain' ),
81 'option_3' => __( 'Option 3', 'text_domain' ),
82 );
83 foreach ( $options as $key => $name ) {
84 printf(
85 '<option value="%s" %s>%s</option>',
86 esc_attr( $key ),
87 selected( $select, $key, false ),
88 esc_html( $name )
89 );
90 }
91 ?>
92 </select>
93 </p>
94 <?php
95 }
96
97 public function update( $new_instance, $old_instance ) {
98 $instance = $old_instance;
99 $instance['title'] = isset( $new_instance['title'] )
100 ? sanitize_text_field( $new_instance['title'] ) : '';
101 $instance['text'] = isset( $new_instance['text'] )
102 ? sanitize_text_field( $new_instance['text'] ) : '';
103 $instance['textarea'] = isset( $new_instance['textarea'] )
104 ? wp_kses_post( $new_instance['textarea'] ) : '';
105 $instance['checkbox'] = isset( $new_instance['checkbox'] ) ? 1 : false;
106 $instance['select'] = isset( $new_instance['select'] )
107 ? sanitize_text_field( $new_instance['select'] ) : '';
108 return $instance;
109 }
110
111 public function widget( $args, $instance ) {
112 $title = isset( $instance['title'] )
113 ? apply_filters( 'widget_title', $instance['title'] ) : '';
114 $text = isset( $instance['text'] ) ? $instance['text'] : '';
115 $textarea = isset( $instance['textarea'] ) ? $instance['textarea'] : '';
116 $select = isset( $instance['select'] ) ? $instance['select'] : '';
117 $checkbox = ! empty( $instance['checkbox'] ) ? $instance['checkbox'] : false;
118
119 echo $args['before_widget'];
120 echo '<div class="widget-text wp_widget_plugin_box">';
121
122 if ( $title ) {
123 echo $args['before_title'] . esc_html( $title ) . $args['after_title'];
124 }
125 if ( $text ) {
126 echo '<p>' . esc_html( $text ) . '</p>';
127 }
128 if ( $textarea ) {
129 echo '<div class="widget-textarea">' . wp_kses_post( $textarea ) . '</div>';
130 }
131 if ( $select ) {
132 echo '<p class="widget-select">' . esc_html( $select ) . '</p>';
133 }
134 if ( $checkbox ) {
135 echo '<p class="widget-checkbox-result">'
136 . esc_html__( 'Additional block activated', 'text_domain' ) . '</p>';
137 }
138
139 echo '</div>';
140 echo $args['after_widget'];
141 }
142}
143
144function my_register_custom_widget() {
145 register_widget( 'My_Custom_Widget' );
146}
147add_action( 'widgets_init', 'my_register_custom_widget' );

Platzieren Sie diese Datei in wp-content/plugins/my-widget-plugin/, aktivieren Sie das Plugin und ziehen Sie das Widget über Design → Widgets in eine beliebige Seitenleiste. Füllen Sie die Felder aus, speichern Sie und überprüfen Sie Ihre Website.

Der fertige Code ist auch auf GitHub verfügbar: wpexplorer/my-widget-plugin, wo Sie ihn mit der ursprünglichen Version von 2017 vergleichen und genau sehen können, was wir geändert haben.

⁉️🤔 Häufig gestellte Fragen

Warum ein Widget in ein Plugin packen, wenn man den Code einfach in die functions.php des Themes einfügen kann?

Code in der functions.php ist an das aktive Theme gebunden. Wechseln Sie das Theme, verschwindet das Widget. Ein Plugin funktioniert unabhängig vom Theme. Darüber hinaus kann ein Plugin selektiv auf verschiedenen Websites aktiviert werden, Theme-Code hingegen nicht. Wenn das Widget einen geschäftlichen Bedarf löst (zum Beispiel die Anzeige eines Anmeldeformulars mit einem bestimmten Layout), gehört es in ein Plugin.

Warum ist sanitize_text_field() besser als wp_strip_all_tags()?

sanitize_text_field() entfernt nicht nur HTML-Tags; es normalisiert auch Leerzeichen, entfernt unsichtbare Steuerzeichen und konvertiert den String in UTF-8. Das ist eine gründlichere Bereinigung. wp_strip_all_tags() hinterlässt „rohen" Text mit allen Leerzeichen-Artefakten. Wählen Sie für Textformularfelder immer sanitize_text_field().

Warum haben Sie extract() durch direkten Array-Zugriff ersetzt?

Die Funktion extract() ist seit Version 4.3 aus den WordPress-Codierungsstandards ausgeschlossen. Sie erstellt Variablen, die nach Array-Schlüsseln benannt sind, im lokalen Gültigkeitsbereich; wenn ein Schlüssel mit einer bestehenden Variablen übereinstimmt, überschreiben Sie diese und erhalten einen schwer zu findenden Fehler. Direkter Zugriff wie $args['before_widget'] ist lesbar und sicher.

Muss ich Block-Widgets unterstützen (Gutenberg)?

Das klassische WP_Widget funktioniert durch Abwärtskompatibilität mit blockbasierten Seitenleisten: WordPress verpackt es automatisch in einen Legacy-Widget-Block. Das ist für die meisten Szenarien ausreichend. Wenn Sie wirklich native Blöcke erstellen möchten, lesen Sie das Block Editor Handbook, das eine separate API bietet. Aber der Einstieg mit WP_Widget ist einfacher: Der Code ist kürzer, die Fehlersuche ist schneller und es funktioniert auf allen WordPress-Versionen ohne zusätzliche Kompatibilitäts-Plugins.

Wie debugge ich ein Widget, das nicht im Admin-Bereich erscheint?

Prüfen Sie drei Dinge. Erstens: Wurde der Hook widgets_init ausgelöst? Fügen Sie error_log( 'Widget registered' ) zur Registrierungsfunktion hinzu und prüfen Sie die Logs. Zweitens: Gibt es einen fatalen Fehler im Konstruktor? Aktivieren Sie WP_DEBUG in der wp-config.php. Drittens: Stimmt der Klassenname in register_widget() mit dem Namen der Klasse überein, die WP_Widget erweitert? Ein einziger Tippfehler, und das Widget erscheint nicht.

Wie geht es weiter: Vom Template zu Ihrem eigenen Widget

Wir haben ein funktionierendes Plugin mit fünf Feldtypen gebaut. Das ist kein fertiges Produkt, sondern ein Grundgerüst. Nehmen Sie es als Ihre Basis und passen Sie es an Ihre Bedürfnisse an. Brauchen Sie ein Widget für ein Anmeldeformular? Ersetzen Sie die Textfelder durch E-Mail- und Namensfelder und fügen Sie einen API-Aufruf eines Mailing-Dienstes in widget() ein. Brauchen Sie einen Block mit Aktionen und Bannern? Laden Sie Bilder über den Medien-Uploader und geben Sie sie in Ihrem Markup aus. Die Mechanik ist immer dieselbe: form() zeichnet die Felder, update() speichert sie, widget() gibt die Ausgabe aus.

Fangen Sie klein an: Kopieren Sie den vollständigen Code oben, aktivieren Sie ihn auf einer Testseite und experimentieren Sie mit den Einstellungen. Sobald Sie verstanden haben, wie die Daten vom Formular zur Website fließen, beginnen Sie, Ihre eigenen Felder hinzuzufügen. Und wenn das Widget mit einem weißen Bildschirm abstürzt, gehen Sie zurück zu Schritt 2 und überprüfen Sie den Konstruktor.