Tour Of Heroes Remix With JS And PHP

Referring to Heroes example here, this example is totally created by Angular 2 and type script. Some people may ask, if it is possible to do the same, using pure JavaScript instead. I decided to make a one, using JavaScript, pure JavaScript and of course AJAX to call the Server-side functionality. At the Server-side, I coded PHP Web Service that accepts different kinds of requests (GET-POST-PUT-DELETE).

Let’s code first the Server-side

We add this piece of code to accept CORS and establish the database connection.

  1. <?php  
  2. //ALLOW CROSS-ORIGIN RESOURCE SHARING CORS  
  3.   
  4. header('Access-Control-Allow-Origin: *');  
  5. header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');  
  6.   
  7. header('Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE,PUT');  
  8.   
  9. //-----------------------------  
  10.   
  11. //ESTABLISH DB CONNECTION  
  12.   
  13. $db_host = "hostname";  
  14. $db_username = "username";  
  15. $db_password="password";  
  16. $db_name="DBName";  
  17.   
  18. $db_connection=new MySQLi($db_host,$db_username,$db_password,$db_name);  
  19.   
  20. if (!$db_connection)  
  21. {  
  22.     die("Connection Error" . mysqli_connect_err());  
  23. }  
  24.   
  25. ?>  
Instead of using the virtual Server used in Angular 2, I wrote some PHP code to handle the different kinds of requests to avoid SQL injection, prepared statement may come in handy and more secure to handle the requests coming to the Server. .

In the very first, check the kind of request and then handle each request, using if statements

  1. $verb=$_SERVER['REQUEST_METHOD'];  

To get the associated row names from the result set, get the result and return get_result() into $result variable that has fetch_assoc() method.

  1. $result$STMNT_SELECT->get_result();  

The full code is given below.

  1. <?php  
  2. //heroesOnline.php file  
  3.   
  4. //CONNECTO TO DB  
  5. include_once('config.php');  
  6.   
  7. //PREPARED STATEMENTS  
  8.   
  9. //SELECT QUERY  
  10. $querySelect="select id,name from heroes";  
  11. $STMNT_SELECT=$db_connection->prepare($querySelect);  
  12. $STMNT_SELECTBYID=$db_connection->prepare("SELECT id,name from heroes WHERE id=?");  
  13.   
  14. //INSERT QUERY  
  15. $STMNT_INSERT = $db_connection->prepare("INSERT INTO heroes (Name) VALUES (?)");  
  16.   
  17. //UPDATE QUERY  
  18. $STMNT_UPDATE=$db_connection->prepare("UPDATE heroes SET Name=? WHERE id=?");  
  19.   
  20. //DELETE QUERY  
  21. $STMNT_DELETE=$db_connection->prepare("DELETE FROM heroes WHERE id=?");  
  22.   
  23. //CHECK VERB  'REQUEST TYPE'  
  24. $verb=$_SERVER['REQUEST_METHOD'];  
  25.   
  26. //ARRAY TO RETURN THE RESULT SET INTO  
  27. $result_set=array();  
  28.   
  29. //CHECK verb type  
  30. if ($verb=='GET'){  
  31.   
  32.     //Check if ID has been passed to the page  
  33.     if (isset($_GET['id']))  
  34.     {  
  35.   
  36.         //Check if it is queryable          
  37.         $STMNT_SELECTBYID->bind_param("i",$_GET['id']);  
  38.   
  39.         if ($STMNT_SELECTBYID->execute()){  
  40.               
  41.             $STMNT_SELECTBYID->bind_result($id,$name);  
  42.   
  43.             //CONVERT RESULT COMING FORM PREPARED STATEMENT INTO 'mysqli_result'  
  44.             //TO BE ABLE TO USE THE METHOD 'fetch_assoc'   
  45.   
  46.             $result$STMNT_SELECTBYID->get_result();            
  47.   
  48.             $row=$result->fetch_assoc();  
  49.   
  50.             echo json_encode($row);  
  51.               
  52.   
  53.         } else {  
  54.   
  55.             echo 'ERROR RETURNING DATA WITH THIS ID';  
  56.         }  
  57.   
  58.     } else{  
  59.   
  60.         //if $STMNT has data  
  61.         if ($STMNT_SELECT){  
  62.   
  63.             $STMNT_SELECT->execute();  
  64.             $STMNT_SELECT->bind_result($id,$name);         
  65.               
  66.             //CONVERT RESULT COMING FORM PREPARED STATEMENT INTO 'mysqli_result'  
  67.             //TO BE ABLE TO USE THE METHOD 'fetch_assoc'   
  68.   
  69.             $result$STMNT_SELECT->get_result();  
  70.   
  71.             while ($row=$result->fetch_assoc()){  
  72.   
  73.                 //printf ("%d %s <br>", $row["id"], $row["name"]);  
  74.                 //ADD EACH ROW TO THE ARRAY  
  75.                 $result_set[]=$row;              
  76.             }  
  77.   
  78.             //RETURN JOSN OBJECT OF THE WHOLE ARRAY  
  79.             echo json_encode($result_set);         
  80.               
  81.               
  82.         } //IF  
  83.   
  84.     }  
  85.       
  86.     $STMNT_SELECTBYID->close();  
  87.     $STMNT_SELECT->close();  
  88.   
  89.   
  90. elseif ($verb=='POST'){  
  91.   
  92.     echo 'POST method was called';  
  93.     $STMNT_INSERT->bind_param("s",$_POST['name']);  
  94.   
  95.     if ($STMNT_INSERT->execute()){  
  96.   
  97.         echo 'INSERTED';  
  98.     } else {  echo 'INSERT_ERROR'; }  
  99.   
  100.         $STMNT_INSERT->close();  
  101.   
  102. elseif ($verb=='DELETE'){  
  103.   
  104.     echo 'DELETE method was called';  
  105.     parse_str(file_get_contents('php://input'),$_DELETE);  
  106.     $STMNT_DELETE->bind_param("i",$_DELETE['id']);  
  107.   
  108.     if ($STMNT_DELETE->execute() ){  
  109.   
  110.         echo 'DELETED' . $_DELETE['id'];  
  111.     } else {  echo 'DELETE_ERROR';  }  
  112.   
  113.     $STMNT_DELETE->close();  
  114.   
  115. elseif ($verb=='PUT'){  
  116.   
  117.     echo 'PUT method was called';  
  118.     parse_str(file_get_contents('php://input'),$_PUT);  
  119.     $STMNT_UPDATE->bind_param("si",$_PUT['name'],$_PUT['id']);  
  120.   
  121.     if ($STMNT_UPDATE->execute()){  
  122.   
  123.         echo 'UPDATED';  
  124.     } else {  echo 'UPDATE_ERROR'; }  
  125.       
  126.     $STMNT_UPDATE->close();  
  127. }  
  128.   
  129. //close connection  
  130. $db_connection->close();  
  131.   
  132. ?>  

Now, let’s move to the client-side.

Once the page opens, it sends a GET request to the Server to get all the heroes.

  1. //Call this on page load  
  2. window.onload=function()  
  3. {  
  4.     selectAllHeroes();  
  5. }  
  6.   
  7. //Get all heroes form the server  
  8. var selectAllHeroes=function(){  
  9.   
  10.     xmlhttp4GET.open("GET","http://localhost:8000/HeroesWebservice/heroesOnline.php",true);  
  11.     xmlhttp4GET.send();  
  12. }  
  13.   
  14. //Array to hold all heroes and filtered ones  
  15. var heroes=[];  
  16. var matchedHeroes=[];  
  17. var hero;  

Text is coming from the Server is parsed as JSON, as the Server-side function returns json_encode() of the resulting result set.

  1. //Initiate XMLHttpRequest object for GET method  
  2.     xmlhttp4GET=new XMLHttpRequest();  
  3.   
  4.     //return data from the server  
  5.     xmlhttp4GET.onreadystatechange=function()  
  6.     {  
  7.         if (this.readyState==4 && this.status==200) {  
  8.   
  9.             heroes=JSON.parse( this.responseText );  
  10.               
  11.             //Draw panels and fill them with heroes data  
  12.             drawPanels(heroes);  
  13.         }  
  14.     }  

Now, comes an important part, it combines the resulting data coming from the Server into the interactive user interface elements, using Bootstrap panels, that invokes the function drawPanls() passing heroes as an argument. 

  1. //Draw panels according to the hero list  
  2.     var drawPanels=function(listHeroes){  
  3.   
  4.         //collapse panel for the rows  
  5.             tableHeroes='<div class="panel-group" id="accordion">';  
  6.   
  7.             //List items in the 'heroes' Array  
  8.             listHeroes.forEach(function(item) {  
  9.   
  10.                 tableHeroes+='<div class="panel panel-default"><div class="panel-heading">' +  
  11.                 '<h4 class="panel-title"><a data-toggle="collapse" data-parent="#accordion" href="#panel' + item.id  + '"' +  
  12.                  ' onclick=' + '"' + 'selectOne(' + item.id + ',' + "'" + item.name + "'" + ')">' + item.name + '</a>' +  
  13.                 '</h4></div><div id="panel' + item.id + '" class="panel-collapse collapse">' +  
  14.                 '<div class="panel-body">' + '<h4>ID: ' +  item.id + '</h4>' +   
  15.                 '<h4>Name: ' + item.name  + '</h4><br />' + '<input type="button" value="Delete" class="btn btn-danger"' +  
  16.                  'onclick="remove(' + item.id + ')"'  + '/>'                                   
  17.                  + '</div></div></div>';  
  18.   
  19.             });  
  20.               
  21.             tableHeroes+='</div>';  
  22.             document.getElementById('div_heroeList').innerHTML=tableHeroes;  
  23.     }  
Note

There are two xmlHTTP objects for GET requests, as we have two different kinds of data received from the Server , using GET request, all heroes data and the second is one record for a hero related to the given ID.
 
 And here is the full code.
  1. //Call this on page load  
  2. window.onload=function()  
  3. {  
  4.     selectAllHeroes();  
  5. }  
  6.   
  7. //Get all heroes form the server  
  8. var selectAllHeroes=function(){  
  9.   
  10.     xmlhttp4GET.open("GET","http://localhost:8000/HeroesWebservice/heroesOnline.php",true);  
  11.     xmlhttp4GET.send();  
  12. }  
  13.   
  14. //Array to hold all heroes and filtered ones  
  15. var heroes=[];  
  16. var matchedHeroes=[];  
  17. var hero;  
  18.   
  19. //variable holding table contents  
  20. var tableHeroes;  
  21.   
  22. //Initiate XMLHttpRequest object for POST, PUT and DELETE methods  
  23.     xmlhttp=new XMLHttpRequest();  
  24.   
  25.     // Return data from the server  
  26.     xmlhttp.onreadystatechange=function()  
  27.     {  
  28.         if (this.readyState==4 && this.status==200) {  
  29.   
  30.               
  31.             console.log(this.responseText);  
  32.         }  
  33.         //  
  34.     }  
  35.   
  36.     //Initiate XMLHttpRequest object for GET method  
  37.     xmlhttp4GET=new XMLHttpRequest();  
  38.   
  39.     //return data from the server  
  40.     xmlhttp4GET.onreadystatechange=function()  
  41.     {  
  42.         if (this.readyState==4 && this.status==200) {  
  43.   
  44.             heroes=JSON.parse( this.responseText );  
  45.               
  46.             //Draw panels and fill them with heroes data  
  47.             drawPanels(heroes);  
  48.         }  
  49.     }  
  50.   
  51.     //Initialize object to get data of one hero from the server  
  52.     xmlhttpGetById=new XMLHttpRequest();  
  53.   
  54.     //return hero data  
  55.     xmlhttpGetById.onreadystatechange=function(){  
  56.   
  57.         if (this.readyState==4 && this.status==200){  
  58.   
  59.             hero=JSON.parse(this.responseText);  
  60.             document.getElementById('lbl_name').innerHTML=hero.name;  
  61.         }  
  62.     }  
  63.   
  64.     //Draw panels according to the hero list  
  65.     var drawPanels=function(listHeroes){  
  66.   
  67.         //collapse panel for the rows  
  68.             tableHeroes='<div class="panel-group" id="accordion">';  
  69.   
  70.             //List items in the 'heroes' Array  
  71.             listHeroes.forEach(function(item) {  
  72.   
  73.                 tableHeroes+='<div class="panel panel-default"><div class="panel-heading">' +  
  74.                 '<h4 class="panel-title"><a data-toggle="collapse" data-parent="#accordion" href="#panel' + item.id  + '"' +  
  75.                  ' onclick=' + '"' + 'selectOne(' + item.id + ',' + "'" + item.name + "'" + ')">' + item.name + '</a>' +  
  76.                 '</h4></div><div id="panel' + item.id + '" class="panel-collapse collapse">' +  
  77.                 '<div class="panel-body">' + '<h4>ID: ' +  item.id + '</h4>' +   
  78.                 '<h4>Name: ' + item.name  + '</h4><br />' + '<input type="button" value="Delete" class="btn btn-danger"' +  
  79.                  'onclick="remove(' + item.id + ')"'  + '/>'                                   
  80.                  + '</div></div></div>';  
  81.   
  82.             });  
  83.               
  84.             tableHeroes+='</div>';  
  85.             document.getElementById('div_heroeList').innerHTML=tableHeroes;  
  86.     }  
  87.   
  88.     //add() function when clicking button 'Add'  
  89.     var add=function(){  
  90.   
  91.         //Get txtAdd value  
  92.         input=document.getElementById("txtAdd").value;  
  93.   
  94.         //if txtAdd is not empty  
  95.         if (input==""){  
  96.   
  97.             document.getElementById('spanAddError').style.display="inline";  
  98.             return;  
  99.         }  
  100.   
  101.         //send POST requert to the server  
  102.         xmlhttp.open("POST","http://localhost:8000/HeroesWebservice/heroesOnline.php",true);  
  103.         xmlhttp.setRequestHeader("Content-type""application/x-www-form-urlencoded");  
  104.         xmlhttp.send("name=" + input);  
  105.         document.getElementById("txtAdd").value="";  
  106.   
  107.         selectAllHeroes();  
  108.   
  109.     }  //end function  
  110.   
  111.     //Fire this on change txtAdd onkeyup  
  112.     var txtAdd_onChange=function(txt){  
  113.   
  114.        if (txt.value==""){  
  115.   
  116.             document.getElementById('spanAddError').style.display="inline";  
  117.             document.getElementById('btnAdd').disabled=true;  
  118.        }  
  119.        else{  
  120.             document.getElementById('spanAddError').style.display="none";  
  121.             document.getElementById('btnAdd').disabled=false;  
  122.        }  
  123.   
  124.     } // end function  
  125.   
  126. //Fire this method on updating the entry  
  127. var update=function() {  
  128.   
  129.     input=document.getElementById("txtEdit").value;  
  130.     id=document.getElementById('hiddenID').value;  
  131.   
  132.     //Send data to the server as a PUT request  
  133.     xmlhttp.open("PUT","http://localhost:8000/HeroesWebservice/heroesOnline.php",true);  
  134.       
  135.     xmlhttp.send("id=" + id  + "&name=" + input);  
  136.   
  137.     //Select all heroes from the server after update.  
  138.     selectAllHeroes();  
  139. }  
  140.   
  141. //Fire this on clicking a panel  
  142. var selectOne=function(id,name){  
  143.   
  144.     document.getElementById('hiddenID').value=id;  
  145.     document.getElementById('txtEdit').value=name;  
  146.   
  147.     document.getElementById('lbl_id').innerHTML=id;  
  148.   
  149.     xmlhttpGetById.open("GET","http://localhost:8000/HeroesWebservice/heroesOnline.php?id=" + id,true);  
  150.     xmlhttpGetById.send();  
  151. }  
  152.   
  153. var remove=function(id){      
  154.           
  155.      //Send data to the server as a POST request  
  156.     xmlhttp.open("DELETE","http://localhost:8000/HeroesWebservice/heroesOnline.php",true);  
  157.       
  158.     xmlhttp.send("id=" + id);  
  159.   
  160.     selectAllHeroes();  
  161. }  
  162.   
  163.   
  164. //Fire this onkeyup for txtSearch  
  165. var search=function(filter){  
  166.       
  167.     //Apply filter when txtSearch is not empty  
  168.     if (filter!=""){  
  169.   
  170.         matchedHeroes=heroes.filter(  n=>n.name.toLowerCase().search(  filter  )!=-1   );  
  171.         drawPanels(matchedHeroes);  
  172.     } else{  
  173.   
  174.         drawPanels(heroes);  
  175.     }      
  176.   
  177. }  
Note, the relative path to the Web service can be used too, but take care about the folder structure and hierarchy to get both the parts connected together.

I hope, this is useful and let me know, if you still have any questions or need any clarifications

Enjoy coding. 
 
Download the full code here.
X

Build smarter apps with Machine Learning, Bots, Cognitive Services - Start free.

Start Learning Now