简体   繁体   中英

jQuery - Datepicker not populating for hashmap date fields

I'm attempting to use the jQuery datepicker function to populate date fields that are part of an object set in a hashmap.

We're using STRUTS 1 to map our form data - and for most of our data, this is sufficient.

I've already checked and written these fields out previously so that they can be populated by manually entering the date, now I want to add the jQuery datepicker to allow the user to select a date from a pop-up calendar. I'm using Chrome. Code snippet below.

    <script>
    $(function() {
        $( ".datePick").datepicker({
          dateFormat: 'mm/dd/yy',
          showOn: "button",
          buttonImage: "images/calendar.png",
          buttonImageOnly: true,
          buttonText: "Select date",
          onSelect: function(dateText,inst)
          {
                id=$(this).attr('id');
    pos = id.indexOf("(") + 1;
    counter = id.slice(pos, -1);
    id=id.replace("("+counter+")","");
                pieces = dateText.split("/");
            $("#"+ id+"MM("+counter+")").val(pieces[0]);
            $("#"+ id+"DD("+counter+")").val(pieces[1]);
            $("#"+id +"YYYY("+counter+")").val(pieces[2]);
          }
        });

      });

      </script>

        <!-- "counter" is an integer which keeps track of what iteration of the 
        hashmap is being accessed, propertyValue is a string that allows me to 
        dynamically change the property of each form-->
        <tr>
            <td align="right" colspan="1">
                <label for="setOfObjectsStartMMDtH("+counter+")">
                <%=label.makeLabel(XXXXForm.FORM_KEY_VALUE)%></label>
            </td>
            <td align="left" colspan="4">
                <% propertyValue="setOfObjectsStartDtHMM("+counter+")";%>
                <html:text property="<%=propertyValue%>" styleId="<%=propertyValue%>" 
                size="2" maxlength="2"/>&nbsp;/&nbsp;

                <% propertyValue="setOfObjectsStartDtHDD("+counter+")";%>                                           
                <html:text property="<%=propertyValue%>"  styleId="<%=propertyValue%>"  
                size="2" maxlength="2"/>&nbsp;/&nbsp;

                <% propertyValue="setOfObjectsStartDtHYYYY("+counter+")";%>                                       
                <html:text property="<%=propertyValue%>" styleId="<%=propertyValue%>" 
                size="4" maxlength="4"/>

                <% propertyValue="setOfObjectsStartDtH("+counter+")";%>   
                <html:hidden styleId="<%=propertyValue%>" property="<%=propertyValue%>" 
                styleClass="datePick"+counter></html:hidden>

Here is what my getters and setters look like.

private final HashMap setOfObjects = new HashMap();

    /**
     * @param startDtH the setOfObjectsStartDtH to set
     */
    public void setSetOfObjectsStartDtH(String key, String startDtH) {
        setOfObjects obj = getSetOfObjects(key);
        obj.setStartDtH(startDtH);
    }

    /**
     * @return the startDtH
     */
    public String getSetOfObjectsStartDtH(String key) {
        if(setOfObjectss.containsKey(key)){
            SetOfObjects obj = getSetOfObjects(key);
            return obj.getStartDtH();
        }
        return "";
    }       

    /**
     * @param startDtHDD the startDtHDD to set
     */
    public void setSetOfObjectsStartDtHDD(String key, String startDtHDD) {
        SetOfObjects obj = getSetOfObjects(key);
        obj.setStartDtHDD(startDtHDD);
    }

    /**
     * @return the startDtHDD
     */
    public String getSetOfObjectsStartDtHDD(String key) {
        if(setOfObjectss.containsKey(key)){
            SetOfObjects obj = getSetOfObjects(key);
            return obj.getStartDtHDD();
        }
        return "";
    }

    /**
     * @param startDtHMM the startDtHMM to set
     */
    public void setSetOfObjectsStartDtHMM(String key, String startDtHMM) {
        SetOfObjects obj = getSetOfObjects(key);
        obj.setStartDtHMM(startDtHMM);
    }

    /**
     * @return the startDtHMM
     */
    public String getSetOfObjectsStartDtHMM(String key) {
        if(setOfObjectss.containsKey(key)){
            SetOfObjects obj = getSetOfObjects(key);
            return obj.getStartDtHMM();
        }
        return "";
    }

    /**
     * @param startDtHYYYY the startDtHYYYY to set
     */
    public void setSetOfObjectsStartDtHYYYY(String key, String startDtHYYYY) {
        SetOfObjects obj = getSetOfObjects(key);
        obj.setStartDtHYYYY(startDtHYYYY);
    }

    /**
     * @return the startDtHYYYY
     */
    public String getSetOfObjectsStartDtHYYYY(String key) {
        if(setOfObjectss.containsKey(key)){
            SetOfObjects obj = getSetOfObjects(key);
            return obj.getStartDtHYYYY();
        }
        return "";
    }


    private SetOfObjects getSetOfObjects(String key){   
        if(setOfObjects.containsKey(key))       
            return (SetOfObjects)setOfObjects.get(key);

        SetOfObjects set = new SetOfObjects();
        set.setId(Integer.parseInt(key));
        setOfObjects.put(key, set);
        return set;
    }

And here's what the SetOfObjects looks like:

public class SetOfObjects{

    private String startDtH = "";
    private String startDtHMM = "";
    private String startDtHDD = "";
    private String startDtHYYYY = "";

    /**
     * @param startDtH the startDtH to set
     */
    public void setStartDtH(String startDtH) {
        startDtH = startDtH;
    }

    /**
     * @return the startDtH
     */
    public String getStartDtH() {
        return startDtH;
    }

    /**
     * @param startDtHMM the startDtHMM to set
     */
    public void setStartDtHMM(String startDtHMM) {
        this.startDtHMM = startDtHMM;
    }

    /**
     * @return the startDtHMM
     */
    public String getStartDtHMM() {
        return startDtHMM;
    }

    /**
     * @param startDtHDD the startDtHDD to set
     */
    public void setStartDtHDD(String startDtHDD) {
        this.startDtHDD = startDtHDD;
    }

    /**
     * @return the startDtHDD
     */
    public String getStartDtHDD() {
        return startDtHDD;
    }

    /**
     * @param startDtHYYYY the startDtHYYYY to set
     */
    public void setStartDtHYYYY(String startDtHYYYY) {
        this.startDtHYYYY = startDtHYYYY;
    }

    /**
     * @return the startDtHYYYY
     */
    public String getStartDtHYYYY() {
        return startDtHYYYY;
    }

}

And finally, here's the generated html.

    <script>
    $(function() {
        $( ".datePick").datepicker({
          dateFormat: 'mm/dd/yy',
          showOn: "button",
          buttonImage: "images/calendar.png",
          buttonImageOnly: true,
          buttonText: "Select date",
          onSelect: function(dateText,inst)
          {
                id=$(this).attr('id');
    pos = id.indexOf("(") + 1;
    counter = id.slice(pos, -1);
    id=id.replace("("+counter+")","");
                pieces = dateText.split("/");
            $("#"+ id+"MM("+counter+")").val(pieces[0]);
            $("#"+ id+"DD("+counter+")").val(pieces[1]);
            $("#"+id +"YYYY("+counter+")").val(pieces[2]);
          }
        });

      });

      </script>

        <tr>
            <td align="right" colspan="1">
                                        <label for="setOfObjectsStartMMDtH("+counter+")"><label class="normal">Set of Objects</label></label>
                        </td>
                        <td align="left" colspan="4">

                <input type="text" name="setOfObjectsStartDtHMM(0)" maxlength="2" size="2" value="" id="setOfObjectsStartDtHMM(0)">&nbsp;/&nbsp;


                <input type="text" name="setOfObjectsStartDtHDD(0)" maxlength="2" size="2" value="" id="setOfObjectsStartDtHDD(0)">&nbsp;/&nbsp;


                <input type="text" name="setOfObjectsStartDtHYYYY(0)" maxlength="4" size="4" value="" id="setOfObjectsStartDtHYYYY(0)">


                <input type="hidden" name="setOfObjectsStartDtH(0)" value="" class="datePick" id="setOfObjectsStartDtH(0)">

((Note: I am aware that the '"+counter+"' is not creating an appropriate label - but fixing this has not fixed the calendar function))

The calendar itself pops up with no problem, but when I select a date, the page jumps to the top, and the date fields are not populated - no error message appears anywhere on the page, and the calendar does not disappear either, as it usually would after selecting a date.

What would cause the calendar to appear for the jQuery datepicker, but not allow me to assign the calendar values?

I think the problem is concatenation of the id selectors. You need to escape the parenthesis.

Try this:

        $("#"+ id+"MM\\("+counter+"\\)").val(pieces[0]);
        $("#"+ id+"DD\\("+counter+"\\)").val(pieces[1]);
        $("#"+id +"YYYY\\("+counter+"\\)").val(pieces[2]);

First of all, you have a mixture of two concepts backend code (Java) and a client-side code (JavaScript). In general, in a web application when a user makes a request that hits your server, which runs the backend code to generate a response and sent it back - that response is in the form of HTML/JS/CSS which is used to display things in the browser. Once in the browser, the JavaScript code can execute to provide further functionality.

This is the basic idea against most web apps - Java can be replaced with PHP or C# or JavaScript (in the form of NodeJS) or many others as a backend but you invariably will have both executing at a different times, environments, and even machines as well as geographical locations.

With that said, both can communicate. Not in a direct manner, eg, you can't call MyServerObject.setMyValue() from the client-side, however if you want to transfer from front end to backend, there are basically two ways to do it:

  • form submission - that nowadays is the "old-school" way of doing it. Not that it's bad but not as used. Essentially you will have a <form> on the page with a set of <input> s that can be manipulated and when the form is submitted it transfers all the values to the backend. This will vary based on how you want to get the data but it boils down to the action attribute on the form. This causes the page to be reloaded as part of the submission and the user being redirected elsewhere (though, possibly to the same page). It's seen as intrusive and not as user-friendly, hence the "old-school"-ness of it. On the other hand, it's natively supported by HTML and any browser knows how to deal with forms, so it has its uses.
  • AJAX requests - while not "new" in any way, this is usually the preferred way client-side code communicates with the backend. It involves sending some data to the server without leaving the page and without necessarily the user knowing about it, either. Thus it provides better user experience and it is also easier to deal with from the backend, as you can shape how your data comes in better (forms only give you key-value pairs).

While there are a lot of ways to achieve AJAX, the jQuery .ajax() and its two shorthands .get() and .post() are very convenient and easy. What you are likely to do is in your onSelect handler call something like: $.post("some/path/on/my/server", myData) where the myData object will be a the data you want that will be sent as JSON and some/path/on/my/server is some part of the server that can accept that data. In general, that path would just end up calling some server-side code passing along the data - in olden days you were likely to just hit a CGI script written in Perl or something but nowadays it's just your backend exposed through a URI. How exactly is that path going to be implemented can vary and unfortunately, I am not familiar with Struts as to how it would be done there, but I imagine it must not be hard.

At any rate, once your backend receives the data, the usual thing to do is process it in some fashion (check for validity, sanitize, decide what to do) and then hand it off for further processing in other parts of the application. In your case, you will likely receive some data then create and populate some objects with dates, then...do whatever else needed. However, if you need to know which user has issued a request, and this which user is doing stuff with their calendars, you might need to include more information. A lot of server-side languages have the concept of sessions which is just a context for a particular user. If somebody modifies a calendar, you can find out who it was based on the session and this find the corresponding calendar. Sessions are likely to be setup for you and you may need to do nothing to use them. Still, an alternative to using sessions is passing around tokens for the user - this takes form of some sort of information - username, key, session ID, that can be transferred as part of the AJAX request and will identify who issued it.

Whatever the case, if you need to pass information back to the client, for example "Action succeeded" or "failed", then the backend can respond to the AJAX request in more or less two ways. One way is to just send some data back from the simplest boolean to indicate success/failure to passing back Strings or entire Objects (likely serialized and transferred into JSON) to indicate the response. The second way is to send a response code to signify what happened. In reality, you are likely to use a mixture of both. On the client side, this would be dealt with by using the jQuery handlers

 $.post("some/path/on/my/server", myData)
 .done(function() { alert("sending data succeeded") })
 .fail(function() { alert("sending data failed") })
 .always(function() { alert("finished sending data") })

This is using the jQuery promises an alternative is specifying the success/failure handlers as part of the $.ajax call. It bears noting that the alert is purely for illustrative purposes - you are likely to notify the users in a different way. Or perhaps not at all, as it might not be relevant as long as it works, so you might only notify them if it fails.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM