10. المثال 08 - العلامات المرتبطة بالقوائم
يتناول المثال التالي العلامات التي تعرض القوائم. وقد سبق أن تناولناها في المثال السابق: القائمة المنسدلة، ومربعات الاختيار، وأزرار الاختيار. وسيكون نموذج الاختبار كما يلي:


10.1. مشروع NetBeans
مشروع NetBeans هو كما يلي:
![]() |
- حيث يمثل [1] الإجراء، و [2] العرض المرتبط به.
يقوم الملف [example/example.xml] بتكوين التطبيق:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="example" namespace="/example" extends="struts-default">
<action name="Form" class="example.Form">
<result name="success">/example/Form.jsp</result>
</action>
</package>
</struts>
توضح السطور 8-9 أن استدعاء عنوان URL [/example/Form.action] يُنشئ طريقة العرض [/example/Form.jsp]. وبالتالي، ستتولى الإجراء [Form] إنشاء نموذج العرض [Form.jsp].
10.2. ملف الرسائل المُترجمة
ملف الرسائل المُترجمة [messages.properties] هو كما يلي:
Form.francais=Fran\u00E7ais
Form.anglais=Anglais
Form.titre=Struts 2 - les tags \u00E0 valeurs multiples
Form.message=Struts 2 - les tags \u00E0 valeurs multiples
Form.langues=langues
Form.select1=1-select1 (multiple=false, size=1)
Form.select2=2-select2 (multiple=true, size=3)
Form.select3=3-select3 (multiple=true, size=3)
Form.select4=4-select4 (multiple=true, size=3)
Form.select5=5-select5 (multiple=true, size=3)
Form.checkboxlist1=6-checkboxlist1
Form.checkboxlist2=7-checkboxlist2
Form.checkboxlist3=8-checkboxlist3
Form.radio1=9-radio1
Form.radio2=10-radio2
Form.radio3=11-radio3
Form.submitText=Valider
Confirmation.message=Confirmation des valeurs saisies
Confirmation.champ=champ
Confirmation.valeur=valeur
Confirmation.select1=1-select1 (multiple=false, size=1)
Confirmation.select2=2-select2 (multiple=false, size=3)
Confirmation.select3=3-select3 (multiple=true, size=3)
Confirmation.select4=4-select4 (multiple=true, size=3)
Confirmation.select5=5-select5 (multiple=true, size=3)
Confirmation.checkboxlist1=6-checkboxlist1
Confirmation.checkboxlist2=7-checkboxlist2
Confirmation.checkboxlist3=8-checkboxlist3
Confirmation.radio1=9-radio1
Confirmation.radio2=10-radio2
Confirmation.radio3=11-radio3
تستخدم طريقة العرض [Form.jsp] هذه الرسائل.
10.3. الطريقة [Form.jsp]
الطريقة [Form.jsp] هي كما يلي:
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title><s:text name="Form.titre"/></title>
<s:head/>
</head>
<body background="<s:url value="/ressources/standard.jpg"/>">
<h2><s:text name="Form.message"/></h2>
<h3><s:text name="Form.langues"/></h3>
<ul>
<li>
<s:url id="url" action="Form">
<s:param name="request_locale">en</s:param>
</s:url>
<s:a href="%{url}"><s:text name="Form.anglais"/></s:a>
</li>
<li>
<s:url id="url" action="Form">
<s:param name="request_locale">fr</s:param>
</s:url>
<s:a href="%{url}"><s:text name="Form.francais"/></s:a>
</li>
</ul>
<s:form name="formulaire">
<s:select name="select1" list="{'vert','jaune','rouge'}" size="1" key="Form.select1"/>
<s:select name="select2" list="{'vert','jaune','rouge'}" size="3" key="Form.select2" multiple="true"/>
<s:select name="select3" list="#{'01':'vert(01)','02':'jaune(02)','03':'rouge(03)','04':'blanc(04)','05':'noir(05)'}" size="3" key="Form.select3" multiple="true"/>
<s:select name="select4" list="dico" size="3" key="Form.select4" multiple="true"/>
<s:select name="select5" list="couleurs" listKey="id" listValue="nom" size="3" key="Form.select5" multiple="true" />
<s:checkboxlist name="checkboxlist1" list="#{'01':'vert(01)','02':'jaune(02)','03':'rouge(03)','04':'blanc(04)','05':'noir(05)'}" key="Form.checkboxlist1"/>
<s:checkboxlist name="checkboxlist2" list="dico" key="Form.checkboxlist2"/>
<s:checkboxlist name="checkboxlist3" list="couleurs" listKey="id" listValue="nom" key="Form.checkboxlist3" />
<s:radio name="radio1" list="#{'01':'vert(01)','02':'jaune(02)','03':'rouge(03)','04':'blanc(04)','05':'noir(05)'}" key="Form.radio1"/>
<s:radio name="radio2" list="dico" key="Form.radio2"/>
<s:radio name="radio3" list="couleurs" listKey="id" listValue="nom" key="Form.radio3" />
<s:submit key="Form.submitText" name="submitText"/>
</s:form>
<hr/>
<h2><s:text name="Confirmation.message"/></h2>
<table border="1">
<tr>
<th><s:text name="Confirmation.champ"/></th>
<th><s:text name="Confirmation.valeur"/></th>
</tr>
<tr>
<td><s:text name="Form.select1"/></td>
<td><s:property value="select1"/>
</tr>
<tr>
<td><s:text name="Form.select2"/></td>
<td><s:property value="select2SelectedValues"/>
</tr>
<tr>
<td><s:text name="Form.select3"/></td>
<td><s:property value="select3SelectedValues"/>
</tr>
<tr>
<td><s:text name="Form.select4"/></td>
<td><s:property value="select4SelectedValues"/>
</tr>
<tr>
<td><s:text name="Form.select5"/></td>
<td><s:property value="select5SelectedValues"/>
</tr>
<tr>
<td><s:text name="Form.checkboxlist1"/></td>
<td><s:property value="checkboxlist1SelectedValues"/>
</tr>
<tr>
<td><s:text name="Form.checkboxlist2"/></td>
<td><s:property value="checkboxlist2SelectedValues"/>
</tr>
<tr>
<td><s:text name="Form.checkboxlist3"/></td>
<td><s:property value="checkboxlist3SelectedValues"/>
</tr>
<tr>
<td><s:text name="Form.radio1"/></td>
<td><s:property value="radio1"/>
</tr>
<tr>
<td><s:text name="Form.radio2"/></td>
<td><s:property value="radio2"/>
</tr>
<tr>
<td><s:text name="Form.radio3"/></td>
<td><s:property value="radio3"/>
</tr>
</table>
</body>
</html>
دعونا نستعرض العلامات المختلفة الخاصة بحقول الإدخال في النموذج:
- السطر 27: العلامة <s:select>:
<s:select name="select1" list="{'vert','jaune','rouge'}" size="1" key="Form.select1"/>
ستولد هذه العلامة كود HTML التالي:
قيمة السمة list هي مصفوفة من سلاسل الأحرف تُستخدم لتوليد قيم الخيارات وتسمياتها. النموذج المرتبط بها هو الحقل select1 الخاص بالإجراء [Form] التالي:
private String select1 = "jaune";
يرتبط هذا الحقل، في كل من القراءة والكتابة، بالعلامة المسماة select1. عند الكتابة، سيتم إدراج قيمة الخيار المحدد في الحقل select1. وعند القراءة، تُستخدم قيمة الحقل select1 لتحديد الخيار المحدد. هنا، تُستخدم القيمة jaune للحقل select1 لاختيار الخيار الخاص بالعلامة select1 الذي قيمته «أصفر». ولهذا السبب، في السطر 3، يتم اختيار الخيار.
- السطر 28
<s:select name="select2" list="{'vert','jaune','rouge'}" size="3" key="Form.select2" multiple="true"/>
لا يوجد فرق جوهري مع العلامة الموجودة في السطر 27، باستثناء أن التحديد هنا متعدد. وبالتالي، فإن القيمة المرسلة هي مصفوفة من القيم، وهي قيم الخيارات المحددة. الحقل select2 الخاص بالإجراء المرتبط بالنموذج هو كما يلي:
private String[] select2 = new String[]{"vert", "rouge"};
إنه بالفعل مصفوفة. تُستخدم قيمته الأولية لاختيار الخيارات التي توجد قيمها في المصفوفة.
- السطر 29
<s:select name="select3" list="#{'01':'vert(01)','02':'jaune(02)','03':'rouge(03)','04':'blanc(04)','05':'noir(05)'}" size="3" key="Form.select3" multiple="true"/>
هنا، قيمة السمة list هي قاموس تُستخدم مفاتيحه كقيم للخيارات، بينما تُستخدم القيم المرتبطة بها كعناوين للخيارات. رمز HTML الذي تم إنشاؤه هو كما يلي:
الحقل المرتبط في الإجراء هو كما يلي:
private String[] select3 = new String[]{"01", "03"};
لدينا مرة أخرى مصفوفة من القيم لأن العلامة المرتبطة بها هي علامة متعددة الخيارات. تشرح القيم الأولية للمصفوفة سبب تحديد خيارات السطرين 2 و4 مسبقًا.
- السطر 30
<s:select name="select4" list="dico" size="3" key="Form.select4" multiple="true"/>
هنا، سيتم توفير خيارات القائمة بواسطة نموذج العرض، وهو النموذج الذي يشكل هنا جزءًا من الإجراء [Form]:
private HashMap<String, String> dico = new HashMap<String, String>();
ستكون مفاتيح القاموس dico هي قيم الخيارات. وستكون قيم القاموس dico هي تسميات الخيارات. والحقل select4 الخاص بالإجراء هو كما يلي:
private String[] select4 = new String[]{"1", "3"};
وهو عبارة عن مصفوفة قيم ستستقبل القيم التي يتم إرسالها بواسطة العلامة select4.
- السطر 31
<s:select name="select5" list="couleurs" listKey="id" listValue="nom" size="3" key="Form.select5" multiple="true" />
يتم إنشاء قائمة الخيارات بواسطة الحقل couleurs المحدد بواسطة السمة list. يتم تعريف الحقل couleurs الخاص بالإجراء [Form] على النحو التالي:
private Couleur[] couleurs;
يتم تعريف الفئة [Couleur] على النحو التالي:
package example;
public class Couleur {
// الحقول
private String id;
private String nom;
// منشئ
public Couleur(){
}
// دالات الاسترجاع والتعيين
...
}
وتحتوي على حقلين باسم id و nom. في العلامة select5، لدينا listKey="id" و listValue="nom". وهذا يعني أن الحقل id كقيمة لخيار ما، بينما سيُستخدم الحقل nom كعنوان. تجدر الإشارة إلى أن قيم الخيارات هي التي يتم تسجيلها. وسيتم تسجيلها في الحقل التالي select5:
private String[] select5 = new String[]{"1", "3"};
- السطر 32
<s:checkboxlist name="checkboxlist1" list="#{'01':'vert(01)','02':'jaune(02)','03':'rouge(03)','04':'blanc(04)','05':'noir(05)'}" key="Form.checkboxlist1"/>
ستقوم هذه العلامة بإنشاء كود HTML التالي:
تحمل جميع خانات الاختيار الاسم checkboxlist1. ونظرًا لإمكانية تحديد كل منها، يمكن إرسال عدة معلمات checkboxlist1. لذا، يجب أن يكون الحقل checkboxlist1 في النموذج من نوع الجدول. السمة list في السطر 22 عبارة عن قاموس تُنشئ مفاتيحه سمات value لمربعات الاختيار، بينما تُنشئ قيمه العبارات المكتوبة في هذه المربعات نفسها. الحقل checkboxlist1 الخاص بالإجراء [Form] هو كما يلي:
private String[] checkboxlist1 = new String[]{"01", "03"};
- السطر 33
<s:checkboxlist name="checkboxlist2" list="dico" key="Form.checkboxlist2"/>
تعمل هذه العلامة مثل العلامة select4 التي تمت دراستها سابقًا. والحقل المرتبط بها في الإجراء هو كما يلي:
private String[] checkboxlist2 = new String[]{"1", "3"};
- السطر 34
<s:checkboxlist name="checkboxlist3" list="couleurs" listKey="id" listValue="nom" key="Form.checkboxlist3" />
تعمل هذه العلامة مثل العلامة select5 التي تمت دراستها سابقًا. الحقل checkboxlist3 المرتبط بالإجراء هو التالي:
private String[] checkboxlist3 = new String[]{"1", "3"};
- السطر 35
<s:radio name="radio1" list="#{'01':'vert(01)','02':'jaune(02)','03':'rouge(03)','04':'blanc(04)','05':'noir(05)'}" key="Form.radio1"/>
تعمل هذه العلامة من حيث المبدأ مثل العلامة select3 التي رأيناها سابقًا. رمز HTML الذي تم إنشاؤه هو التالي:
تحمل جميع العلامات الاسم نفسه radio1. يمكن تحديد زر اختيار واحد فقط. وبالتالي، يتم إرسال قيمة واحدة فقط، وهي قيمة زر الاختيار المحدد. تُستخدم مفاتيح القاموس list لتوليد سمات أزرار الاختيار value، بينما تُستخدم قيم القاموس لتوليد التسميات المرتبطة بهذه الأزرار. الحقل radio1 المرتبط بالإجراء هو التالي:
private String radio1="01";
- السطر 36
<s:radio name="radio2" list="dico" key="Form.radio2"/>
تعمل هذه العلامة من حيث المبدأ مثل العلامة select4. الحقل radio2 المرتبط بالإجراء هو التالي:
private String radio2="1";
- السطر 37
<s:radio name="radio3" list="couleurs" listKey="id" listValue="nom" key="Form.radio3" />
تعمل هذه العلامة من حيث المبدأ مثل العلامة select5. الحقل radio3 المرتبط بالإجراء هو التالي:
private String radio3="1";
هذا هو الجزء saisie من النموذج. هناك أيضًا جزء confirmation مشابه للجزء الموجود في النموذج في المثال السابق: فهو يؤكد القيم التي تم إرسالها. لن نعلق إلا على الأسطر التالية:
<tr>
<td><s:text name="Form.select2"/></td>
<td><s:property value="select2SelectedValues"/>
</tr>
والتي تتطابق بصريًا مع ما يلي:
![]()
النص الموجود في الخلية اليسرى مأخوذ من الملف [messages.properties]:
Form.select2=2-select2 (multiple=true, size=3)
تم إنشاء النص الموجود في الخلية اليمنى بواسطة الطريقة getSelect2SelectedValues التابعة للإجراء [Form]:
// القيم المحددة في القوائم المنسدلة
public String getSelect2SelectedValues() {
return getArrayValue(select2);
}
// الأساليب المساعدة
public String getArrayValue(String[] values) {
String result = "";
for (String value : values) {
result += " " + value;
}
return result;
}
تقوم الطريقة getSelect2SelectedValues بتحويل قيم الجدول select2 إلى سلسلة أحرف.
10.4. الإجراء [Form]
عند شرح العرض [Form.jsp]، قمنا بعرض حقول الإجراء [Form] المرتبط به. رمز الإجراء [Form] هو كما يلي:
package example;
import com.opensymphony.xwork2.ActionSupport;
import java.util.HashMap;
public class Form extends ActionSupport {
// حقول النموذج
private String select1 = "jaune";
private String[] select2 = new String[]{"vert", "rouge"};
private String[] select3 = new String[]{"01", "03"};
private String[] select4 = new String[]{"1", "3"};
private String[] select5 = new String[]{"1", "3"};
private HashMap<String, String> dico = new HashMap<String, String>();
private Couleur[] couleurs;
private String[] checkboxlist1 = new String[]{"01", "03"};
private String[] checkboxlist2 = new String[]{"1", "3"};
private String[] checkboxlist3 = new String[]{"1", "3"};
private String radio1="01";
private String radio2="1";
private String radio3="1";
private String submitText;
// منشئ بدون معلمات
public Form() {
// تهيئة قاموس الألوان
dico.put("1", "vert(1)");
dico.put("2", "jaune(2)");
dico.put("3", "bleu(3)");
dico.put("4", "rouge(4)");
dico.put("5", "blanc(5)");
// تهيئة مصفوفة كائنات اللون
couleurs = new Couleur[dico.size()];
int i = 0;
for (String key : dico.keySet()) {
couleurs[i] = new Couleur();
couleurs[i].setId(key);
couleurs[i].setNom(dico.get(key));
i++;
}
}
// القيم المحددة في القوائم المنسدلة
public String getSelect2SelectedValues() {
return getArrayValue(select2);
}
public String getSelect3SelectedValues() {
return getArrayValue(select3);
}
public String getSelect4SelectedValues() {
return getArrayValue(select4);
}
public String getSelect5SelectedValues() {
return getArrayValue(select5);
}
public String getCheckboxlist1SelectedValues() {
return getArrayValue(checkboxlist1);
}
public String getCheckboxlist2SelectedValues() {
return getArrayValue(checkboxlist2);
}
public String getCheckboxlist3SelectedValues() {
return getArrayValue(checkboxlist3);
}
// طرق مساعدة
public String getArrayValue(String[] values) {
String result = "";
for (String value : values) {
result += " " + value;
}
return result;
}
// أدوات الاسترجاع والتعيين
...
}
لا توجد طريقة execute في هذه العملية. وبالتالي، يتم تنفيذ الطريقة execute التابعة للفئة الأم ActionSupport. ولا تقوم هذه الطريقة بأي شيء، بل تكتفي بإرجاع مفتاح التنقل SUCCESS.
10.5. الاختبارات
ندعو القارئ إلى اختبار التطبيق [exemple-08].
