diff --git a/src/wuttaweb/forms/base.py b/src/wuttaweb/forms/base.py
index 8f5cafc..83cd069 100644
--- a/src/wuttaweb/forms/base.py
+++ b/src/wuttaweb/forms/base.py
@@ -1111,6 +1111,32 @@ class Form:
return self.validated
+ def has_global_errors(self):
+ """
+ Convenience function to check if the form has any "global"
+ (not field-level) errors.
+
+ See also :meth:`get_global_errors()`.
+
+ :returns: ``True`` if global errors present, else ``False``.
+ """
+ dform = self.get_deform()
+ return bool(dform.error)
+
+ def get_global_errors(self):
+ """
+ Returns a list of "global" (not field-level) error messages
+ for the form.
+
+ See also :meth:`has_global_errors()`.
+
+ :returns: List of error messages (possibly empty).
+ """
+ dform = self.get_deform()
+ if dform.error is None:
+ return []
+ return dform.error.messages()
+
def get_field_errors(self, field):
"""
Return a list of error messages for the given field.
diff --git a/src/wuttaweb/templates/forms/vue_template.mako b/src/wuttaweb/templates/forms/vue_template.mako
index 5a4af70..d913054 100644
--- a/src/wuttaweb/templates/forms/vue_template.mako
+++ b/src/wuttaweb/templates/forms/vue_template.mako
@@ -4,6 +4,14 @@
${h.form(form.action_url, method='post', enctype='multipart/form-data', **form_attrs)}
${h.csrf_token(request)}
+ % if form.has_global_errors():
+ % for msg in form.get_global_errors():
+
+ ${msg}
+
+ % endfor
+ % endif
+
% for fieldname in form:
${form.render_vue_field(fieldname)}
diff --git a/tests/forms/test_base.py b/tests/forms/test_base.py
index ef8e4b6..54bf4da 100644
--- a/tests/forms/test_base.py
+++ b/tests/forms/test_base.py
@@ -544,6 +544,34 @@ class TestForm(TestCase):
data = form.get_vue_model_data()
self.assertEqual(list(data.values()), ['one', 'two', True])
+ def test_has_global_errors(self):
+
+ def fail(node, value):
+ node.raise_invalid("things are bad!")
+
+ schema = self.make_schema()
+ schema.validator = fail
+ form = self.make_form(schema=schema)
+ self.assertFalse(form.has_global_errors())
+ self.request.method = 'POST'
+ self.request.POST = {'foo': 'one', 'bar': 'two'}
+ self.assertFalse(form.validate())
+ self.assertTrue(form.has_global_errors())
+
+ def test_get_global_errors(self):
+
+ def fail(node, value):
+ node.raise_invalid("things are bad!")
+
+ schema = self.make_schema()
+ schema.validator = fail
+ form = self.make_form(schema=schema)
+ self.assertEqual(form.get_global_errors(), [])
+ self.request.method = 'POST'
+ self.request.POST = {'foo': 'one', 'bar': 'two'}
+ self.assertFalse(form.validate())
+ self.assertTrue(form.get_global_errors(), ["things are bad!"])
+
def test_get_field_errors(self):
schema = self.make_schema()