Frage

Ich habe eine Liste der Bohnen, von denen jede eine Eigenschaft hat, die sich eine Liste der E-Mail-Adressen ist.

<c:forEach items="${upcomingSchedule}" var="conf">
    <div class='scheduled' title="${conf.subject}" id="scheduled<c:out value="${conf.id}"/>">
    ...
    </div>
</c:forEach>

Dies macht eine <div> pro Bohne in der Liste.

Für den sublist, was ich möchte in der Lage sein zu tun, ist jeden der Einträge in der Liste verketten einen einzelnen String zu bilden, als Teil des <div> des title Attributs angezeigt werden. Warum? Weil wir eine Javascript-Bibliothek (Mootools) sind mit dieser <div> in ein schwebendes Werkzeugspitze zu drehen, und die Bibliothek schaltet den title in den Text des Tooltips.

Also, wenn ${conf.subject} „Subject“ war, schließlich würde ich die title der <div> gerne sein „Subject: blah@blah.com, blah2@blah2.com usw.“, enthält alle E-Mail-Adressen von die Unterliste.

Wie kann ich diese mit JSP EL tun? Ich versuche davon ab, scriptlet Blöcke in der JSP-Datei zu.

War es hilfreich?

Lösung 2

einen etwas schmutzig Weg gefunden, dies zu tun:

<c:forEach items="${upcomingSchedule}" var="conf">
    <c:set var="title" value="${conf.subject}: "/>
    <c:forEach items="${conf.invitees}" var="invitee">
        <c:set var="title" value="${title} ${invitee}, "/>
    </c:forEach>
    <div class='scheduled' title="${title}" id="scheduled<c:out value="${conf.id}"/>">
    ...
    </div>
</c:forEach>

I <c:set> nur wiederholt verwenden, seinen eigenen Wert verweisen, um die Strings zu anhängen / verketten.

Andere Tipps

Die „saubere“ Art und Weise, dies zu tun wäre, eine Funktion zu verwenden. Da die JSTL join Funktion auf einem Collection nicht funktionieren, können Sie Ihre eigenen, ohne zu viel Mühe, schreiben und sie alle über dem Platz statt Ausschneiden und Einfügen eines großen Teil der Schleife Code wiederverwenden.

Sie müssen die Funktionsimplementierung und eine TLD Ihre Web-Anwendung zu informieren, wo sie zu finden. Setzen Sie diese zusammen in einer JAR-und-Drop in Ihr WEB-INF / lib.

Hier ist ein Überblick:

com / x / taglib / core / StringUtil.java

package com.x.taglib.core;

public class StringUtil {

  public static String join(Iterable<?> elements, CharSequence separator) {
    StringBuilder buf = new StringBuilder();
    if (elements != null) {
      if (separator == null)
        separator = " ";
      for (Object o : elements) {
        if (buf.length() > 0)
          buf.append(separator);
        buf.append(o);
      }
    }
    return buf.toString();
  }

}

META-INF / x-c.tld:

<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0">
  <tlib-version>1.0</tlib-version>
  <short-name>x-c</short-name>
  <uri>http://dev.x.com/taglib/core/1.0</uri>
  <function>
    <description>Join elements of an Iterable into a string.</description>
    <display-name>Join</display-name>
    <name>join</name>
    <function-class>com.x.taglib.core.StringUtil</function-class>
    <function-signature>java.lang.String join(java.lang.Iterable, java.lang.CharSequence)</function-signature>
  </function>
</taglib>

Während die TLD ein wenig ausführlich sind, zu wissen, Ihren Weg ist eine gute Fähigkeit für jeden Entwickler mit JSP arbeiten. Und da Sie einen Standard wie JSP für die Präsentation ausgewählt haben, gibt es eine gute Chance, dass Sie Tools, die Ihnen helfen werden.

Dieser Ansatz hat viele Vorteile gegenüber der Alternative von mehreren Verfahren auf das zugrunde liegende Modell hinzufügen. Diese Funktion kann einmal geschrieben werden, und in jedem Projekt wiederverwendet werden. Es arbeitet mit einer Closed-Source-Drittanbieter-Bibliothek. Verschiedene Trennzeichen können in unterschiedlichen Kontexten unterstützt werden, ohne dass ein Modell API mit einer neuen Methode für jede verschmutzen.

Am wichtigsten ist, es unterstützt eine Trennung von Ansicht und Modellreglerentwicklungsrollen. Aufgaben in diesen beiden Bereichen werden häufig von verschiedenen Personen zu verschiedenen Zeiten durchgeführt. Die Aufrechterhaltung eine lose Kopplung zwischen diesen Schichten minimiert die Komplexität und Wartungskosten. Wenn selbst eine triviale Änderung ein anderes Trennzeichen in der Präsentation ein Programmierer wie unter Verwendung erfordert eine Bibliothek zu ändern, haben Sie eine sehr teure und umständliche System.

Die StringUtil Klasse ist das gleiche, ob sein als EL-Funktion ausgesetzt oder nicht. Die einzige „extra“ notwendig ist, die TLD, die trivial ist; ein Werkzeug, könnte es leicht erzeugen.

Könnten Sie diese nutzen? Scheint, wie es ein Array statt einer Liste will ..

${fn:join(array, ";")}

http: // java .sun.com / products / jsp / jstl / 1.1 / docs / tlddocs / fn / join.fn.html

Wenn Ihr sublist ist ein Arraylist und Sie dies tun:

<div class='scheduled' title="${conf.subject}: ${conf.invitees}" id="scheduled${conf.id}">

Sie erhalten fast, was Sie brauchen.

Der einzige Unterschied ist, dass der Titel sein wird: "Subject: [. Blah@blah.com, blah2@blah2.com, etc]".

Vielleicht kann für Sie gut genug sein.

Ich denke, das ist, was Sie wollen:

<c:forEach var="tab" items="${tabs}">
 <c:set var="tabAttrs" value='${tabAttrs} ${tab.key}="${tab.value}"'/>
</c:forEach>

In diesem Fall hatte ich eine hashmap mit Tab-ID (Schlüssel) und URL (Wert). Die tabAttrs Variable wird nicht vor diesem eingestellt. So setzt er nur den Wert auf den aktuellen Wert von tabAttrs ( ‚‘ starten) plus dem Schlüssel / Wert-Ausdruck.

Setzen Sie einfach die Zeichenfolge byside var vom Server, wie folgt aus:

<c:forEach items="${upcomingSchedule}" var="conf">
    <div class='scheduled' title="${conf.subject}" 

         id="scheduled${conf.id}">

    ...
    </div>
</c:forEach>

Zu spät !!!

Die Art und Weise Tag-Bibliotheken implementiert werden scheint erheblich weitergezogen zu haben, da diese Antwort ursprünglich geschrieben wurde, so landete ich einige drastischen Änderungen auf die Dinge zum Laufen zu bringen. Mein Endergebnis war:

Tag Library-Datei:

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd">
  <tlib-version>1.0</tlib-version>
  <short-name>string_util</short-name>
  <uri>/WEB-INF/tlds/string_util</uri>
  <info>String Utilities</info>
  <tag>
    <name>join</name>
    <info>Join the contents of any iterable using a separator</info>
    <tag-class>XXX.taglib.JoinObjects</tag-class>
    <body-content>tagdependent</body-content>
    <attribute>
      <name>iterable</name>
      <required>true</required>
      <rtexprvalue>true</rtexprvalue>
      <type>java.lang.Iterable</type>
    </attribute>
    <attribute>
      <name>separator</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
      <type>java.lang.String</type>
    </attribute>
  </tag>

  <tag>
    <name>joinints</name>
    <info>Join the contents of an integer array using a separator</info>
    <tag-class>XXX.taglib.JoinInts</tag-class>
    <body-content>tagdependent</body-content>
    <attribute>
      <name>integers</name>
      <required>true</required>
      <rtexprvalue>true</rtexprvalue>
      <type>java.lang.Integer[]</type>
    </attribute>
    <attribute>
      <name>separator</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
      <type>java.lang.String</type>
    </attribute>
  </tag>
</taglib>

JoinInts.java

public class JoinInts extends TagSupport {

    int[] integers;
    String separator = ",";

    @Override
    public int doStartTag() throws JspException {
        if (integers != null) {
            StringBuilder buf = new StringBuilder();
            if (separator == null) {
                separator = " ";
            }
            for (int i: integers) {
                if (buf.length() > 0) {
                    buf.append(separator);
                }
                buf.append(i);
            }
            try {
                pageContext.getOut().print(buf);
            } catch (IOException ex) {
                Logger.getLogger(JoinInts.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return SKIP_BODY;
    }

    @Override
    public int doEndTag() throws JspException {
        return EVAL_PAGE;
    }

    public int[] getIntegers() {
        return integers;
    }

    public void setIntegers(int[] integers) {
        this.integers = integers;
    }

    public String getSeparator() {
        return separator;
    }

    public void setSeparator(String separator) {
        this.separator = separator;
    }
}

Um es zu verwenden:

<%@ taglib prefix="su" uri="/WEB-INF/tlds/string_util.tld" %>

[new Date(${row.key}), <su:joinints integers="${row.value}" separator="," />],

Sie können den 3.0 Stream-API EL verwenden. Wenn Sie zum Beispiel eine Liste von Strings,

<div>${stringList.stream().reduce(",", (n,p)->p.concat(n))}</div>

Falls Sie eine Liste von Objekten für ex. Person (Vorname, Nachname), und Sie wollen nur eine Eigenschaft von ihnen verketten (ex Vornamen) können Sie Karte verwenden,

<div>${personList.stream().map(p->p.getFirstName()).reduce(",", (n,p)->p.concat(n))}</div>

In Ihrem Fall, dass Sie so etwas nutzen könnten (entfernen Sie die letzte ‚‘ auch)

<c:forEach items="${upcomingSchedule}" var="conf">
    <c:set var="separator" value=","/>
    <c:set var="titleFront" value="${conf.subject}: "/>
    <c:set var="titleEnd" value="${conf.invitees.stream().reduce(separator, (n,p)->p.concat(n))}"/>
    <div class='scheduled' title="${titleFront} ${titleEnd.isEmpty() ? "" : titleEnd.substring(0, titleEnd.length()-1)}" id="scheduled<c:out value="${conf.id}"/>">
    ...
    </div>
</c:forEach>

Seien Sie vorsichtig! Die EL 3.0 Stream-API wurde abgeschlossen, bevor die Java 8-Stream API und es ist anders als das. Sie können nicht beide apis SUNC, weil sie die Abwärtskompatibilität brechen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top