3

I'm having troubles when making a linked list in HTML, let me explain:

In HTML I have this two selects:

<!-- This select WORKS and read the opened projects from de database  -->
            <select name="project" id="project">
                <option value="0">Select a project</option>
                <?php if (isset($result2)): ?>
                    <?php foreach ($result2 as $res): ?>
                        <option value=<?php echo $res['c_project_id'] ?>><?php echo $res['d_name'] ?></option>
                    <?php endforeach ?>
                <?php endif ?>

            </select>

<!-- This doesn't work, but I want: When I select a project, the project's categories go here -->
                <select name="category" id="category">

                </select>

The REAL DATA are the next: Table PROJECT

c_project_id | d_name | d_description | n_budget | d_state
      1      |  Test  |  Test Project |    100   |  Open
      2      |  Web   |    Web APP    |   3000   |  Open
      3      | C Test |Closed Project |    100   | Closed
      4      | Certif.| Certificates  |   2500   |  Open

Table Categories (conected with table project)

c_category_id | d_name | d_description | c_project_id
     1        | General| General cat   |      1
     2        | Test   | Test cat      |      1
     3        | General| General cat   |      2
     4        | General| General cat   |      3
     5        | Nothing| Nothing cat   |      3
     6        |Program | Programming   |      2
...

I have a SELECT in html that takes the project name and ID, this works in the select nº1

$statement2 = $conexion->prepare("SELECT c_project_id, d_name FROM project WHERE d_state= 'Open'");
$statement2->execute();
$resultado2 = $statement2->fetchAll();

Now I want: When I "click" in the first select, the second select make the statement and fulfill the second select. For testing, I just wrote a simple option. I tried with AJAX and PHP but the 2nd option is empty:

AJAX:

$( "#project" ).change(function() {
      var select = $( "#project option:selected" ).val();
      console.log(select); //just for testing that I took the value.
      $.ajax({
            type: "POST",
            url: "phpPage.php",
            data: { selectedProject : select } 
        }).done(function(data){
            console.log("Done");
            $("#category").html(data);
        });
    });

AND PHP:

if(isset($_POST["selectedProject"])){
        $proy = $_POST["selectedProject"];
        $output = "<option value='100'> Select your category </option>";

        if($proy != 0){
            $output.= "<option>" . $proy . "</option>"; 
        }

        echo $output;   
    }

But this return me nothing, all is empty.

FINALLY, when I tried to debug, I noticed that in one of the PHP responses, the HTML code () is been written at start of the page (in the response):

<option value='100'> Select your category </option><option>1</option> 
<!DOCTYPE html>
<html lang="es">
    <head>
        <title>
...

Sorry for that huge question, but I'm wasting a lot of time with that and I don't know what could happen. Thanks you!

nasito90
  • 45
  • 4
  • try `.success` instead of `.done` – Ali Sheikhpour May 30 '18 at 12:36
  • Exactly the same, the second option is empty, and in the PHP response, all is writen before the HTML code – nasito90 May 30 '18 at 12:48
  • 2
    Since you are only needing the base html of the `option` tags, you do not need anymore html. So add an `exit;` just after `echo $output;` – IncredibleHat May 30 '18 at 12:51
  • 1
    More info on `.success` (or success: option) vs `.done` ... https://stackoverflow.com/a/8840315/2960971 – IncredibleHat May 30 '18 at 12:56
  • @IncredibleHat amazing!!, this works, but can you explain me why? I really don't understood that – nasito90 May 30 '18 at 12:57
  • 2
    @AliSheikhpour that's completely wrong. .done() is the correct method of the jQuery Deferred / Promise interface ($.ajax() returns a Deferred object) to call when the request succeeded. You're no doubt thinking of the "success" callback which is provided as an option within the call to $.ajax(). the Deferred interface does not expose any method called "success()". Check the documentation...http://api.jquery.com/jquery.ajax/ and http://api.jquery.com/category/deferred-object/ before writing. There's nothing wrong with that specific aspect of the OP's code. – ADyson May 30 '18 at 13:12
  • 2
    Anyway as to your question..."can you explain me why", see IncredibleHat's answer recently posted. You're using the same PHP script to output the bits needed for your ajax call, and for your main page. It's generally a bad design to mix them up, but if you're careful you can. The reason the change works is because exit stops your script running, and therefore stops it spitting out lots of other HTML which is meant to be for loading the main page, and not meant to be part of the output of the ajax call. – ADyson May 30 '18 at 13:28
  • Yeah I read it and I think I took the point, I coulnd't think about it... THANKS!!! – nasito90 May 30 '18 at 13:36
  • 2
    I tend to have a sub directory filled with 'little scripts' for ajax calls. But sometimes when I'm being a bit lazy (or going too fast), I stuff ajax reaction code near the very tippytop of some big-ass script I'm working on (just to get things rolling)... then later yank that top bit out into its own file when I nail things down. The main thing to grasp on, is ajax is generally used to 'manipulate the current html document'... so you only need either json data to use, or chunks of html to insert/replace parts with. – IncredibleHat May 30 '18 at 13:41

1 Answers1

2

Lets look at the breakdown of what you have and want to do. First, you have an empty select element:

<select name="category" id="category">
    // empty
</select>

Then, you are tripping off an ajax call which returns data from your PHP. This ajax is simply taking all the returned html from the PHP and putting it in the middle of that above select:

$("#category").html(data);

Your PHP is where you are creating too much information on output. This is usually where its a good idea to isolate your "ajax php scripts" from normal full html build php scripts. So that you are only outputting what you need for that specific ajax call.

In your above PHP, you have:

if(isset($_POST["selectedProject"])){
    $proy = $_POST["selectedProject"];
    $output = "<option value='100'> Select your category </option>";
    if($proy != 0){
        $output.= "<option>" . $proy . "</option>"; 
    }
    echo $output;
}
// you must have more page generation below this based on your Q (?)

You can either isolate the above code into a new ajax response script (include any needed db actions and pull of data from the database based on the POST arg value, etc).... OR, you can add exit; after your echo $output;... so long as no other extra html was being output BEFORE this if block.

if(isset($_POST["selectedProject"])){
    $proy = $_POST["selectedProject"];
    $output = "<option value='100'> Select your category </option>";
    if($proy != 0){
        $output.= "<option>" . $proy . "</option>"; 
    }
    echo $output;
    exit; // <-- halt so none of the other following html spills out
}
IncredibleHat
  • 4,000
  • 4
  • 15
  • 27