mardi 30 août 2011

Ajax, Struts2 et JSP





Notre page de paramètres est prête, sauf que le look'n feel n'est pas au rendez-vous. L'idée étant d'avoir un tableau (joli) qui permet de filtrer, ajouter, trier des enregistrements de manière simple.


En cherchant un peu, voici sur quoi je suis tombé : 


http://code.google.com/p/struts2-jquery/wiki/EditGrid#Simple_Edit

Plugin JQuery (Ajax) compatible Struts2, et plus particulièrement cette EditGrid qui fait tout toute seule (enfin presque).


Mise en place : 


 1) Tout d'abord, il faut tirer avec Maven la dépendance sur ce Plugin, direction fichier pom :


<dependency>
<groupId>com.jgeppert.struts2.jquery</groupId>
<artifactId>struts2-jquery-grid-plugin</artifactId>
<version>3.1.1</version>
<type>jar</type>
<scope>compile</scope>
</dependency>


 2) Import dans le Head des JSP des tags nécessaires au chargement de JQuery et de ce plugin.


<sj:head locale="fr" jqueryui="true" defaultIndicator="myDefaultIndicator" jquerytheme="ui-darkness"/>



3) Ajout du composant Grid dans la JSP de base appelée parameter.jsp soumise sur parameterAction


   <s:url id="remoteurl" action="parameterJQueryAction"/>
    <s:url id="editurl" action="parameterEditAction"/>
    <sjg:grid
    id="gridedittable"
   
    dataType="json"
    href="%{remoteurl}"
    pager="true"
    navigator="true"
   
    navigatorSearchOptions="{sopt:['eq','ne','lt','gt']}"
    navigatorAddOptions="{height:200,width:400,reloadAfterSubmit:true}"
    navigatorEditOptions="{height:200,width:400,reloadAfterSubmit:false}"
    navigatorEdit="false"
    navigatorView="false"
    navigatorDelete="true"
    navigatorDeleteOptions="{height:200,width:400,reloadAfterSubmit:true}"
    navigatorExtraButtons="{
    seperator: { 
    title : 'seperator'  
    }, 
    hide : { 
    title : 'Show/Hide', 
    icon: 'ui-icon-wrench', 
    topic: 'showcolumns'
    },
    alert : { 
    title : 'Alert', 
    onclick: function(){ alert('Grid Button clicked!') }
    }
    }"
    gridModel="gridModel"
    rowList="10,15,20"
    rowNum="10"
    editurl="%{editurl}"
    editinline="true"
    onSelectRowTopics="rowselect"
    onEditInlineSuccessTopics="oneditsuccess"
    viewrecords="true"
    >
    <sjg:gridColumn name="id" index="id" title="ID" width="30" formatter="integer" editable="false" sortable="false" search="true" searchoptions="{sopt:['eq','ne','lt','gt']}"/>
    <sjg:gridColumn name="cle" index="cle" title="Cle" width="250" editable="true" edittype="text" sortable="true" search="false"/>
    <sjg:gridColumn name="valeur" index="valeur" width="250" editable="true" edittype="text" title="Valeur" sortable="false" hidden="false"/>
    <sjg:gridColumn name="commentaire" index="commentaire" editable="true" edittype="text" width="250" title="Commentaire" sortable="false" hidden="false"/>
    </sjg:grid>


En bleu, l'action qui permet de peupler la table et renvoyer sur parameter.jsp,
En vert, l'action qui permet le CRUD sur les objets (Create, Retrieve, Update, Delete)

4) Config struts, on retrouve nos 3 actions : 

      A) La première consiste à afficher la page des paramètres (depuis le menu)



                <action name="parameterAction" class="parameterAction">
<result name="success">WEB-INF/jsp/panel/parameter.jsp</result>
</action>


      B) La seconde permet de peupler notre grille, elle est peuplée via une requête AJAX.


<action name="parameterJQueryAction" class="parameterAction">
<result name="success" type="json" />
</action>


     C) La dernière permet de réaliser le CRUD


<action name="parameterEditAction" class="parameterEditAction">
<result name="success">WEB-INF/jsp/panel/parameter.jsp</result>
</action>

5) Détail de l'action parameterAction


package com.homeautomate.ihm.actions;


import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.interceptor.SessionAware;


import com.homeautomate.bean.parameter.Parameter;


public class ParameterAction extends AbstractAction implements SessionAware {


private static final long serialVersionUID = 5078264277068533593L;
private static final Log log = LogFactory.getLog(JQueryAction.class);


private List<Parameter> gridModel;
private List<Parameter> myParameters;
private Integer rows = 0;
private Integer page = 0;
private Integer total = 0;
private Integer record = 0;
private String sord;
private String sidx;
private String searchField;
private String searchString;
private String searchOper;
private boolean loadonce = false;
private Map<String, Object> session;


@Override
public String execute() {
log.debug("Page " + getPage() + " Rows " + getRows()
+ " Sorting Order " + getSord() + " Index Row :" + getSidx());
log.debug("Search :" + searchField + " " + searchOper + " "
+ searchString);


Object list = session.get("mylist");
if (list != null) {
myParameters = (List<Parameter>) list;
} else {
log.debug("Build new List");
myParameters = getParameterManager().getDao().list(Parameter.class);
}


if (getSord() != null && getSord().equalsIgnoreCase("asc")) {
Collections.sort(myParameters);
}
if (getSord() != null && getSord().equalsIgnoreCase("desc")) {
Collections.sort(myParameters);
Collections.reverse(myParameters);
}


setRecord(myParameters.size());


int to = (getRows() * getPage());
int from = to - getRows();


if (to > getRecord())
to = getRecord();


if (loadonce) {
setGridModel(myParameters);
} else {
System.out.println(searchString);
if (searchString != null && searchOper != null) {
try {
int id = Integer.parseInt(searchString);
if (searchOper.equalsIgnoreCase("eq")) {
log.debug("search id equals " + id);
List<Parameter> cList = new ArrayList<Parameter>();
cList.add(getParameterManager().getDao().findById(
Parameter.class, id));
setGridModel(cList);
} else if (searchOper.equalsIgnoreCase("ne")) {
log.debug("search id not " + id);
setGridModel(getParameterManager().getDao().findByQbe(
null));
} else if (searchOper.equalsIgnoreCase("lt")) {
log.debug("search id lesser then " + id);
setGridModel(getParameterManager().getDao().findByQbe(
null));
} else if (searchOper.equalsIgnoreCase("gt")) {
log.debug("search id greater then " + id);
setGridModel(getParameterManager().getDao().findByQbe(
null));
}
} catch (NumberFormatException e) {
searchString = null;
}


} else {
setGridModel(getParameterManager().getDao().list(
Parameter.class));
}
}


setTotal((int) Math.ceil((double) getRecord() / (double) getRows()));


session.put("mylist", myParameters);


return SUCCESS;
}


public String getJSON() {
return execute();
}


/**
* @return how many rows we want to have into the grid
*/
public Integer getRows() {
return rows;
}


/**
* @param rows
*            how many rows we want to have into the grid
*/
public void setRows(Integer rows) {
this.rows = rows;
}


/**
* @return current page of the query
*/
public Integer getPage() {
return page;
}


/**
* @param page
*            current page of the query
*/
public void setPage(Integer page) {
this.page = page;
}


/**
* @return total pages for the query
*/
public Integer getTotal() {
return total;
}


/**
* @param total
*            total pages for the query
*/
public void setTotal(Integer total) {
this.total = total;
}


/**
* @return total number of records for the query. e.g. select count(*) from
*         table
*/
public Integer getRecord() {
return record;
}


/**
* @param record
*            total number of records for the query. e.g. select count(*)
*            from table
*/
public void setRecord(Integer record) {


this.record = record;


if (this.record > 0 && this.rows > 0) {
this.total = (int) Math.ceil((double) this.record
/ (double) this.rows);
} else {
this.total = 0;
}
}


/**
* @return an collection that contains the actual data
*/
public List<Parameter> getGridModel() {
return gridModel;
}


/**
* @param gridModel
*            an collection that contains the actual data
*/
public void setGridModel(List<Parameter> gridModel) {
this.gridModel = gridModel;
}


/**
* @return sorting order
*/
public String getSord() {
return sord;
}


/**
* @param sord
*            sorting order
*/
public void setSord(String sord) {
this.sord = sord;
}


/**
* @return get index row - i.e. user click to sort.
*/
public String getSidx() {
return sidx;
}


/**
* @param sidx
*            get index row - i.e. user click to sort.
*/
public void setSidx(String sidx) {
this.sidx = sidx;
}


public void setSearchField(String searchField) {
this.searchField = searchField;
}


public void setSearchString(String searchString) {
this.searchString = searchString;
}


public void setSearchOper(String searchOper) {
this.searchOper = searchOper;
}


public void setLoadonce(boolean loadonce) {
this.loadonce = loadonce;
}


public void setSession(Map<String, Object> session) {
this.session = session;
}


}

5) Détail de l'action parameterEditAction

package com.homeautomate.ihm.actions;

import com.homeautomate.bean.parameter.Parameter;
import com.homeautomate.dao.IParameterDao;

public class ParameterEditAction extends AbstractAction {

/**
*/
private static final long serialVersionUID = -7217313678052619367L;

private String oper;
private String id;
private String cle;
private String valeur;
private String commentaire;
private IParameterDao parameterDao;

@Override
public String execute() throws Exception {
Parameter parameter;
if (oper.equalsIgnoreCase("add")) {
parameter = new Parameter();
parameter.setCle(cle);
parameter.setCommentaire(commentaire);
parameter.setValeur(valeur);
parameterDao.save(parameter);
} else if (oper.equalsIgnoreCase("edit")) {
parameter = parameterDao.findById(Parameter.class,
Integer.parseInt(id));
parameter.setCle(cle);
parameter.setCommentaire(commentaire);
parameter.setValeur(valeur);
parameterDao.update(parameter);
} else if (oper.equalsIgnoreCase("del")) {
parameter = parameterDao.findById(Parameter.class,
Integer.parseInt(id));
parameterDao.delete(parameter);
}
return SUCCESS;
}

public IParameterDao getParameterDao() {
return parameterDao;
}

public void setParameterDao(IParameterDao parameterDao) {
this.parameterDao = parameterDao;
}

public String getOper() {
return oper;
}

public void setOper(String oper) {
this.oper = oper;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getCle() {
return cle;
}

public void setCle(String cle) {
this.cle = cle;
}

public String getValeur() {
return valeur;
}

public void setValeur(String valeur) {
this.valeur = valeur;
}

public String getCommentaire() {
return commentaire;
}

public void setCommentaire(String commentaire) {
this.commentaire = commentaire;
}
}


On va donc créer 2 classes Actions pour tous les objets persistés de notre application (Au moins pour ceux à modifier et afficher sous format tableau)

Au passage, d'autres thèmes sont dispos, il suffit de les modifier dans le tag du Head.

Aperçus : 





Aucun commentaire:

Enregistrer un commentaire