4

I'm writing a mobile app with PhoneGap and jQuery Mobile. To simplify navigation I want to spread a single form over multiple 'pages' using div data-role="page". The idea is to give the user a wizard like experience for filling in a large form. On completion I need to be able to save the form locally, or submit it, if the mobile is online.

I don't understand how to go about submitting or saving a form using jQuery Mobile if the form is split into multiple 'virtual' pages. I've search the web but can't find any tutorials or examples on solving this problem.

Any help will be appreciated.

UPDATE:

I recently changed the way I worked with multipage forms, and this solution worked nice for me. You basically use a naming convention where fields become part of sections by giving them id's starting with the section name and a dash, e.g: person-name, person-surname. See the answer below.

Jack
  • 16,506
  • 19
  • 100
  • 167
  • My advice would be to use Local Storage to save (http://davidwalsh.name/html5-storage), I think you can have a form over multiple pages and still able to submit. I did something like this using Alpha 4 but jQM has changed a ton from that build. Just start testing and post code you have tried so we can help a little better – Phill Pafford Nov 07 '11 at 14:34
  • To be honest, I don't know where to start. The multipage concept of jQuery Mobile is a complete mystery to me. Effectively you end up with a form that is spread across multiple virtual pages, but this does not seem right at all, and I could not get it to work either. – Jack Nov 11 '11 at 10:19
  • I added this question: [PhoneGap and jQuery real world tutorial](http://stackoverflow.com/questions/8093225/phonegap-jquery-mobile-real-world-sample-or-tutorial) I'm hoping that a good real world tutorial will cover this problem. – Jack Nov 15 '11 at 11:31
  • The main issue you need to deal with is that JQM automatically takes over forms and submits them via Ajax. You want to write your own handler for forms and store the data while moving the user to the next page. Phill's recommendation on using local storage makes sense. How about this - I'll do a blog post on it this morning. Look for in 2-3 hours. – Raymond Camden Nov 18 '11 at 12:45
  • Actually - if you are using a server side language to manage what step a user is on - you could do it w/o any client side JS code at all. Basically the page loads with form 1, on submit your server side stores it and outputs form 2. Since JQM automatically takes the result and replaces it in the DOM ,it may just work. I'll try that too. – Raymond Camden Nov 18 '11 at 12:56

2 Answers2

6

Ok, I posted my thoughts here: http://www.coldfusionjedi.com/index.cfm/2011/11/18/Demo-of-a-multistep-form-in-jQuery-Mobile

Essentially I ended up using a sever side language to simply include the right part of the form at a time. (I'm using ColdFusion, but any language would work really.) The form self posts and simply displays the right step based on where you are in the process.

Raymond Camden
  • 10,661
  • 3
  • 34
  • 68
  • Your sample does provide a good workaround, thank you. I remain hopeful to find a good solution to a true jQuery multipage submit, effectively avoiding the server until the final form is completed. – Jack Nov 21 '11 at 14:36
  • Your tutorial shows a good alternative to solving the problem, thank you very much. It's really well done, but unfortunately does not answer the question, in that the form needs to be filled in locally and only submitted on full completion. I am still hopeful to finding a jQuery Mobile solution that relies on using JQM's multipage ability. In mobile apps it usually pays to keep server round trips to a minimum which is very important in my case. I'm still looking for a solution, and will post it if I get it in the meantime. – Jack Nov 21 '11 at 14:58
  • Let me see if I can rewrite it using your requirement. Shouldn't be difficult. – Raymond Camden Nov 21 '11 at 16:58
  • I'm keeping my fingers crossed :-) – Jack Nov 22 '11 at 09:35
  • Ok, I've got it working. Will blog after lunch (in about 1.5 hours). You can see the demo here: http://coldfusionjedi.com/demos/2011/nov/22/draft5/ – Raymond Camden Nov 22 '11 at 17:27
  • Oops, and I meant to say, when I blog it, I'll explain what I did. – Raymond Camden Nov 22 '11 at 17:27
  • http://www.coldfusionjedi.com/index.cfm/2011/11/22/Demo-of-a-multistep-form-in-jQuery-Mobile-Part-2 – Raymond Camden Nov 22 '11 at 19:37
1

A quick help to anyone stuck with the same problem. I did the 'form thing', but it gets sloppy. You basically just embed the page divs inside the form element, but that's not very elegant and has given me some navigation issues.

So I ended up with my own solution that works over huge multipage forms (+/- 1000 elements). Not the most elegant, but it works like a charm:

<!DOCTYPE html>

<head>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <meta charset="utf-8"/>
    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.css" />
    <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
    <script src="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.js"></script>
    <script>
        $(function () {
            $('#submit_my_form').click(function (e) {
                alert(JSON.stringify(readFormData('names')));
                alert(JSON.stringify(readFormData('dates')));
            });
        });

        function readFormData(section) {
            var sectionData;
            var els = $(':input[id|='+section+']');

            var sectionData = {};
            $.each(els, function() {
                if (this.name && !this.disabled && (this.checked
                    || /select|textarea/i.test(this.nodeName)
                    || /text|hidden|password|date|email/i.test(this.type))) {
                    sectionData[this.name.substr(section.length+1)] = $(this).val();
                    console.log(this.name + " -> " + $(this).val());
                }
            });
            return sectionData;
        }
    </script>
</head>

<body>
    <div data-role="page" id="menu" data-theme="a">
        <div data-role="header" data-position="fixed">
            <h1>Menu Page</h1>
        </div>
        <div data-role="content">
            <ul data-role="controlgroup">
                <li><a target_id="page1" href="#page1" data-role="button"
                       style="text-align:left" data-icon="arrow-r"
                       data-iconpos="right" class=".ui-icon-manditory">Page1</a></li>
                <li><a target_id="page2" href="#page2" data-role="button"
                       style="text-align:left" data-icon="arrow-r"
                       data-iconpos="right">Page2</a></li>
            </ul>
            <input id="submit_my_form" type="button" name="send" value="Submit"/>
        </div>
        <div data-role="footer" data-position="fixed" class="ui-btn-right" style="min-height:42px;">
            Menu page footer
        </div>
    </div>

    <div data-role="page" id="page1" data-theme="a">
        <div data-role="header" data-position="fixed">
            <a href="#menu" data-icon="arrow-l" data-direction="reverse">Prev</a>
            <h1>Page 1</h1>
            <a href="#page2" data-icon="arrow-r">Next</a>
        </div>
        <div data-role="content">
            <label for="names-initials">Name:</label>
            <input type="text" name="names-initials" id="names-initials" value=""/>
            <label for="names-surname">Surname:</label>
            <input type="text" name="names-surname" id="names-surname" value=""/>
        </div>
        <div data-role="footer" data-position="fixed" class="ui-btn-right" style="min-height:42px;">
        </div>
    </div>

    <div data-role="page" id="page2" data-theme="a">
        <div data-role="header" data-position="fixed">
            <a href="#page1" data-icon="arrow-l" data-direction="reverse">Prev</a>
            <h1>Page 2</h1>
        </div>
        <div data-role="content">
            <label for="dates-birthday">Birthday:</label>
            <input type="date" name="dates-birthday" id="dates-birthday" value=""/>
        </div>
        <div data-role="footer" data-position="fixed" class="ui-btn-right" style="min-height:42px;">
            <a href="#menu" data-icon="arrow-l" data-direction="reverse" data-iconpos="left"
               style="margin-left: 10px; margin-top: 5px">Back to Main From</a>
        </div>
    </div>
</body>
</html>
Jack
  • 16,506
  • 19
  • 100
  • 167