Repository: wagtail/wagtail

Issue:
Add expanding height to plain text fields
Currently with a full classname applied to the panel they are very tall within the CMS. It would be good if the expanded like the rich text field does. 



Discussion:
Implemented for StreamField in #1035 - will take this as a request to apply this to non-StreamField text areas too...

Brilliant thanks. 


Resolving patch:
diff --git a/wagtail/wagtailadmin/edit_handlers.py b/wagtail/wagtailadmin/edit_handlers.py
--- a/wagtail/wagtailadmin/edit_handlers.py
+++ b/wagtail/wagtailadmin/edit_handlers.py
@@ -25,26 +25,43 @@
 from wagtail.utils.deprecation import RemovedInWagtail11Warning
 
 
+# Form field properties to override whenever we encounter a model field
+# that matches one of these types - including subclasses
 FORM_FIELD_OVERRIDES = {
     models.DateField: {'widget': widgets.AdminDateInput},
     models.TimeField: {'widget': widgets.AdminTimeInput},
     models.DateTimeField: {'widget': widgets.AdminDateTimeInput},
-    TaggableManager: {'widget': widgets.AdminTagWidget}
+    TaggableManager: {'widget': widgets.AdminTagWidget},
+}
+
+# Form field properties to override whenever we encounter a model field
+# that matches one of these types exactly, ignoring subclasses.
+# (This allows us to override the widget for models.TextField, but leave
+# the RichTextField widget alone)
+DIRECT_FORM_FIELD_OVERRIDES = {
+    models.TextField: {'widget': widgets.AdminAutoHeightTextInput},
 }
 
 
 # Callback to allow us to override the default form fields provided for each model field.
 def formfield_for_dbfield(db_field, **kwargs):
-    # snarfed from django/contrib/admin/options.py
+    # adapted from django/contrib/admin/options.py
+
+    overrides = None
 
     # If we've got overrides for the formfield defined, use 'em. **kwargs
     # passed to formfield_for_dbfield override the defaults.
-    for klass in db_field.__class__.mro():
-        if klass in FORM_FIELD_OVERRIDES:
-            kwargs = dict(copy.deepcopy(FORM_FIELD_OVERRIDES[klass]), **kwargs)
-            return db_field.formfield(**kwargs)
+    if db_field.__class__ in DIRECT_FORM_FIELD_OVERRIDES:
+        overrides = DIRECT_FORM_FIELD_OVERRIDES[db_field.__class__]
+    else:
+        for klass in db_field.__class__.mro():
+            if klass in FORM_FIELD_OVERRIDES:
+                overrides = FORM_FIELD_OVERRIDES[klass]
+                break
+
+    if overrides:
+        kwargs = dict(copy.deepcopy(overrides), **kwargs)
 
-    # For any other type of field, just call its formfield() method.
     return db_field.formfield(**kwargs)
 
 


Test patch:
diff --git a/wagtail/wagtailadmin/tests/test_edit_handlers.py b/wagtail/wagtailadmin/tests/test_edit_handlers.py
--- a/wagtail/wagtailadmin/tests/test_edit_handlers.py
+++ b/wagtail/wagtailadmin/tests/test_edit_handlers.py
@@ -16,10 +16,11 @@
     InlinePanel,
 )
 
-from wagtail.wagtailadmin.widgets import AdminPageChooser, AdminDateInput
+from wagtail.wagtailadmin.widgets import AdminPageChooser, AdminDateInput, AdminAutoHeightTextInput
 from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
 from wagtail.wagtailcore.models import Page, Site
-from wagtail.tests.models import PageChooserModel, EventPageChooserModel, EventPage, EventPageSpeaker
+from wagtail.wagtailcore.fields import RichTextArea
+from wagtail.tests.models import PageChooserModel, EventPageChooserModel, EventPage, EventPageSpeaker, SimplePage
 from wagtail.tests.utils import WagtailTestUtils
 from wagtail.utils.deprecation import RemovedInWagtail11Warning
 
@@ -43,6 +44,22 @@ def test_get_form_for_model(self):
         self.assertIn('speakers', form.formsets)
         self.assertIn('related_links', form.formsets)
 
+    def test_direct_form_field_overrides(self):
+        # Test that field overrides defined through DIRECT_FORM_FIELD_OVERRIDES
+        # are applied
+
+        SimplePageForm = get_form_for_model(SimplePage)
+        simple_form = SimplePageForm()
+        # plain TextFields should use AdminAutoHeightTextInput as the widget
+        self.assertEqual(type(simple_form.fields['content'].widget), AdminAutoHeightTextInput)
+
+        # This override should NOT be applied to subclasses of TextField such as
+        # RichTextField - they should retain their default widgets
+        EventPageForm = get_form_for_model(EventPage)
+        event_form = EventPageForm()
+        self.assertEqual(type(event_form.fields['body'].widget), RichTextArea)
+
+
     def test_get_form_for_model_with_specific_fields(self):
         EventPageForm = get_form_for_model(EventPage, fields=['date_from'], formsets=['speakers'])
         form = EventPageForm()