0

I've read multiple threads here and still can't find a good answer for my question, so I'm sorry for this silly question but there are no words for how bad I am with Javascript.

So I'm currently trying to change the select options on a 2nd select tag based on the selected option from the first one.

<select name="category" id="category">
    <option value="" disabled selected value>Cat1</option>
                <?php 
  $stmt = $conn->query("SELECT * FROM cats");
  while($row = $stmt->fetch()) {
    echo "<option value='".$row['name']."'>".$row['text']."</option>";
  }
  ?>
</select>
    </div>
</div>

  <div class="div3">
<div class="div4">
  <label for="test">cat2</label>
</div>
<div class="div7">
 <select name="sub" id="sub">
 <?php 
  $stmt = $conn->query("SELECT * FROM cats WHERE name = $cat");
  while($row = $stmt->fetch()) {
    echo "<option value='".$row['subname']."'>".$row['subtext']."</option>";
  }
  ?>
 </select>
</div>

So I know that I somehow need to call a JavaScript with "onchange" which will get the $cat variable and then pass back the information from the SQL table. But I have absolute no idea how I can do this.. I don't wanna use either form or Ajax. If this is possible with pure Javascript, I would be really happy..

Then of course I don't expect you to solve the entire issue for me but I would be glad if someone could point me in the right direction (Don't think too much about the prepared statements with $stmt, this is just a first test)

E A
  • 11
  • 4
  • You can not do without form, Ajax, or Web socket. In your example, JS works in client side and PHP (of course) works in server side. You have to solve 2 issues totally: firstly, let PHP know which `$cat` value it should catch to query and generate 2nd options; and secondly, trigger PHP (to re-query) + HTML (to re-generate options in 2nd select tag) everytime the 1st select tag value changes. As I said, PHP script run on server, and it does not know what happen / to do until clients / websocket clients tell it what to do. – vietanhyt Sep 30 '19 at 10:03
  • I didn't want to use Ajax but of course I'll do it if that's needed. But I really don't wanna use form since that's probably going to mess up the site – E A Sep 30 '19 at 10:07
  • It's not going to mess up the site if you can handle your work / your code / your project structure. Every web app / mobile app need forms. – vietanhyt Sep 30 '19 at 10:12
  • the problem is that this a part is from a form plus that the form is divided into 2 parts so this form goes trough a handler which then sends you to a different page. I don't want a form in a form which then sends you to a new form – E A Sep 30 '19 at 10:15
  • OK it's good. Actually, you can not have nested-forms. And. You did not mention it in your question. – vietanhyt Sep 30 '19 at 10:18
  • I don't think it matter. This form closes -> Goes to start.php -> check what category was set -> goes to next form based on category – E A Sep 30 '19 at 10:24

1 Answers1

-1

If you don't want to use Ajax, you need to get all data for each main category and save them all into a pieced-together JS array.

Something like

  $jstext = ''; //our pieced-together array definition for JS
  $stmt = $conn->query("SELECT * FROM cats");
  while($row = $stmt->fetch()) {
    echo "<option value='".$row['name']."'>".$row['text']."</option>";

    $stmt2 = $conn->query("SELECT * FROM cats WHERE name = {$row['name']}");
    $jstext .= "subcategories['".$row['name']."'] = '";
    $tmp = '';
    while($row2 = $stmt2->fetch()) {
      $tmp .= '<option>'.$row2['name'].'</option>'; //generate html for each subcategory
    }
  }
  $jstext .= $tmp."';\r\n"; //add subcategories to array index, add line break

Then in your <script> tag, add:

<script>
var subcategories;
<?php echo $jstext ?>
</script>

This should generate an array with an index of each main category and the content is the respective sub-categories.

Example Output:

<script>
var subcategories;
subcategories['maincat1'] = '<option>subcat1</option><option>subcat3</option>';
subcategories['maincat2'] = '<option>subcat4</option><option>subcat6</option>';
</script>

Now you just need to replace the innerHTML of your "sub" select when the "category" select fires an onchange event.

MiK
  • 918
  • 4
  • 16
  • Thank you very much, I'll try in a minute. But what you're saying is that it would actually be smoother if I used ajax? – E A Sep 30 '19 at 10:09
  • It would probably be smoother and also have the advantage of only requesting the data for the main category that the user selected instead of getting all data at once. But this method should work if you don't want to use them. – MiK Sep 30 '19 at 10:11
  • You got N+1 query issue. @MiK – vietanhyt Sep 30 '19 at 10:14
  • Never do any PRODUCTION piece like this. – vietanhyt Sep 30 '19 at 10:15
  • So if I instead pick to go with Ajax, where should I start? – E A Sep 30 '19 at 10:23
  • @vietanhyt n+1 is a [hot topic](https://stackoverflow.com/questions/97197/what-is-the-n1-selects-problem-in-orm-object-relational-mapping) that is by no means a "this is wrong and this is right" matter. – MiK Sep 30 '19 at 11:12
  • @EA I recommend researching the [basic principles of Ajax](https://www.w3schools.com/xml/ajax_intro.asp) first. What it boils down to is that your visitor's browser sends a request to a php page on your server, the php processes this request and offers data back to the requesting site. The visitor's browser reacts to the ready state change and you can then replace your select's innerHTML with the returned data. – MiK Sep 30 '19 at 11:15