0

I have a JSP where I am reading some values dynamically. Based on number of values I receive I want to add fields dynamically and a user can add more fields in same sequence if they want.

I am stuck and I can't work out how to add values in the fields dynamically loaded at startup.

<fieldset id="statusETA" name="statusETA"></fieldset> </br>
                    <script type="text/javascript">
                            $(document).ready(function() {
                                $("#add").click(function() {
                                    var lastField = $("#statusETA div:last");
                                    var intId = (lastField && lastField.length && lastField.data("idx") + 1) || 1;
                                    var fieldWrapper = $("<div class=\"fieldwrapper\" id=\"field" + intId + "\"/>");
                                    fieldWrapper.data("idx", intId);
                                    var fName = $("<input type=\"text\" class=\"fieldname\" name=\"status\"/>");
                                    var fType = $("<input type=\"date\" name=\"eta\"/>");
                                    var removeButton = $("<input type=\"button\" class=\"remove\" value=\"-\" />");
                                    removeButton.click(function() {
                                        $(this).parent().remove();
                                    });
                                    fieldWrapper.append(fName);
                                    fieldWrapper.append(fType);
                                    fieldWrapper.append(removeButton);
                                    $("#statusETA").append(fieldWrapper);
                                });
                                
                                
                               
                            });
                    </SCRIPT>

I want to set values in status (input field) and eta (date field) which I'll retrieve from a request variable.

Any help is really appreciated.

Anu
  • 1
  • 2
  • 1
    I don't have much experience in JSP, but from what I understand you may be able to skip using jQuery to insert the fields altogether if you just place the [JSP values directly into the page](https://stackoverflow.com/questions/33183108/how-to-print-a-java-string-in-a-jsp-file) as the value property of the input. – Chase Ingebritson Apr 17 '21 at 07:50
  • 1
    Like this: Put `` in your HTML. – connexo Apr 17 '21 at 07:53
  • OK so nice for making your question clearer. Now you've edited out all the JSP code. So much for time passed trying to answer your initial question. It would have been nice if you'd thought of it before initially posting... – julien.giband Apr 17 '21 at 09:47
  • Thanks everyone for your help guys, specially to Julien. I will try your advise. – Anu Apr 17 '21 at 10:11

1 Answers1

0

There is so much wrong with your code that it's hard to tell what you're trying to achieve here. At first glance :

  • Please describe your goal and issue in more readable terms. We're not in your head
  • Please indent and format your code correctly so we can read it easily.
  • Don't use scriptlet tags is JSPs (those <%...%> things are deprecated since at least 2009). You should look into JSTL/el
  • You should be generating your initial HTML entirely from JSP, and then offer the user a way to append some fields using javacript, maybe by making some kind of HTML template (invisible) with JSP and then duplicate it as needed

One solution here:

Java file DataFilter.java

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

@WebFilter(urlPatterns = "/data.jsp")
public class DataFilter implements Filter {

    @Override
    public void init(FilterConfig arg0) throws ServletException { }

    @Override
    public void destroy() { }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        
        String[] status = {"status1", "status2", "status3"};
        String[] eta = {"2021-05-01", "2021-05-02", "2021-05-03"};
        
        req.setAttribute("status", status);
        req.setAttribute("eta", eta);
        
        chain.doFilter(req, res);
    }

}

JSP file data.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>

<html>

    <head>
        <meta charset="UTF-8">
        <title>Tomcat test</title>
        
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <script type="text/javascript">
            $(_e => {
                const fields = $('.fields');
                
                let lastEntryNum = fields.find('.fieldWrapper').length;
                
                addRemoveHandler(fields.find('button.remove'));
                
                $('#adder-form').on('submit', e=> {
                    e.preventDefault();
                    const jqfrm = $(e.target).closest('form');
                    const frm = jqfrm[0];
                    const template = $('#field-row-template .field-row').clone();
                    template.prop('id', template.prop('id') + (++lastEntryNum));
                    template.find('*[name="status"]').val(frm.status.value);
                    template.find('*[name="eta"]').val(frm.eta.value);
                    const remBut = template.find('button.remove');
                    remBut.value = lastEntryNum;
                    fields.append(template);
                    addRemoveHandler(remBut);
                    frm.reset();
                });
                
                function addRemoveHandler(jQButton) {
                    jQButton.on('click', e => {
                        e.preventDefault();
                        $(e.target).closest('.fieldwrapper').remove();
                    });
                }
            });
        </script>
    </head>
    
    <body>
    
        <main>
            <div class="fields">
                <h5>Data:</h5>
                <c:forEach items="${requestScope.status}" varStatus="fstat" var="curStatus">
                    <c:set var="curEta" value="${requestScope.eta[fstat.index]}" />
                    <div class="fieldwrapper" id="field-${fstat.index}">
                        <input type="text" class="fieldname" name="status" value="<c:out value="${curStatus}" />" />
                        <input type="date" name="eta" value="${curEta}" />
                        <button type="button" class="remove" name="remove" value="${fstat.index}">-</button>
                    </div>
                </c:forEach>
            </div>
            <form name="adder" id="adder-form">
                <h5>Add row:</h5>
                <input type="text" class="fieldname" name="status" />
                <input type="date" name="eta" />
                <button type="submit" name="add">Add</button>
            </form>
        </main>
        
        <template id="field-row-template">
            <div class="field-row">
                <div class="fieldwrapper" id="field-">
                    <input type="text" class="fieldname" name="status" required="required" />
                    <input type="date" name="eta" required="required" />
                    <button type="button" class="remove" name="remove" value="${fstat.index}">-</button>
                </div>
            </div>
        </template>
        
    </body>
    
</html>

On a side note, if you have "eta" dates matching each "status" string, your data would be better organized in a LinkedHashMap, that would match one ETA date for one status string, preserving insertion order.

It would make your jstl easyier as you could get the ETA for each status in a loop like:

<c:forEach items="${requestScope.dataMap}" varStatus="fstat" var="entry">
    <div class="fieldwrapper" id="field-${fstat.index}">
        <input type="text" class="fieldname" name="status" value="<c:out value="${entry.key}" />" />
        <input type="date" name="eta" value="${entry.value}" />
        <button type="button" class="remove" name="remove" value="${fstat.index}">-</button>
    </div>
</c:forEach>
julien.giband
  • 2,467
  • 1
  • 12
  • 19