الجزء الاولالجزء الثاني7 رسائل التحقق والخطأ
يجب أن تعرض معظم النماذج رسائل التحقق لإعلام المستخدم بالأخطاء التي ارتكبها.
يوفر
Thymeleaf العديد من الأدوات لذلك: العديد من الوظائف في كائن
#fields ، و
th: أخطاء ،
وخاصية error: errorclass .
7.1 أخطاء المجال
دعونا نرى كيف يمكننا تعيين فئة CSS محددة للحقل إذا كان يحتوي على خطأ:
<input type="text" th:field="*{datePlanted}" th:class="${#fields.hasErrors('datePlanted')}? fieldError" />
كما ترى ، تتلقى الدالة
# fields.hasErrors (...) تعبير حقل كمعلمة (
datePlanted ) وتُرجع قيمة منطقية تشير إلى ما إذا كانت هناك أية أخطاء في التحقق من صحة هذا الحقل.
يمكننا أيضًا الحصول على جميع الأخطاء لهذا الحقل وتكرارها:
<ul> <li th:each="err : ${#fields.errors('datePlanted')}" th:text="${err}" /> </ul>
بدلاً من التكرار ، يمكننا أيضًا استخدام
th: أخطاء ، وهي سمة متخصصة تنشئ قائمة بها جميع الأخطاء الخاصة بالمحدد المحدد ، مفصولة <br />:
<input type="text" th:field="*{datePlanted}" /> <p th:if="${#fields.hasErrors('datePlanted')}" th:errors="*{datePlanted}">Incorrect date</p>
تصميم CSS القائم على الأخطاء:
th: errorclassالمثال الذي رأيناه أعلاه ، تعيين فئة CSS لنموذج الإدخال ، إذا كانت هناك أخطاء في هذا الحقل ، يعد أمرًا شائعًا إلى حد أن Thymeleaf يقدم سمة خاصة للتنفيذ الدقيق:
th: errorclass .
يتم تطبيقه على علامة حقل النموذج (الإدخال ، الاختيار ، textarea ...) ، سوف يقرأ اسم الحقل المراد التحقق منه من أي
اسم موجود أو سمات
الحقل: في نفس العلامة ، ثم إضافة فئة CSS المحددة إلى العلامة ، إذا كان هذا الحقل لديه أي أخطاء ذات صلة:
<input type="text" th:field="*{datePlanted}" class="small" th:errorclass="fieldError" />
إذا كانت هناك أخطاء في
datePlanted ، سيبدو كما يلي:
<input type="text" id="datePlanted" name="datePlanted" value="2013-01-01" class="small fieldError" />
7.2 كل الأخطاء
ولكن ماذا لو أردنا إظهار كل الأخطاء في النموذج؟ نحتاج فقط إلى طلب
# field.hasErrors (...) و
# field.errors (...) مع الثوابت '
* ' أو '
all ' (أي ما يعادلها):
<ul th:if="${#fields.hasErrors('*')}"> <li th:each="err : ${#fields.errors('*')}" th:text="${err}">Input is incorrect</li> </ul>
كما في الأمثلة أعلاه ، يمكننا الحصول على كل الأخطاء والتكرار عليها ...
<ul> <li th:each="err : ${#fields.errors('*')}" th:text="${err}" /> </ul>
... وكذلك إنشاء قائمة مشتركة <br />:
<p th:if="${#fields.hasErrors('all')}" th:errors="*{all}">Incorrect date</p>
أخيرًا ، لاحظ أن
# field.hasErrors ('*') مكافئ لـ
# field.hasAnyErrors () ، و
# field.errors ('*') مكافئ لـ
# field.allErrors () . استخدم بناء الجملة الذي تفضله:
<div th:if="${#fields.hasAnyErrors()}"> <p th:each="err : ${#fields.allErrors()}" th:text="${err}">...</p> </div>
7.3 الأخطاء العالمية
يوجد نوع ثالث من الأخطاء في نموذج Spring: الأخطاء العامة. هذه هي الأخطاء التي لا ترتبط بأي حقول محددة في النموذج ، ولكن لا تزال موجودة.
يوفر Thymeleaf ثابتًا
عالميًا للوصول إلى هذه الأخطاء:
<ul th:if="${#fields.hasErrors('global')}"> <li th:each="err : ${#fields.errors('global')}" th:text="${err}">Input is incorrect</li> </ul>
<p th:if="${#fields.hasErrors('global')}" th:errors="*{global}">Incorrect date</p>
... بالإضافة إلى أساليب المساعد المكافئة
# field.hasGlobalErrors () و
# field.globalErrors () :
7.4 عرض الأخطاء خارج النماذج
يمكن أيضًا عرض أخطاء التحقق من صحة النموذج خارج النماذج باستخدام المتغيرات (
$ {...} ) بدلاً من تحديد التعبيرات (
* {...} ) وبادئة لاسم المكون الذي يدعم النموذج:
<div th:errors="${myForm}">...</div> <div th:errors="${myForm.date}">...</div> <div th:errors="${myForm.*}">...</div> <div th:if="${#fields.hasErrors('${myForm}')}">...</div> <div th:if="${#fields.hasErrors('${myForm.date}')}">...</div> <div th:if="${#fields.hasErrors('${myForm.*}')}">...</div> <form th:object="${myForm}"> ... </form>
7.5 كائنات خطأ غني
يوفر Thymeleaf إمكانية تلقي معلومات حول أخطاء النماذج في شكل مكونات bean (بدلاً من سلاسل بسيطة) مع سمات
fieldName (سلسلة)
ورسالة (سلسلة)
وعالمية (منطقية).
يمكن الحصول على هذه الأخطاء باستخدام طريقة الأداة المساعدة
# field.detailedErrors () :
<ul> <li th:each="e : ${#fields.detailedErrors()}" th:class="${e.global}? globalerr : fielderr"> <span th:text="${e.global}? '*' : ${e.fieldName}">The field name</span> | <span th:text="${e.message}">The error message</span> </li> </ul>
8 هذا لا يزال نموذجا أوليا!
طلبنا جاهز ولكن دعونا نلقي نظرة أخرى على صفحة. html التي أنشأناها ...
إحدى أكثر عواقب العمل مع Thymeleaf ممتعة هي أنه بعد كل هذه الوظائف التي أضفناها إلى HTML ، لا يزال بإمكاننا استخدام HTML هذا كنموذج أولي (نقول أن هذا
قالب طبيعي ). دعنا نفتح
seedstartermng.html مباشرة في
متصفحنا دون إطلاق تطبيقنا:

ها هو! هذا ليس تطبيقًا عمليًا ، فهو ليس بيانات حقيقية ... ولكنه نموذج أولي صحيح تمامًا يتكون من كود HTML المعروض تمامًا.
9 خدمة التحويل
9.1 التكوين
كما هو موضح سابقًا ، قد تستخدم Thymeleaf خدمة التحويل المسجلة في سياق التطبيق. تقوم فئة تهيئة التطبيق لدينا ، التي توسع برنامج Spring
WebMvcConfigurerAdapter المساعد ، بتسجيل خدمة التحويل التي يمكننا تكوينها تلقائيًا عن طريق إضافة أدوات التنسيق اللازمة. دعونا نرى كيف يبدو مرة أخرى:
@Override public void addFormatters(final FormatterRegistry registry) { super.addFormatters(registry); registry.addFormatter(varietyFormatter()); registry.addFormatter(dateFormatter()); } @Bean public VarietyFormatter varietyFormatter() { return new VarietyFormatter(); } @Bean public DateFormatter dateFormatter() { return new DateFormatter(); }
9.2 بناء جملة قوس مزدوج
يمكن تطبيق خدمة التحويل بسهولة لتحويل / تنسيق أي كائن إلى سلسلة. يتم ذلك باستخدام بناء جملة تعبير الأقواس المزدوجة:
- للتعبيرات المتغيرة: $ {{...}}
- للتعبير عن الاختيار: * {{...}}
لذلك ، على سبيل المثال ، في ضوء المحول Integer-to-String ، الذي يضيف الفواصل كفاصل الآلاف ، هذا:
<p th:text="${val}">...</p> <p th:text="${{val}}">...</p>
... يجب أن يؤدي إلى:
<p>1234567890</p> <p>1,234,567,890</p>
9.3 استخدم في النماذج
لقد رأينا سابقًا أن كل سمة
: field ستطبق دائمًا خدمة تحويل ، لذلك هذا:
<input type="text" th:field="*{datePlanted}" />
... مكافئ فعليًا لـ:
<input type="text" th:field="*{{datePlanted}}" />
لاحظ أنه وفقًا لمتطلبات Spring ، هذا هو السيناريو الوحيد الذي يتم فيه تطبيق خدمة التحويل على التعبيرات باستخدام بناء جملة أحادي.
9.4 # كائن تحويل التحويلات
يسمح لك كائن الأداة المساعدة للتحويل #conversions ببدء تشغيل خدمة التحويل يدويًا عند الضرورة:
<p th:text="${'Val: ' + #conversions.convert(val,'String')}">...</p>
بناء جملة كائن الخدمة هذا هو:
- # conversions.convert (كائن ، فئة) : يحول الكائن إلى الفئة المحددة
- # conversions.convert (كائن ، سلسلة) : نفسه على النحو الوارد أعلاه ، ولكن مع الفئة المستهدفة مثل سلسلة (لاحظ أنه قد يتم حذف حزمة java.lang.)
10 تقديم أجزاء من أجزاء قالب القالب (أجاكس إلخ)
يوفر Thymeleaf القدرة على تقديم جزء فقط من القالب نتيجة لتنفيذه:
شظية .
يمكن أن يكون هذا أداة تكوين مفيدة. على سبيل المثال ، يمكن استخدامه على وحدات التحكم التي تعمل على مكالمات
AJAX التي يمكنها إرجاع أجزاء من تخطيط الصفحة التي تم تحميلها بالفعل في المستعرض (لتحديث التحديد ، لتبديل / إيقاف تشغيل الأزرار ...).
يمكن تحقيق التجزؤ المجزأ باستخدام مواصفات مقتطف Thymeleaf: الكائنات التي تنفذ واجهة
org.thymeleaf.fragment.IFragmentSpec .
أكثر هذه التطبيقات شيوعًا هو
org.thymeleaf.standard.fragment.StandardDOMSelectorFragmentSpec ، والذي يسمح لك بتحديد جزء باستخدام محدد DOM ، تمامًا مثل تلك المستخدمة في
th: include أو
th: replace .
10.1 تعريف الشظايا في حبة المشاهدة
حبوب المشاهدة هي حبوب فئة
org.thymeleaf.spring4.view.ThymeleafView المعلنة في سياق التطبيق (تعليق
Bean إذا كنت تستخدم تكوين Java). إنها تسمح لك بتحديد الأجزاء كما يلي:
@Bean(name="content-part") @Scope("prototype") public ThymeleafView someViewBean() { ThymeleafView view = new ThymeleafView("index");
بالنظر إلى التعريف الوارد أعلاه للحبة ، إذا كانت وحدة التحكم الخاصة بنا تُرجع
جزءًا من المحتوى (اسم الحبة أعلاه) ...
@RequestMapping("/showContentPart") public String showContentPart() { ... return "content-part"; }
... لن يعرض Thymeleaf سوى جزءًا بسيطًا من
محتوى قالب الفهرس - من المرجح أن يكون
موقعه هو نفسه تقريبا /
WEB-INF/templates/index.html ، بعد تطبيق البادئة واللاحقة. وبالتالي ، ستكون النتيجة مكافئة تمامًا لتحديد
index :: content :
<!DOCTYPE html> <html> ... <body> ... <div th:fragment="content"> Only this div will be rendered! </div> ... </body> </html>
لاحظ أيضًا أنه بفضل محددات تخطيط Thymeleaf القوية ، يمكننا تحديد جزء في قالب بدون أي سمات
th: fragment .
لنستخدم سمة
المعرف ، على سبيل المثال:
@Bean(name="content-part") @Scope("prototype") public ThymeleafView someViewBean() { ThymeleafView view = new ThymeleafView("index");
10.2 تحديد الشظايا في القيمة المرجعة لوحدة التحكم
بدلاً من التصريح عن
حبوب العرض ، يمكن تعريف الأجزاء من وحدة التحكم باستخدام بناء جملة
تعبيرات الأجزاء . مثلما هو الحال في
ال: إدراج أو
ال: استبدال السمات.
@RequestMapping("/showContentPart") public String showContentPart() { ... return "index :: content"; }
بالطبع ، تتوفر الطاقة الكاملة لمحددات DOM مرة أخرى ، حتى نتمكن من تحديد جزءنا استنادًا إلى سمات HTML القياسية ، مثل
id = "content" :
@RequestMapping("/showContentPart") public String showContentPart() { ... return "index :: #content"; }
ويمكننا أيضًا استخدام معلمات مثل:
@RequestMapping("/showContentPart") public String showContentPart() { ... return "index :: #content ('myvalue')"; }
11 ميزات التكامل المتقدمة
11.1 التكامل مع RequestDataValueProcessor
يدمج Thymeleaf بسلاسة مع واجهة Spring
RequestDataValueProcessor . تسمح لك هذه الواجهة باعتراض عناوين URL للرابط وعناوين URL الخاصة بالقيم وقيم حقل النموذج قبل كتابتها إلى نتيجة الترميز ، بالإضافة إلى إضافة حقول النماذج المخفية التي تتضمن ميزات الأمان بشفافية ، مثل: الحماية من ملف CSRF (تزوير الطلبات عبر المواقع) .
يمكن تكوين تطبيق
RequestDataValueProcessor بسهولة في سياق التطبيق. يجب أن تقوم
بتطبيق واجهة
org.springframework.web.servlet.support.RequestDataValueProcessor ويكون لها
requestDataValueProcessor كاسم الفول:
@Bean public RequestDataValueProcessor requestDataValueProcessor() { return new MyRequestDataValueProcessor(); }
... وسوف تستخدم ثيميليف على النحو التالي:
- th: href و th: src استدعاء RequestDataValueProcessor.processUrl (...) قبل تقديم URL
- th: يستدعي الإجراء RequestDataValueProcessor.processAction (...) قبل تقديم سمة الإجراء للنموذج ، بالإضافة إلى أنه يكتشف عندما يتم تطبيق هذه السمة على العلامة <form> ، والتي يجب أن تكون في كل الأحوال هي المكان الوحيد ، وفي هذه الحالة تستدعي RequestDataValueProcessor.getExtraHiddenFields (...) ) ويضيف الحقول المخفية التي تم إرجاعها مباشرة قبل علامة الإغلاق </form>
- th: مكالمات القيمة RequestDataValueProcessor.processFormFieldValue (...) لرسم القيمة التي تشير إليها ، ما لم يكن th: الحقل في نفس العلامة (في هذه الحالة th: الحقل سيحرص )
- th: يستدعي الحقل RequestDataValueProcessor.processFormFieldValue (...) لرسم قيمة الحقل الذي ينطبق عليه (أو نص العلامة إذا كان <textarea>)
لاحظ أن هناك سيناريوهات قليلة للغاية قد تحتاج فيها إلى تطبيق RequestDataValueProcessor بشكل صريح في التطبيق الخاص بك. في معظم الحالات ، سيتم استخدامه تلقائيًا بواسطة مكتبات الأمان التي تستخدمها بشفافية ، على سبيل المثال ، CSRF لـ Spring Security.11.1 بناء URIs إلى وحدات التحكم
بدءًا من الإصدار 4.1 ، يوفر
Spring القدرة على إنشاء ارتباطات إلى وحدات التحكم المشروحة مباشرةً من طرق العرض ، دون الحاجة إلى معرفة URIs التي تم تعيين وحدات التحكم هذه عليها.
في Thymeleaf ، يمكن تحقيق ذلك باستخدام التعبير
# mvc.url (...) ، والذي يسمح لك بتعيين طرق تحكم بأحرف كبيرة من فئة وحدة التحكم التي توجد فيها ، متبوعة باسم الطريقة. هذا يكافئ
الربيع المخصص
: mvcUrlx (...) تعمل في JSP.
على سبيل المثال ، من أجل:
public class ExampleController { @RequestMapping("/data") public String getData(Model model) { ... return "template" } @RequestMapping("/data") public String getDataParam(@RequestParam String type) { ... return "template" } }
التعليمة البرمجية التالية ستنشئ مراجع الأسلوب:
<a th:href="${(#mvc.url('EC#getData')).build()}">Get Data Param</a> <a th:href="${(#mvc.url('EC#getDataParam').arg(0,'internal')).build()}">Get Data Param</a>
يمكنك أن تقرأ عن هذه الآلية على
http://docs.spring.io/spring-framework/docs/4.1.2.RELEASE/spring-framework-reference/html/mvc.html#mvc-links-to-controllers- من وجهات النظر12 ربيع التكامل WebFlow
تتضمن حزم تكامل Thymeleaf + Spring التكامل مع Spring WebFlow (2.3+).
يتضمن WebFlow بعض ميزات AJAX لعرض أجزاء من الصفحة المعروضة عند تشغيل أحداث معينة (انتقالات) ، ولكي تتمكن Thymeleaf من تتبع طلبات AJAX هذه ، سنحتاج إلى استخدام تطبيق ViewResolver آخر تم تكوينه على النحو التالي:
<bean id="thymeleafViewResolver" class="org.thymeleaf.spring4.view.AjaxThymeleafViewResolver"> <property name="viewClass" value="org.thymeleaf.spring4.view.FlowAjaxThymeleafView" /> <property name="templateEngine" ref="templateEngine" /> </bean>
... ثم يمكن تكوين
ViewResolver هذا في
WebFlow ViewFactoryCreator على النحو التالي:
<bean id="mvcViewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator"> <property name="viewResolvers" ref="thymeleafViewResolver"/> </bean>
من هنا يمكنك تحديد قوالب Thymeleaf في حالة العرض الخاصة بك:
<view-state id="detail" view="bookingDetail"> ... </view-state>
في المثال أعلاه ،
bookingDetail هو قالب Thymeleaf المحدد بالطريقة المعتادة ، ويمكن فهمه لأي من محللي القوالب الذين تم تكوينهم في TemplateEngine.
12.2 مقتطفات AJAX في Spring WebFlow
لاحظ أن هذا يوضح فقط كيفية إنشاء أجزاء AJAX للاستخدام مع Spring WebFlow. إذا كنت لا تستخدم WebFlow ، فإن إنشاء وحدة تحكم Spring MVC التي تستجيب لطلب AJAX وتُرجع جزءًا من HTML بسيطًا مثل إنشاء أي وحدة تحكم أخرى تُرجع قالبًا ، مع الاستثناء الوحيد الذي من المحتمل أن ترجع جزءًا مثل " main :: المشرف "من طريقة التحكم الخاصة بك.يسمح لك WebFlow بتحديد العرض من خلال AJAX بعلامات <render> ، على سبيل المثال مثل هذا:
<view-state id="detail" view="bookingDetail"> <transition on="updateData"> <render fragments="hoteldata"/> </transition> </view-state>
يمكن أن تكون هذه الأجزاء (في هذه الحالة
hoteldata ) قائمة مفصولة بفواصل من الأجزاء
الموضحة في العلامة بعلامة
th: fragment :
<div id="data" th:fragment="hoteldata"> This is a content to be changed </div>
تذكر دائمًا أن هذه المقتطفات يجب أن تحتوي على سمة
معرّف بحيث يمكن لمكتبات Spring JavaScript التي تعمل في المستعرض استبدال العلامات.
يمكنك أيضًا تحديد علامات <render> باستخدام محددات DOM:
<view-state id = "detail" view = "bookingDetail">
/>
</view-state>
... وهذا يعني أنه لا توجد حاجة إلى
: جزء :
<div id="data"> This is a content to be changed </div>
بالنسبة للرمز الذي يشغل عملية نقل
updateData ، يبدو كما يلي:
<script type="text/javascript" th:src="@{/resources/dojo/dojo.js}"></script> <script type="text/javascript" th:src="@{/resources/spring/Spring.js}"></script> <script type="text/javascript" th:src="@{/resources/spring/Spring-Dojo.js}"></script> ... <form id="triggerform" method="post" action=""> <input type="submit" id="doUpdate" name="_eventId_updateData" value="Update now!" /> </form> <script type="text/javascript"> Spring.addDecoration( new Spring.AjaxEventDecoration({formId:'triggerform',elementId:'doUpdate',event:'onclick'})); </script>