Why doesn't ng-repeat update dynamically? - php

I've literally checked out every single ng-repeat question out there but a lot of them don't deal with databases and people just use arrays in JS and a simple $scope.array.push("stuff") works for them.
I've tried $scope.apply, $rootScope and even calling the GET request right after a successful POST request.
I have a form with 2 text inputs, date and content.
When the submit button is pressed, date and content are added into a MySQL database using PHP.
The data is added just fine to the MySQL database and retrieving also works properly.
Even the GET request inside the successful POST request is executed.
So I don't understand why it forces me to refresh the page to see the updated ng-repeat results.
Am I missing something?
Any help or suggestions is greatly appreciated, thanks!
Relevant HTML code
<div ng-controller="insertController">
<h2> What I learned today </h2>
<form>
Date <br>
<input type="text" ng-model="date"><br><br>
Content <br>
<textarea rows="10" cols="50" ng-model="content"></textarea><br><br>
<input type="button" value="Submit" ng-click="insertdata()">
</form>
</div>
<div ng-controller="fetchController">
<span ng-repeat="item in results">
{{item.date}}<br>
{{item.content}}<br><br>
</span>
</div>
insertController.js
var app = angular.module('myApp', []);
app.controller('insertController', function($scope, $http) {
$scope.insertdata = function() {
$http({
method: 'POST',
url: 'http://localhost/storestuff/insert.php',
data: {'date':$scope.date, 'content':$scope.content, 'in':'json-format'},
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
.then(function(res) {
console.log("Successful response", res)
$scope.date = "";
$scope.content = "";
$http.get('http://localhost/storestuff/fetch.php')
.then(function successCallback(response) {
alert("GOT NEW DATA");
$scope.results = response.data; // Allow angular to access the PHP output data
});
$scope.apply;
})
.catch(function(err) {
console.error("Error with POST", err);
});
}
});
insert.php
<?php
header('Access-Control-Allow-Origin: *');
$theConnection = mysqli_connect("localhost", "root", "", "storestuff");
if(mysqli_connect_errno()) {
echo "Failed to connect to MySQL.";
}
$theData = json_decode(file_get_contents('php://input'));
$date = mysqli_real_escape_string($theConnection, $theData->date);
$content = mysqli_real_escape_string($theConnection, $theData->content);
mysqli_query($theConnection, "INSERT INTO thestuff(date, content) VALUES('$date', '$content')");
mysqli_close($theConnection);
?>
fetchController.js
app.controller('fetchController', function ($scope, $http) {
$http.get('http://localhost/storestuff/fetch.php')
.then(function successCallback(response) {
$scope.results = response.data; // Allow angular to access the PHP output data
});
});
fetch.php
<?php
header('Access-Control-Allow-Origin: *'); // clientside(Node) <-> serverside(PHP)
$mysqli = new mysqli("localhost", "root", "", "storestuff");
if($mysqli->connect_error) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}
$query = "SELECT * FROM thestuff";
$theData = array();
if($result = $mysqli->query($query)) {
while($row = mysqli_fetch_array($result)) {
$theData[] = array(
'date'=>$row['date'],
'content'=>$row['content']);
}
echo json_encode($theData); // Echo the output for the controller to access
$result->free(); // Free the result set
}
else {
echo "0 results.";
}
$mysqli->close(); // Close the connection
?>

The problem with this code is that you have two different controllers, both with separate scopes. Inserting/updating the $scope.results object/array in one controller, will not update the other $scope; they are separate distinct scopes, both with a copy of the data.
Using two controllers looks correct in your use case. However you should be using a service to access your remote data. Check out this answer for some advice on this https://stackoverflow.com/a/20181543/2603735.
Using a service like in that answer, will allow you to store the array/object of remote data in one place, and reference the SAME object from both controllers. Therefore updating from one controller, will also update the other.

For anyone who will ever stumble on my question, I don't want to just leave my broken code there with no answer but neither can I edit the question and put in my answer cause that would defy the purpose of StackOverflow.
So here is my answer to my own question.
I had to make quite a few changes to what I had before. The biggest change by far, is how I handled the data that was returned by fetch.php.
Instead of just taking the output into $scope.results = response.data;, which would work fine if I wasn't dynamically adding to the database, but for this case, I ended up using a service. (Thanks #jayden-meyer for suggesting Angular services.)
The service allowed me to access the same array from my insertController and from my fetchController instead of having a copy of the same array in both controllers which was my problem.
No changes in the HTML code.
No changes to insert.php.
No changes to fetch.php.
insertController.js
I removed the extraneous GET request I had inside the .then method which was completely unneeded since I can just push to the existing array.
(Thanks #charlietfl for the tip)
Instead I added resultsService.addItem($scope.date, $scope.content); inside of the .then method.
I also added my service as an argument.
app.controller('insertController', function($scope, $http, resultsService) {
result.js
app.service('resultsService', function() {
var results = new Array();
var addItem = function(date, content) {
var obj = new Object();
obj["date"] = date;
obj["content"] = content;
results.push(obj);
}
var getItems = function() {
return results;
}
return {
addItem: addItem,
getItems: getItems
};
});
fetchController.js
var size = 0;
var count = 0;
app.controller('fetchController', function ($scope, $http, resultsService) {
$http.get('http://localhost/storestuff/fetch.php')
.then(function successCallback(response) {
size = (response.data).length;
while(count < size) {
var date = response.data[count].date;
var content = response.data[count].content;
resultsService.addItem(date, content);
count++;
}
size = 0;
count = 0;
$scope.results = resultsService.getItems();
});
});

Related

Using MySQL results in javascript

I have a web application where I need to get values from a MySQL database.
The series of event is as follows:
PHP code creates HTML page (works fine)
Click a button on the page, updating a cookie (works fine)
Use cookie in a MySQL query (This does not work)
Get a record from the above MySQL query result and pass to HTML page with jQuery
The problem with bullet 3 is that the MySQL query is only run when I load the page (of course). But I need a method to run a query, based on user input (stored as the cookie), without reloading the PHP script.
How can this be done?
My engineering c-coding brain has a really hard time wrapping this ajax thing. Here is the code so far, still not working:
The popup(HTML) I want to update with new strings when a button on the same page, is clicked:
<div id="popup" class="popup" data-popup="popup-1">
<div class="popup-inner">
<h2 id="popup-headline"></h2> //Headline, created from a cookie. Could be "Geography"
<div id="dialog"></div> //From Will's suggestion
<p id="question"></p> //String 1 from online MySQL DB goes here "A question in Geography"
<p id="answer"></p> //String 2 from online MySQL DB goes here "The answer to the question"
<p class="popup-small-button"><a data-popup-close="popup-1" href="#"><br>Close</a></p> // Hides the popup
<a class="popup-close" data-popup-close="popup-1" href="#">x</a>
</div>
</div>
Then i have my file with custom functions. It executes whenever the popup is shown:
<script>
jQuery(function() {
jQuery('[data-popup-open]').on('click', function(e) {
function myfunction(myparams) {
// your logic here: testing myparams for valid submission, etc.
alert("hey");
jQuery.ajax({
type: 'post',
url: 'server.php',
data: {
my_var1: 'question',
my_var2: 'answer'
},
success: function(data) {
data = JSON.parse(data);
jQuery('#question').html(data["question"]);
jQuery('#answer').html(data["answer"]);
},
error: function(jqxhr, status, exception) {
alert('Exception:', exception);
}
});
}
});
});
</script>
My server.php file contains now this:
<?php
require("db.php");
if(isset($_POST['my_var1']) && isset($_POST['my_var2'])) {
myfunction($_POST['my_var1'], $_POST['my_var2']);
}
?>
And my db.php contains this:
<?php
function myfunction($var1, $var2) {
$db = mysqli_connect('MyOnlineSQLPath','username','password','database1_db_dk');
$stmt = $db->prepare("SELECT question, answer FROM t_da_questions WHERE category_id=?;");
$stmt->bind_param("s", $_COOKIE('category'));
$stmt->execute();
$retval = false;
if($result->num_rows > 0) {
$row = $result->fetch_assoc();
if(!is_null($row['question']) && !is_null($row['answer'])) {
$retval = new stdClass();
$retval->question = row['question'];
$retval->answer = row['answer'];
}
}
mysqli_close($db);
return $retval;
}
?>
What I need, is the "question" and "answer" from the SELECT query.
TL;DR I need question and answer strings to go into <p id="question"></p> and <p id="answer"></p> in the HTML, both without refreshing the page. The getCookie('category') is a cookie stored locally - It contains the last chosen category for a question. The function getCookie('category') returns an integer.
Let me know if you need any more info on this.
Here is some template AJAX that may help you out. I used this in another project. This won't require a page refresh. You will have to include the code to send your cookie's data in the 'data' section.
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<meta charset="utf-8">
</head>
<body>
// your HTML here
<script>
<div id="dialog"></div>
function myfunction(myparams) {
// your logic here: testing myparams for valid submission, etc.
$.ajax({
type: 'post',
url: 'myphpfile.php',
data: {
my_var1: 'myval',
my_var2: 'myval2'
},
success: function(data) {
$("#dialog").html("<span>Success!</span>");
$("#dialog").fadeIn(400).delay(800).fadeOut(400);
}
});
}
</script>
</body>
</html>
Then in the file 'myphpfile.php', you'll have code like the following:
<?php
require("../mycodebase.php");
if(isset($_POST['my_var1']) && isset($_POST['my_var2'])) {
myfunction($_POST['my_var1'], $_POST['my_var2']);
}
?>
Finally, in mycodebase.php (which is stored in a place inaccessible to the public/world), you'll have a function that actually runs your query and returns your result:
function myfunction($var1, $var2) {
$db = mysqli_connect('localhost','myuser','mypass','dbname');
$stmt = $db->prepare("UPDATE mytbl SET col1=? WHERE col2=?;");
$stmt->bind_param("ss", $var1, $var2);
$stmt->execute();
$result = (($db->affected_rows) > 0);
mysqli_close($db);
return $result;
}
UPDATE
That function above is to run an UPDATE query, so the result returned just indicates whether you successfully updated your data or not. If you want to return an actual result, you have to extract the result from the query as follows:
function myfunction($cat) {
$db = mysqli_connect('localhost','myuser','mypass','dbname');
$stmt = $db->prepare("SELECT question, answer FROM t_da_questions WHERE category_id=?;");
$stmt->bind_param("s", $cat);
$stmt->execute();
$retval = false;
if($result->num_rows > 0) {
$row = $result->fetch_assoc();
if(!is_null($row['question']) && !is_null($row['answer'])) {
$retval = new stdClass();
$retval->question = row['question'];
$retval->answer = row['answer'];
}
}
mysqli_close($db);
return $retval;
}
Then your server.php file will look like:
<?php
require("db.php");
if(isset($_COOKIE['category'])) {
json_encode(myfunction($_COOKIE['category']));
}
?>
Here's the JS:
jQuery('[data-popup-open]').on('click', function(e) {
function myfunction(myparams) {
// your logic here: testing myparams for valid submission, etc.
alert("hey");
jQuery.ajax({
type: 'post',
url: 'server.php',
// data section not needed (I think), getting it from the cookie
success: function(data) {
data = JSON.parse(data);
jQuery('#question').html(data["question"]);
jQuery('#answer').html(data["answer"]);
}
});
}
});
This is untested -- I may have gotten an argument wrong, but this is at least very close if it's not already there.

How to get data using php and angylarJS

I hope that you are in good mood :). I'm trying to return data which depend on text from user using AngularJS and php. So I create file php which contain my query and using $http.get in AngularJS. My problem is I want to integrate value of input in mysql query, but always using angular. I tried many times but nothing works To be more clear, here is muy code:
app.js
app1.controller('autoCompleteCTRL',function($scope,$rootScope,$http) {
$scope.search = function(){
$scope.$watch('searchText', function() {
console.log($scope.searchText);
});
$http({
method: "get",
url: "../SearchResultsQuery.php",
dataType: 'json',
data: { 'userText': $scope.searchText},
async: false,
params: {action: "get"}
}).success(function(data, status, headers, config) {
alert(data);
}).error(function(data, status, headers, config) {
alert(error);
});
};
}
index.html
<input type="text" placeholder="Search for items" id="textFiled" class="input" ng-model="searchText" ng-change="search()" />
app.php
<?php
$conn=pgsqlCon();
$searchText = mysql_real_escape_string(userText);
$query='SELECT * FROM planet_osm_roads AS a, to_tsquery_partial(\'%.$searchText.%\') AS query
WHERE ts_road ## query';
$result = pg_query($conn,$query);
$myarray = array();
while ($row = pg_fetch_row($result)) {
$myarray[] = $row;
}
pg_close($conn);
echo json_encode($myarray);
?>
I hope that you understand me Thanks for advance :)
try to make your http request like this:
app.controller('TestCtrl', function ($scope, $http){
$scope.search = function(){
$http.post('../app.php', {searchText: $scope.searchText})
.success(function (response){
console.log(response);
})
.error(function (response){
console.log(response);
});
}
});
app.php
<?php
$data = file_get_contents("php://input");
$searchText = mysql_real_escape_string($data['searchText']);
/* database code */
?>
This should work.
In your app.js file, instead of this line:
data: { 'userText': $scope.searchText}
write:
params: { 'userText': $scope.searchText}
and remove this line:
params: {action: "get"}
This way it will transfer userText variable through request URL as a GET parameter.
In your app.php file, instead of:
$searchText = mysql_real_escape_string(userText);
write:
$searchText = mysql_real_escape_string($_GET['userText']);
This will populate your $searchText php variable with text from client application (AngularJS). I'm not sure about your postgresql query. Your question title is mysql - How to get data..., but in your php code sample you use postgres extension to build query. But that's a different story I guess.

combining angular js and php - failed insert data into database

its been two days since i start to learning about angular js.
its quite fun actually. fyi, im still using static data.
it means nothing when you cant manipulate database rite?
so i jump into the next step. connect it with my db. im using regular php.
if success, i will jump into next step, combining angular and php framework like laravel or codeigniter.
actually, its quit easy to retrieve data from database.
but, im here not to share that story, i found difficulties when trying to input it into database. i dont understand why. the point is i cant get the data from the form in html. im using factory in angular.
here is my add.html :
<h1>add newdata</h1>
new name :
<input type='text' ng-model='newdata.name'> <br>
new city :
<input type='text' ng-model='newdata.city'> <br>
<button ng-click='addData()'>submit</button>
here is my index.html :
//define dependency ngRoute module
var test = angular.module('testPeople', ['ngRoute']);
test.factory('factoryPeople', function($http) {
var factoryPeople= {};
factoryPeople.getPeople = function() {
return $http.get('data.php');
};
factoryPeople.addPeople = function() {
return $http.post('add.php');
};
return factoryPeople;
});
routes :
test.config(function($routeProvider) {
$routeProvider
.when('/add', {
templateUrl : 'add.html',
controller : 'add'
})
.when('/contact', {
templateUrl : 'contact.html'
})
.when('/second', {
templateUrl : 'index2.html'
})
.otherwise({redirectTo: '/'});
});
controller :
test.controller('add', function($scope, $http, factoryPeople){
$scope.tambahData = function() {
//bikin format file json, dari hasil tangkapan form di file add.html
databaru = {
name: $scope.newdata.name,
city: $scope.newdata.city
}
factoryPeople.addPeople(newdata).success(function(result) {
//update data using push method
$scope.listofname.push({
name: $scope.newdata.name,
city: $scope.newdata.city
});
//set form data empty again
$scope.newdata.name= '';
$scope.newdata.city = '';
alert(result);
});
here is my add.php :
<?php
header("Access-Control-Allow-Origin: *");
$host = "localhost";
$user = "root";
$pass = "";
$db = "angular";
$link = mysqli_connect($host, $user, $pass, $db) or die(mysqli_error($link));
// get input data
$data = json_decode(file_get_contents("php://input"));
// take value from array
$name= $data['name'];
$city= $data['city'];
// query insert
$sql = "insert into users (name , city) values ('$name', '$city') ";
// echo message
if(mysqli_query($link, $sql)):
echo"input success| name: $name| city: $city";
else: echo"input failed| name : $name | city: $city";
endif;
?>
if i run that script, data will always succesfully insert into database.
but the problems is $name and $city has no value.
i dont understand why.
am i wrong using php_get_contents or what?
can you guys tell me what should i do in order to get a better result?
Hope you guys can help me.
Thanks a lot.
You forgot to pass the parameters. Change your factory (addPeople() function):
factoryPeople.addPeople = function(data) {
return $http.post('add.php', data);
};
And then just use $_POST on the server like you usually (I guess) do

Problems populating a select list with angular js and php

I am trying to populate a select list with data from my db (php & mysql). I am working with AngularJs and Angular Material. So for i am not able to show the data from the db in the list
db situation:
tblProjectType -> name of table
2 rows:
id_ProjectType
project_type
Any help or pointers would be great.
This is my html code:
<form ng-controller="AppCtrl">
<div layout="row">
<md-select-label>Project type</md-select-label>
<md-select ng-model="project_type" name="project_type" placeholder="Choose a project type" id="containerProjectType">
<md-option ng-repeat="projecttype in projecttypes" value="{{projecttype.id_ProjectType}}">{{projecttype.project_type}}</md-option>
</md-select>
</div>
</form>
The code of my app.js is:
var app = angular.module("DragDrop", ['ngMaterial']);
app.controller('AppCtrl', function($scope, $mdDialog, $http) {
$scope.projectTypeInfo = [];
var getProjectTypeFunction = function(succesFn, errorFn)
{
$http.get('db.php?action=get_ProjectType_info')// call to the server
.succesFn(function(data){
succesFn(data); //call the function passed into getProjectTypeFunction with the data from the server
console.log('Retrieved data from server');
})
.error(errorFn || function() {
console.log("Error in retrieving data from server");
})
}
this.reloadProjectTypeList = function()
{
getProjectTypeFunction(
/* success function */
function(data) {
//debugger;
$scope.projectTypeInfo = data;
//digest recycle
//if (!$scope.$$phase) { $scope.$apply(); }
},
/* error function */
function()
{
alert("Server load failed");
})
};
My php code is:
<?php
include('config.php');
//echo ('test' . $_GET['action']);
switch($_GET['action']) {
case 'get_ProjectType_info' :
get_ProjectType_info();
break;
}
/** Function to data from tblProjectType **/
function get_ProjectType_info(){
$qry = mysql_query('SELECT * from tblProjectType');
echo("test");
//echo(qry);
$data = array();
while($rows = mysql_fetch_array($qry))
{
$data[] = array(
"id_ProjectType" => $rows['id_ProjectType'],
"project_type" => $rows['project_type']
);
}
print_r(json_encode($data));
return json_encode($data);
}
?>
So for starters lets clean up your JS. We can reduce what you have to this:
var app = angular.module("DragDrop", ['ngMaterial']);
app.controller('AppCtrl', function($scope, $mdDialog, $http)
{
$scope.projectTypeInfo = [];
$scope.getProjectTypeFunction = function()
{
$http.get('db.php?action=get_ProjectType_info')
.success(function(data, status, headers, config)
{
$scope.projectTypeInfo = data;
console.log('Retrieved data from server');
console.log(data);
})
.error(function(data, status, headers, config)
{
console.log("Error in retrieving data from server");
console.log(data,status);
});
};
$scope.getProjectTypeFunction(); //-- call the function that invokes $http.get()
};
In PHP your function needs to echo the data via echo json_encode($data);, not return it (as stated by #Avalanche).
Now, your console should output something, but you need to remove console.log("test"); from your PHP as that will surely cause an error.
edit
Currently your repeat states:
<md-option ng-repeat="projecttype in projecttypes" value="{{projecttype.id_ProjectType}}">{{projecttype.project_type}}</md-option>
We have stored your data in $scope.projectTypeInfo therefore it needs to be modified to:
<md-option ng-repeat="projecttype in projectTypeInfo" ng-value="projecttype.id_ProjectType">{{projecttype.project_type}}</md-option>

Retrieving Data with Jquery, AJAX, and PHP from a MySQL Database

I am trying to figure out how to retrieve data from a MySQL database using an AJAX call to a PHP page. I have been following this tutorial
http://www.ryancoughlin.com/2008/11/04/use-jquery-to-submit-form/
But i cant figure out how to get it to send back json data so that i can read it.
Right now I have something like this:
$('h1').click(function() {
$.ajax({
type:"POST",
url: "ajax.php",
data: "code="+ code,
datatype: "xml",
success: function() {
$(xml).find('site').each(function(){
//do something
});
});
});
My PHP i guess will be something like this
<?php
include ("../../inc/config.inc.php");
// CLIENT INFORMATION
$code = htmlspecialchars(trim($_POST['lname']));
$addClient = "select * from news where code=$code";
mysql_query($addClient) or die(mysql_error());
?>
This tutorial only shows how to insert data into a table but i need to read data. Can anyone point me in a good direction?
Thanks,
Craig
First of all I would highly recommend to use a JS object for the data variable in ajax requests. This will make your life a lot simpler when you will have a lot of data. For example:
$('h1').click(function() {
$.ajax({
type:"POST",
url: "ajax.php",
data: { "code": code },
datatype: "xml",
success: function() {
$(xml).find('site').each(function(){
//do something
});
});
});
As for getting information from the server, first you will have to make a PHP script to pull out the data from the db. If you are suppose to get a lot of information from the server, then in addition you might want to serialize your data in either XML or JSON (I would recomment JSON).
In your example, I will assume your db table is very small and simple. The available columns are id, code, and description. If you want to pull all the news descriptions for a specific code your PHP might look like this. (I haven't done any PHP in a while so syntax might be wrong)
// create data-structure to handle the db info
// this will also make your code more maintainable
// since OOP is, well just a good practice
class NewsDB {
private $id = null;
var $code = null;
var $description = null;
function setID($id) {
$this->id = $id;
}
function setCode($code) {
$this->code = $code;
}
function setDescription($desc) {
$this->description = $desc;
}
}
// now you want to get all the info from the db
$data_array = array(); // will store the array of the results
$data = null; // temporary var to store info to
// make sure to make this line MUCH more secure since this can allow SQL attacks
$code = htmlspecialchars(trim($_POST['lname']));
// query
$sql = "select * from news where code=$code";
$query = mysql_query(mysql_real_escape_string($sql)) or reportSQLerror($sql);
// get the data
while ($result = mysql_fetch_assoc($query)) {
$data = new NewsDB();
$data.setID($result['id']);
$data.setCode($result['code']);
$data.setDescription($result['description']);
// append data to the array
array_push($data_array, $data);
}
// at this point you got all the data into an array
// so you can return this to the client (in ajax request)
header('Content-type: application/json');
echo json_encode($data_array);
The sample output:
[
{ "code": 5, "description": "desc of 5" },
{ "code": 6, "description": "desc of 6" },
...
]
So at this stage you will have a PHP script which returns data in JSON. Also lets assume the url to this PHP script is foo.php.
Then you can simply get a response from the server by:
$('h1').click(function() {
$.ajax({
type:"POST",
url: "foo.php",
datatype: "json",
success: function(data, textStatus, xhr) {
data = JSON.parse(xhr.responseText);
// do something with data
for (var i = 0, len = data.length; i < len; i++) {
var code = data[i].code;
var desc = data[i].description;
// do something
}
});
});
That's all.
It's nothing different. Just do your stuff for fetching data in ajax.php as usually we do. and send response in your container on page.
like explained here :
http://openenergymonitor.org/emon/node/107
http://www.electrictoolbox.com/json-data-jquery-php-mysql/

Categories