2

I am trying to get select menus show hide by using ajax and serialised hashes. I had this system working last night but I changed the #selector from a form to a div and suddenly its stopped running. I had to broaden the form for additional data on post and did not want to serialise all the data at once for this as it would be additional strain on the system.

The page somewhat works as expected. It shows the first select, allows me to select an option, I can see the AJAX posting but the hash value is empty which I believe is breaking the PHP above. I cant figure out why the hash is posting empty. I assume its not getting the value from the select but I cant work out why..

If possible can you please point out where I am going wrong?

<section id="add">
<div class="container">
    <form method="post">
        <div class="panel panel-default">
            <div class="panel-heading">
                <h3 class="panel-title"><strong>Step 1: Instance Select</strong></h3>
            </div>
            <div id="selector">
                <div class="panel-body">
                    <div class="col-md-6">
                        <select class="form-control box1" name="box1"></select>
                        <input name="box1hash" class="box1hash" type="hidden" />
                    </div>
                    <div class="col-md-6">
                        <select class="form-control box2" name="box2"></select>
                        <input name="box2hash" class="box2hash" type="hidden" />
                    </div>
                    <div class="col-md-6">
                        <select class="form-control box3" name="box3"></select>
                        <input name="box3hash" class="box3hash" type="hidden" />
                    </div>
                    <div class="col-md-6">
                        <select class="form-control box4" name="box4"></select>
                        <input name="box4hash" class="box4hash" type="hidden" />
                    </div>
                    <div class="col-md-6">
                        <select class="form-control box5" name="box5"></select>
                        <input name="box5hash" class="box5hash" type="hidden" />
                    </div>
                </div>
            </div>
        </div>
        <div class="panel panel-default">
            <div class="panel-heading">
                <h3 class="panel-title"><strong>Step 2: Event Details</strong></h3>
            </div>
            <div class="panel-body">
                <input name="event_name" type="text" class="form-control" />

            </div>
        </div>
        <input type="submit"/>
    </form>
</div>

        $(document).on('change', '#selector', function(e) {
            ajax_post(this);
        });

        ajax_post();

    })(jQuery);

    function show_hide_select(select){
        if ($(select).find('option').length < 1) {
            $(select).hide();
        } else {
            $(select).show();
        }
    }

    function ajax_post(element=null) {
        var frm = $('#selector');

        if (element != null) {
            // Reset selections
            var found=false;
            frm.find('select').each(function(e){
                if (found==true) {
                    $(this).hide().find('option:selected').prop("selected", false)
                }
                if (element==this) found=true;
            });
        }


        $.ajax({
        url: '?ajax=1',
        type: "POST",
        data: frm.serialize(),
        dataType: 'json',
            success: function (data) {

                if (data.box1hash != frm.find('.box1hash').val()) {
                    frm.find('.box1').html(data.box1?data.box1:'');
                    frm.find('.box1hash').val(data.box1hash);
                    show_hide_select(frm.find('.box1'));
                }

                if (data.box2hash != frm.find('.box2hash').val()) {
                    frm.find('.box2').html(data.box2?data.box2:'');
                    frm.find('.box2hash').val(data.box2hash);
                    show_hide_select(frm.find('.box2'));
                }

                if (data.box3hash != frm.find('.box3hash').val()) {
                    frm.find('.box3').html(data.box3?data.box3:'');
                    frm.find('.box3hash').val(data.box3hash);
                    show_hide_select(frm.find('.box3'));
                }

                if (data.box4hash != frm.find('.box4hash').val()) {
                    frm.find('.box4').html(data.box4?data.box4:'');
                    frm.find('.box4hash').val(data.box4hash);
                    show_hide_select(frm.find('.box4'));
                }

                if (data.box5hash != frm.find('.box5hash').val()) {
                    frm.find('.box5').html(data.box5?data.box5:'');
                    frm.find('.box5hash').val(data.box5hash);
                    show_hide_select(frm.find('.box5'));
                }

            }
        });
    }
</script>
Brendonexus
  • 142
  • 1
  • 10
  • i don't know exactly but i think you should `serialize` the `inputs` and `select` from the `#selected` div . not the whole `#selected` div see here > https://stackoverflow.com/questions/9589126/jquery-serialize-serializearray-from-an-element-that-is-not-a-form – Mihai T Jun 16 '17 at 12:44
  • The AJAX shows that the data is posting hashes from the other hidden fields but not from box2... box two is the one im using to validate in the PHP not shown on the page. I think the issue is with the jquery not getting the value of the first box and not serialising the content itself. I have updated my question to explain this further. – Brendonexus Jun 16 '17 at 12:59
  • the first line of your js is missing? when you change the form container the nature of jquery 'change' and the component selectors also changes (because it's no longer a Form I think your `frm.serialize()` will no longer work. As such a different strategy might be needed. Can you summarise your overall intended behaviour? – Sam0 Jun 16 '17 at 14:39
  • Yeah the first line would not format correctly so I had to remove it before it would let me post. My intention is that the first dropdown will have 2 options, the second dropdown will return results relative to the first and so on, this can nest up to 5 times. My intention is to get the value from the select and post with AJAX, this will then go into PHP if statements and return the right function to output into the next dropdown menu. Everything was working fine prior to me changing to form tag to a div so I am positive its not a php issue and the AJAX is still posting.. – Brendonexus Jun 16 '17 at 14:45
  • I agree it's not a php issue. Have you considered returning it to a form tag but separating it from the main form to focus the data being serialized? – Sam0 Jun 16 '17 at 14:52
  • Can I do that but still post the same values? In the end I need to throw the data into a database so am unsure if its going to work like that – Brendonexus Jun 16 '17 at 18:17
  • Alternative strategy, to reduce your strain on your system: return your current script back to its former Form tag, serialize its contents as you would, before copying out the data you wish to send into a different array and posting that instead. In short generate the larger data set and send a reduced version of that. If you can provide an example of the full serialized dataset and an indication of the part you wish to keep I can update your script as needed. – Sam0 Jun 17 '17 at 11:34

1 Answers1

0

Contrary to my earlier comments, a form tag cannot be nested within another form tag. jquery serialize() only works on forms, so unfortunately it's not possible to focus it on a div component of the form. Instead however you can serialize the whole form as a string, and then extract the subsection of that string for reduced ajax posting. Snippet below with inline comments...

$('form').on({
 'change':function(e){
   e.preventDefault();
   var dats = $(this).serialize(); // serialize the whole form into a string
   var pico = dats.indexOf('&event_name='); // get the index of the end point of the desired data
   var newDats = dats.slice(0 , pico); // get the edited section for ajax submission
   $('#results').text(dats+' '+newDats);
   
 }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<section id="add">
<div class="container">
    <form method="post" id='bob'>
        <div class="panel panel-default">
            <div class="panel-heading">
                <h3 class="panel-title"><strong>Step 1: Instance Select</strong></h3>
            </div>
            <div id="selector">
                <div class="panel-body">
                    <div class="col-md-6">
                        <select class="form-control box1" name="box1">
                        <option>a</option>
                        <option>b</option>
                        <option>c</option>
                        </select>
                        <input name="box1hash" class="box1hash" type="hidden" />
                    </div>
                    <div class="col-md-6">
                        <select class="form-control box2" name="box2"></select>
                        <input name="box2hash" class="box2hash" type="hidden" />
                    </div>
                    <div class="col-md-6">
                        <select class="form-control box3" name="box3"></select>
                        <input name="box3hash" class="box3hash" type="hidden" />
                    </div>
                    <div class="col-md-6">
                        <select class="form-control box4" name="box4"></select>
                        <input name="box4hash" class="box4hash" type="hidden" />
                    </div>
                    <div class="col-md-6">
                        <select class="form-control box5" name="box5"></select>
                        <input name="box5hash" class="box5hash" type="hidden" />
                    </div>
                </div>
            </div>
        </div>
        <div class="panel panel-default">
            <div class="panel-heading">
                <h3 class="panel-title"><strong>Step 2: Event Details</strong></h3>
            </div>
            <div class="panel-body">
                <input name="event_name" type="text" class="form-control" />

            </div>
        </div>
        <input type="submit"/>
    </form>
</div>

<p><tt id="results"></tt></p>
Sam0
  • 1,459
  • 1
  • 11
  • 13
  • Sorry for my late reply. This was actually rectified by adding an * to the frm variable var frm = $('#selector *'); Thank you for your help and advise though! – Brendonexus Jun 21 '17 at 12:55