Reputation: 1252
I have the following form using angular. I want to submit the results to an email address and have set up a php action page with server side code to do this.
However, it feels wrong the way I'm using the action="action.php"
call on the form element. Dirty in fact... but i'm not sure of any other way to this. Is this the best way to submit the form? Should I be using an AJAX call via ng-submit to collect and store the data....
Here's a JSfiddle of the form but without the action="action.php"
- I was experimenting with ng-submit="mealForm.$valid"
.
Below is my code using the action="action.php"
- you'll see I have added the action call in and omitted the ng-submit="mealForm.$valid"
as was unsure how this would work, even after extensive reading of the docs
Any help much appreciated - newbie to angular :)
Thanks
HTML
<!DOCTYPE html>
<html ng-app="form">
<head>
<link rel="stylesheet" type="text/css" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body>
<div class="container" style="margin-top: 40px;">
<section ng-controller="PanelController as panel">
<ul class="nav nav-pills">
<li ng-class="{ active: panel.isSelected(1)}">
<a href ng-click="panel.selectTab(1)">Standard Form</a>
</li>
<li ng-class="{ active: panel.isSelected(2)}">
<a href ng-click="panel.selectTab(2)">Custom Form</a>
</li>
</ul>
<div class="panel" ng-show="panel.isSelected(1)">
<h4>Standard Form</h4>
<p>Use the standard form if the number people and meals are the same throughout your stay.<br />E.G : 10 people wanting 7 dinners over a 7 day period.</p>
<p>Use the custom form if the number of people wanting meals alters each day.</p>
<p><span class="required">*</span> required fields</p>
<form name="mealForm" ng-controller="FormController as form" action="action.php" method="post" novalidate>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label for="firstName">First Name<span class="required"> *</span></label>
<input ng-model="booking.firstName" type="text" class="form-control" id="firstName" name="firstName" placeholder="First Name" required>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label for="lastName">Last Name<span class="required"> *</span></label>
<input ng-model="booking.lastName" type="text" class="form-control" id="lastName" name="lastName" placeholder="Last Name" required>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label for="email">Email<span class="required"> *</span></label>
<input ng-model="booking.email" type="email" class="form-control" id="email" name="email" placeholder="Email" required>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label for="telephone">Phone Number</label>
<input type="text" class="form-control" id="telephone" name="telephone" placeholder="Telephone" required>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label for="startDate">Start Date</label>
<input type="date" class="form-control" name="startDate" id="startDate" required>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label for="endDate">End Date</label>
<input type="date" class="form-control" name="endDate" id="endDate" required>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label for="totalDays">Number of Days <span class="required"> *</span><em>(Discount of 10% Applies for 10 or more days)</em></label>
<select ng-model="booking.totalDays" class="form-control" name="totalDays" id="totalDays" required>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="18">18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="28">28</option>
<option value="29">29</option>
<option value="30">30</option>
</select>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label for="groupSize">Group Size <span class="required"> *</span><em>(max 15)</em></label>
<select ng-model="booking.groupSize" class="form-control" name="groupSize" id="groupSize" required>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label>Meal Type <span class="required"> *</span><em>(Select from below options)</em></label>
<ul>
<li ng-repeat="meal in form.meals" ng-click="form.selectMeal(meal);" ng-class="{active:meal.active}" class="mealType">{{meal.name}} - {{meal.description}} <span>{{meal.price | currency}}</span>
</li>
</ul>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label for="message">Accomodation Details <em>(Please provide full address / specific dietery requirements and any other information)</em></label>
<textarea name="message" id="message"></textarea>
</div>
</div>
</div>
<div class="form-group">
<hr />
<label for="total">
Total: <span>{{form.total(booking.totalDays, booking.groupSize)[0] | currency}}</span> <em ng-show="form.total(booking.totalDays, booking.groupSize)[3]">(10% Discount of <span>{{form.total(booking.totalDays, booking.groupSize)[1] | currency}} applied)</em></span>
</label>
</div>
<div class="form-group">
<div class="form-valid" ng-class="{active: mealForm.$valid}">Form complete: {{mealForm.$valid}}</div>
<hr />
<button type="submit" ng-disabled="mealForm.$invalid" value="Submit" class="btn btn-default">Submit</button>
</div>
<input type="hidden" name="mealType" value="{{form.total()[2]}}">
<input type="hidden" name="total" id="total" value="{{form.total(booking.totalDays, booking.groupSize)[0] | currency}}">
<input type="hidden" name="discount" value="{{form.total(booking.totalDays, booking.groupSize)[1] | currency}}">
</form>
</div><!-- /.panel -->
<div class="panel" ng-show="panel.isSelected(2)">
</div>
</section>
</div>
</body>
</html>
ANGULAR JS (APP.JS) EDITED
(function () {
var app = angular.module('form', []);
// start of edit
app.controller('FormController', ['$scope','$window',
function($scope,$window){
this.meals = mealTypes;
$scope.handleFormSubmit = function (booking) {
$http.post('action.php', booking).success(function (data, status) {
if (data.success) {
$window.alert("Thank you! Your message has been sent.");
}
}).error(function (data, status) {
$window.alert("Sorry, there was a problem! " + data.message);
});
};
// end of edit
this.selectMeal = function (setMeal) {
if (!setMeal.active) {
angular.forEach(this.meals, function (s) {
s.active = false;
});
setMeal.active = true;
}
};
this.total = function (days, size) {
var total = 0;
var percentage = 0;
var mealType;
var discount = false;
total = days * size;
angular.forEach(this.meals, function (s) {
if (s.active) {
total *= s.price;
mealType = s.name + ' - ' + s.description;
}
});
if (days >= 10) {
percentage = (total / 100) * 10;
total -= percentage;
discount = true;
}
return [total, percentage, mealType, discount];
};
});
var mealTypes = [{
name: 'breakfast',
price: '20',
description: 'Three course breakfast',
active: true
}, {
name: 'dinner',
price: '20',
description: 'Three course dinner',
active: false
}, {
name: 'both',
price: '40',
description: 'Breakfast and Dinner',
active: false
}
];
app.controller('PanelController', function () {
this.tab = 1;
this.selectTab = function (setTab) {
this.tab = setTab;
};
this.isSelected = function (checkTab) {
return this.tab == checkTab;
};
});
})();
PHP (ACTION.PHP)
<?php
if(isset($_POST['email'])) {
// EDIT THE 2 LINES BELOW AS REQUIRED
$email_to = "[email protected]";
$email_subject = "Subject line";
function died($error) {
echo "We are very sorry, but there were error(s) found with the form you submitted. ";
echo "These errors appear below.<br /><br />";
echo $error."<br /><br />";
echo "Please go back and fix these errors.<br /><br />";
die();
}
$firstName = $_POST['firstName'];
$lastName = $_POST['lastName'];
$email_from = $_POST['email'];
$telephone = $_POST['telephone'];
$startDate = $_POST['startDate'];
$endDate = $_POST['endDate'];
$totalDays = $_POST['totalDays'];
$groupSize = $_POST['groupSize'];
$mealType = $_POST['mealType'];
$discount = $_POST['discount'];
$total = $_POST['total'];
$email_message = "Form details below.\n\n";
function clean_string($string) {
$bad = array("content-type","bcc:","to:","cc:","href");
return str_replace($bad,"",$string);
}
$email_message .= "First Name: ".clean_string($firstName)."\n";
$email_message .= "Last Name: ".clean_string($lastName)."\n";
$email_message .= "Email: ".clean_string($email_from)."\n";
$email_message .= "Telephone: ".clean_string($telephone)."\n";
$email_message .= "Start Date: ".clean_string($startDate)."\n";
$email_message .= "End Date: ".clean_string($endDate)."\n";
$email_message .= "Total Days: ".clean_string($totalDays)."\n";
$email_message .= "Group Size: ".clean_string($groupSize)."\n";
$email_message .= "Meal Type: ".clean_string($mealType)."\n";
$email_message .= "Discount: ".clean_string($discount)."\n";
$email_message .= "Total: ".clean_string($total)."\n";
// create email headers
$headers = 'From: '.$email_from."\r\n".
'Reply-To: '.$email_from."\r\n" .
'X-Mailer: PHP/' . phpversion();
@mail($email_to, $email_subject, $email_message, $headers);
?>
Thank you for contacting us. We will be in touch with you very soon.
<?php
}
?>
Upvotes: 0
Views: 1135
Reputation: 172
For submit you can do a ng-click
<input type="text" size="40" ng-model="email"><br>
<input type="text" size="40" ng-model="msg"><br>
<button type="submit" ng-disabled="mealForm.$invalid" ng-click="SendEmail()" value="Submit" class="btn btn-default">Submit</button>
next you need send a http post
$scope.SendEmail= function () {
var request = $http({
method: "post",
url: window.location.href + "send.php",
data: {
email: $scope.email,
msg: $scope.msg
},
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
/* Check whether the HTTP Request is successful or not. */
request.success(function (data) {
document.getElementById("message").textContent = "You send email successfully "+data;
});
}
in Send.php
$postdata = file_get_contents("php://input");
$request = json_decode($postdata);
@$email= $request->email;
@$msg = $request->msg;
// all code for send email and next you can return a value if email is sending, with return "Msg is Sending", and you can capture it in request.success
PD: for return value from Php to Javascript only use return value;
and next you can work in
request.success(function (data) {... where data=value;
Upvotes: 0
Reputation: 1304
You can use an $http.post(...)
request in AngularJS. This will allow you to receive a response and show a success message, without having to reload the page.
If you want to go that route, I suggest adding a ng-model="params.fieldName"
attribute to each field (just change fieldName
to match the value passed to the PHP form). Then in your controller, you could do something like:
$scope.handleFormSubmit = function (params) {
$http.post('action.php', params).success(function (data, status) {
if (data.success) {
$window.alert("Thank you! Your message has been sent.");
}
}).error(function (data, status) {
$window.alert("Sorry, there was a problem! " + data.message);
});
};
Then in your <form ...>
tag you could do something like:
<form ng-submit="handleFormSubmit(params)" ...>
Then in your PHP script, you just need to output a JSON object with the variables you want to pass to AngularJS.
<?php echo json_encode({success: false, message: "Couldn't send email"}); ?>
Ideally instead of using $window.alert(...)
you would display some sort of inline message instead. If the form was successfully sent, you could also hide it as well to prevent a user from sending it a second time. You also should do something with the submit button, to disable it, while the form is being sent, so it can't be clicked more than once.
Also, instead of returning a value from PHP, you can return a status code instead:
<?php http_response_code(400); ?>
If it's in the 200-range, it will activate the .success(...)
callback. If it's in the 400-range, it will activate the .error(...)
callback. You can check what each status code means.
Upvotes: 1