Josh Crocker
Josh Crocker

Reputation: 41

AngularJS pass form array to php

I am struggling to get this form to work was wondering if anyone can give me any ideas why! So what I have is an index page with an ng-app=especial. In the DIV main_area_holder goes the ng_view. The Ng-view displays fine and form displays on index page (from localtion app/partials/cust_form.php). What I am struggling to get working is the http request to php file so I can import form data into DB. I know the php code works without ajax (straight post request). If you can help out I would be very grateful.

app.js UPDATED

var especial = angular.module('especial', ['ngRoute']);

especial.config(function($routeProvider) {
$routeProvider.when('/',
    {
        controller: 'custPage',
        templateUrl: 'app/partials/cust_form.tpl.html'
    });
});

especial.config(function($httpProvider) {
$httpProvider.defaults.transformRequest = function(request){
    if(typeof(request)!='object'){
        return request;
    }
    var str = [];
    for(var k in request){
        if(k.charAt(0)=='$'){
            delete request[k];
            continue;
        }
        var v='object'==typeof(request[k])?JSON.stringify(request[k]):request[k];
        str.push(encodeURIComponent(k) + "=" + encodeURIComponent(v));
    }
    return str.join("&");
};
$httpProvider.defaults.timeout=10000;
$httpProvider.defaults.headers.post = {
    'Content-Type': 'application/x-www-form-urlencoded',
    'X-Requested-With': 'XMLHttpRequest'
};
});
especial.controller('custPage', function($scope, $http){
    $scope = {};
    $scope.custCreUpd = function(){
        $http({
            method: 'POST',
            url: 'app/php/cust_cre_upd.php',
            data: $scope.cust,
            headers : {'Content-Type': 'application/x-www-form-urlencoded'}
        }).success(function(data){

            console.log("OK", data)

        }).error(function(err){"ERR", console.log(err)})
    };
});

cust_cre_upd.php

<?php

        $post = file_get_contents("php://input");
        $values = json_decode($post, true);
        $table='customers';
        $conn = new PDO('mysql:host=localhost;dbname=displaytrends;charset=utf8', 'displaytrends', 'displaytrends');
        $conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
                    //Strip array to fields with values     
        $values=array_filter($values);
                    //Take array keys from array
        $field_keys=array_keys($values);
                    //Implode for insert fields
        $ins_fields=implode(",", $field_keys);
                    //Implode for insert value fields (values will binded later)
        $value_fields=":" . implode(", :", $field_keys);
                    //Create update fields for each array create value = 'value = :value'.
        $update_fields=array_keys($values);
        foreach($update_fields as &$val){
            $val=$val." = :".$val;
        }
        $update_fields=implode(", ", $update_fields);
                    //SQL Query
        $insert = "INSERT INTO $table ($ins_fields) VALUES ($value_fields) ON DUPLICATE KEY UPDATE $update_fields";
        $query = $conn->prepare($insert);
                    //Bind each value based on value coming in.
        foreach ($values as $key => &$value) {
            switch(gettype($value)) {
                case 'integer':
                case 'double':
                $query->bindParam(':' . $key, $value, PDO::PARAM_INT);
                break;
                default:
                $query->bindParam(':' . $key, $value, PDO::PARAM_STR);
            }
        }
        $query->execute();

    ?>

index.php

<!doctype html>
<html ng-app="especial">
<head>
<meta charset="UTF-8">
<title>Especial - Database</title>
<link rel="stylesheet" href="css/index.css">
<script src="scripts/angular.js"></script>
<script src="scripts/angular-route.js"></script>
<script src="scripts/angular-animate.js"></script>
</head>

<body>
<div class="header">
<img id="logo" src="images/especial-logo.jpg">
<a id="logout" href="logout.php">Logout</a>
<div class="menu"></div>
</div>
<div class="sub_menu"></div>

<div class="main_area">
    <div id="main_area_holder" ng-view>
    </div>
</div>
<div class="footer"></div>
<script src="app/app.js"></script>
</body>
</html>

cust_form.php

<div ng-controller="custPage">
<div id="form">
        <form name="cust_form">   
           <label>Account No:</label>
           <input type="text" ng-model="cust.int_custID" name="cust[int_custID]" id="int_custID"/>
           <label>Company:</label>
           <input type="text" ng-model="cust.cust_company" name="cust[cust_company]" id="cust_company"/>
            <label>Address:</label>
            <textarea type="text" rows=5 ng-model="cust.cust_address" name="cust[cust_address]" id="cust_address"></textarea>
            <label>Postcode:</label>
            <input type="text" ng-model="cust.cust_postcode" name="cust[cust_postcode]" id="cust_postcode"/>
            <label>Contact 1:</label>
            <input type="text" ng-model="cust.cust_contact_1" name="cust[cust_contact_1]" id="cust_contact_1"/>
            <label>Contact 2:</label>
            <input type="text" ng-model="cust.cust_contact_2"  name="cust[cust_contact_2]"  id="cust_contact_2"/>
            <label>Telephone:</label>
            <input type="text" ng-model="cust.cust_tel" name="cust[cust_tel]" id="cust_tel"/>
            <label>Mobile:</label>
            <input type="text" ng-model="cust.cust_mob" name="cust[cust_mob]" id="cust_mob"/>
            <label>DDI:</label>
            <input type="text" ng-model="cust.cust_DDI" name="cust[cust_DDI]" id="cust_DDI"/>
            <label>Email:</label>
            <input type="email" ng-model="cust.cust_email" name="cust[cust_email]" id="cust_email"/>
            <label>Notes:</label>
            <textarea type="text" rows=5 colums=1 ng-model="cust.cust_notes"  name="cust[cust_notes]" id="cust_notes"></textarea>

           <button type="submit" ng-click="custCreUpd()"> Submit </button>
       </form>
</div>
</div>

Upvotes: 1

Views: 2164

Answers (3)

danzeer
danzeer

Reputation: 86

app.js:

var especial = angular.module('especial', ['ngRoute']);

especial.config(function($routeProvider) {
    $routeProvider.when('/',
    {
        controller: 'custPage',
        templateUrl: 'app/partials/cust_form.tpl.html'
    });
});

especial.config(function($httpProvider) {
$httpProvider.defaults.transformRequest = function(request){
    if(typeof(request)!='object'){
        return request;
    }
    var str = [];
    for(var k in request){
        if(k.charAt(0)=='$'){
            delete request[k];
            continue;
        }
        var v='object'==typeof(request[k])?JSON.stringify(request[k]):request[k];
        str.push(encodeURIComponent(k) + "=" + encodeURIComponent(v));
    }
    return str.join("&");
};
$httpProvider.defaults.timeout=10000;
$httpProvider.defaults.headers.post = {
    'Content-Type': 'application/x-www-form-urlencoded',
    'X-Requested-With': 'XMLHttpRequest'
};
});
especial.controller('custPage', function($scope, $http){
   $scope.cust = {};
   $scope.custCreUpd = function(){
    $http({
        method: 'POST',
        url: 'app/php/cust_cre_upd.php',
        data: $scope.cust,
        headers : {'Content-Type': 'application/x-www-form-urlencoded'}
    }).success(function(data){
        console.log(data)
    }).error(function(err){
        console.log(err)
    })
};
});

cust_cre_upd.php

<?php
//print_r($_POST); you can print_r it for understanding
//use $_POST as usual, example $_POST["cust_ID"] means your     
$values = $_POST;
$conn = new PDO('mysql:host=localhost;dbname=displaytrends;charset=utf8', 'displaytrends', 'displaytrends');
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
//Strip array to fields with values
$values=array_filter($values);
//Take array keys from array
$field_keys=array_keys($values);
//Implode for insert fields
$ins_fields=implode(",", $field_keys);
//Implode for insert value fields (values will binded later)
$value_fields=":" . implode(", :", $field_keys);
//Create update fields for each array create value = 'value = :value'.
$update_fields=array_keys($values);
foreach($update_fields as &$val){
    $val=$val." = :".$val;
}
$update_fields=implode(", ", $update_fields);
//SQL Query
$insert = "INSERT INTO $table ($ins_fields) VALUES ($value_fields) ON DUPLICATE KEY UPDATE $update_fields";
$query = $conn->prepare($insert);
//Bind each value based on value coming in.
foreach ($values as $key => &$value) {
    switch(gettype($value)) {
        case 'integer':
        case 'double':
            $query->bindParam(':' . $key, $value, PDO::PARAM_INT);
            break;
        default:
            $query->bindParam(':' . $key, $value, PDO::PARAM_STR);
    }
}
$query->execute();

index.php:

<!doctype html>
<html ng-app="especial">
<head>
    <meta charset="UTF-8">
    <title>Especial - Database</title>
<!--    <link rel="stylesheet" href="css/index.css">-->
    <script src="scripts/angular-1.3.8.min.js"></script>
    <script src="scripts/angular-route.min.js"></script>
<!--    <script src="scripts/angular-animate.js"></script>-->
</head>

<body>
<div class="header">
    <img id="logo" src="images/especial-logo.jpg">
    <a id="logout" href="logout.php">Logout</a>
    <div class="menu"></div>
</div>
<div class="sub_menu"></div>

<div class="main_area">
    <div id="main_area_holder" ng-view>
    </div>
</div>
<div class="footer"></div>
<script src="app/app.js"></script>
</body>
</html>

cust_form.php (cust_form.tpl.html):

<div id="form">
    <form name="cust_form">
        <label>Account No:</label>
        <input type="text" ng-model="cust.int_custID" id="int_custID"/>
        <label>Company:</label>
        <input type="text" ng-model="cust.cust_company"  id="cust_company"/>
        <label>Address:</label>
        <textarea type="text" rows=5 ng-model="cust.cust_address" id="cust_address"></textarea>
        <label>Postcode:</label>
        <input type="text" ng-model="cust.cust_postcode" id="cust_postcode"/>
        <label>Contact 1:</label>
        <input type="text" ng-model="cust.cust_contact_1"  id="cust_contact_1"/>
        <label>Contact 2:</label>
        <input type="text" ng-model="cust.cust_contact_2"  id="cust_contact_2"/>
        <label>Telephone:</label>
        <input type="text" ng-model="cust.cust_tel" id="cust_tel"/>
        <label>Mobile:</label>
        <input type="text" ng-model="cust.cust_mob" id="cust_mob"/>
        <label>DDI:</label>
        <input type="text" ng-model="cust.cust_DDI" id="cust_DDI"/>
        <label>Email:</label>
        <input type="email" ng-model="cust.cust_email" id="cust_email"/>
        <label>Notes:</label>
        <textarea type="text" rows=5 colums=1 ng-model="cust.cust_notes" id="cust_notes"></textarea>

        <button type="submit" ng-click="custCreUpd()"> Submit </button>
    </form>
</div>

I creat a repository here https://github.com/Danzeer/forJoshCrocker

To debug with script in web browser, you can use chrome's Developer's tools - network (option+command+i in OSX, F12 in window, and chose the network card).When you click submit, you can see request in network card and check http header by clicking the request.

enter image description here enter image description here

Upvotes: 1

danzeer
danzeer

Reputation: 86

I have rewrite your code, that seems sending post. You can compare it with yours:

app.js :

var especial = angular.module('especial', ['ngRoute']);

especial.config(function($routeProvider) {
$routeProvider.when('/',
    {
        controller: 'custPage',
        templateUrl: 'app/partials/cust_form.tpl.html'
    });
});

especial.config(function($httpProvider) {
$httpProvider.defaults.transformRequest = function(request){
    if(typeof(request)!='object'){
        return request;
    }
    var str = [];
    for(var k in request){
        if(k.charAt(0)=='$'){
            delete request[k];
            continue;
        }
        var v='object'==typeof(request[k])?JSON.stringify(request[k]):request[k];
        str.push(encodeURIComponent(k) + "=" + encodeURIComponent(v));
    }
    return str.join("&");
};
$httpProvider.defaults.timeout=10000;
$httpProvider.defaults.headers.post = {
    'Content-Type': 'application/x-www-form-urlencoded',
    'X-Requested-With': 'XMLHttpRequest'
};
});
//when using 1.3.8 version , consider how to write controller with []
especial.controller('custPage', ['$scope', '$http', function($scope, $http){
    $scope.cust = {};
    //$scope = {}; !!!!
    $scope.custCreUpd = function(){ // pay attention of params
        $http({
            method: 'POST',
            url: "app/php/cust_cre_upd.php",
            data: $scope.cust,
            headers : {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
        }).success(function(data){

            console.log("OK", data)

        }).error(function(err){"ERR", console.log(err)})
    };
}]);

index.php:

!doctype html>
<html ng-app="especial">
<head>
<meta charset="UTF-8">
<title>Especial - Database</title>
<script src="js/angular-1.3.8.min.js"></script>
<script src="js/angular-route.min.js"></script>
<!--    <script src="scripts/angular-animate.js"></script>-->
</head>

<body>
   <div id="main_area_holder" ng-view>
    </div>
<script src="app/app.js"></script>
</body>
</html>

custForm.tpl.html(your cust_form.php):

<!--<div ng-controller="custPage"> !none ng-controller when using ng-route-->

<div id="form">
   <form name="cust_form">
       <label>Account No:</label>
       <input type="text" ng-model="cust.int_custID" name="cust[int_custID]" id="int_custID"/>
       <button type="submit" ng-click="custCreUpd()"> Submit </button>
    </form>
</div>

naming custForm.tpl.html instead of cust_form.php seems much meaningful) and request of .php will be pass to php executor by apache/nginx while request for html only through apache/nginx. And pay attention to angular cache problem when using ng-route. -- some tools not relavent https://github.com/karlgoldstein/grunt-html2js and https://github.com/angular-ui/bootstrap, enjoy!

Points: 1 definition of controller

2 post of angularjs

3 how to use ng-view with ng-route

4 params-"$scope" of function custCreUpd hide $scope service

Upvotes: 0

danzeer
danzeer

Reputation: 86

I think you can find answer for "post" here AngularJs $http.post() does not send data

angualr's get works well, but angular's post does not seralize form-data as jquery. my solution (maybe wrong, according to what I have searched) was rewriting angular's httpProvider:

app.config(function($httpProvider) {
    $httpProvider.defaults.transformRequest = function(request){
        if(typeof(request)!='object'){
                return request;
        }
        var str = [];
        for(var k in request){
                if(k.charAt(0)=='$'){
                        delete request[k];
                        continue;
                }
                var v='object'==typeof(request[k])?JSON.stringify(request[k]):request[k];
                str.push(encodeURIComponent(k) + "=" + encodeURIComponent(v));
        }
        return str.join("&");
   };
   $httpProvider.defaults.timeout=10000;
   $httpProvider.defaults.headers.post = {
        'Content-Type': 'application/x-www-form-urlencoded',
        'X-Requested-With': 'XMLHttpRequest'
   };
  });

2 your

ng-click="custCreUpd"

should be

ng-click="custCreUpd()"

3 check the result of below, I'm not familiar with it

$.param($scope.cust)

Upvotes: 0

Related Questions