Reputation: 21
I have been trying to solve this and have been looking everywhere. Apologies in advance if this sounds stupid or there is a duplicate question somewhere that I have missed.
I am trying to create dynamic email content and send the email via php mail. I want to use angularJS to compile the html content and using $http.post method send to a submit.php to send email.
I can manually enter in the html content in php and no problem but having a compiled dynamic html is the issue.
I am really not too sure how to tackle this, so any help would be much appreciated.
Thanks,
My angular controller:
$scope.url = 'submit.php';
$scope.formsubmit = function(isValid) {
if (isValid) {
$http.post($scope.url, {"name": $scope.name, "email": $scope.email, "message": $scope.message }).
success(function(data, status) {
console.log(data);
$scope.status = status;
$scope.data = data;
$scope.result = data;
})
}
}
submit.php
$post_date = file_get_contents("php://input");
$data = json_decode($post_date);
$to = $data->email;
$from = "[email protected]";
$name = $data->name;
$subject = "Email from AngularJS";
$htmlContent = $data->message;
I have added my code below :
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Dynamic Email AngularJS</title>
</head>
<body ng-app="myApp" ng-cloak>
<div ng-controller="formCtrl">
<pre ng-model="result">
{{result}}
</pre>
<form name="userForm">
<input type="text" class="form-control" ng-model="$parent.name" placeholder="Name Lastname" required>
<input type="text" class="form-control" ng-model="$parent.email" placeholder="[email protected]" required>
<div ng-view></div>
<button ng-click="add()">New Item</button>
<button type="submit" class="btn" ng-click="formsubmit(userForm.$valid)" ng-disabled="userForm.$invalid">Submit </button>
</form>
</div>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
<script src="//code.angularjs.org/1.4.3/angular-route.min.js"></script>
<script src="app.js"></script>
</body>
</html>
app.js:
myApp.controller("formCtrl", ['$scope', '$http','$templateRequest','$compile', function($scope, $http, $templateRequest, $compile) {
$scope.lists = [
{
"year":"year I",
"semesters":[
{
"label": "Semester I",
"max": "4",
"courses": [
{"name": "Introductory Accounting I", "type": "populated"},
{"name": "Principles of Economics I", "type": "populated"},
]
},
{
"label": "Semester II",
"max": "4",
"courses": [
{"name": "Accounting Method II", "type": "populated"},
]
}
]
},
{
"year":"year II",
"semesters":[
{
"label": "Semester I",
"max": "4",
"courses": [
{"name": "Introductory Accounting I", "type": "levelII"},
{"name": "Business Finance I", "type": "levelII"}
]
},
{
"label": "Semester II",
"max": "4",
"courses": [
{"name": "Accounting Method II", "type": "levelII"},
{"name": "Management Accounting II", "type": "levelII"},
]
}
]
}
]
$scope.add = function () {
$scope.lists.push(
{
"year":"year III",
"semesters":[
{
"label": "Semester I",
"max": "4",
"courses": [
{"name": "Introductory Accounting I", "type": "levelII"},
{"name": "Business Finance I", "type": "levelII"}
]
},
{
"label": "Semester II",
"max": "4",
"courses": [
{"name": "Accounting Method II", "type": "levelII"},
{"name": "Management Accounting II", "type": "levelII"},
]
}
]
});
}
$scope.url = 'submit.php';
$scope.formsubmit = function(isValid) {
if (isValid) {
$templateRequest('email.html').then(function(html) {
$scope.contentHtml = $compile(html);
});
$http.post($scope.url, {"name": $scope.name, "email": $scope.email, "message": $scope.contentHtml }).
success(function(data, status) {
console.log(data);
$scope.status = status;
$scope.data = data;
$scope.result = data;
})
}else{
alert('Form is not valid');
}
}
}]);
submit.php:
<?php
$post_date = file_get_contents("php://input");
$data = json_decode($post_date);
$to = $data->email;
$from = "[email protected]";
$name = $data->name;
$subject = "Dynamic Email";
$htmlContent = $data->message;
// Set content-type header for sending HTML email
$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";
// Additional headers
$headers .= 'From: '.$from . "\r\n";
if(mail($to,$subject,$htmlContent,$headers)) {
echo "Mail Sent. Thank you " . $name . ", we will contact you shortly.";
} else {
echo 'Sorry there was an error sending your message. Please try again later.';
}
echo "Name : ".$data->name."\n";
echo "Email : ".$data->email."\n";
echo "Hero : ".$data->hero."\n";
echo "Message": $htmlContent;
?>
email.html
<table ng-repeat="list in lists">
<tr>
<td>
<h1>{{list.year}}</h1>
</td>
</tr>
<tr>
<td ng-repeat="semester in list.semesters">
<table>
<tr>
<td>
<h3>{{semester.label}}</h3>
<ul>
<li ng-repeat="course in semester.courses">{{course.name}}</li>
</ul>
</td>
</tr>
</table>
</td>
</tr>
</table>
Upvotes: 1
Views: 2003
Reputation: 71
I have successfully implemented this architecture in my one project. I have created separate service to get email template. I passed URL and $scope object to getTemplate() method and this method will return compiled email template to me.
angular.module('myApp').factory("TemplateService", ['$resource', '$q', '$rootScope', '$templateRequest', '$compile', '$timeout', function ($resource, $q, $rootScope, $templateRequest, $compile, $timeout) {
class TemplateService {
constructor() {
}
/**
* Get the template from url and then compile it with data.
* @param url
* @param $scope
* @returns {*|Promise<T>}
*/
static getTemplate(url, $scope) {
return $templateRequest(url)
.then(function(response){
let template = angular.element('<div></div>');
template.html(response);
//3. Pass the data to email template, in data will be merged in it
$compile(template)($scope);
return $timeout(function(){
return template.html();
}, 300);
})
.catch(function(err){
return $templateRequest('views/templates/404.html');
});
}
}
return TemplateService;
}]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="https://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Email</title>
</head>
<body leftmargin="0" marginwidth="0" topmargin="0" marginheight="0" offset="0">
<table align="center" border="0" cellpadding="0" cellspacing="0" height="100%" width="100%" id="bodyTable" style="background: #f2f2f2;padding:40px 10px;">
<tr>
<td align="center" valign="top" id="bodyCell">
<table border="0" cellpadding="0" cellspacing="0" id="templateContainer" style="background: white;text-align: center;border: 1px solid grey;padding: 20px;box-shadow: 0 0 5px 2px grey;margin:0 auto;">
<tr>
<td align="center" valign="top">
<table border="0" cellpadding="0" cellspacing="0" width="100%" id="templateBody">
<tr>
<td valign="top" class="bodyContent">
Hello {{ contactEmailCtrl.contact.firstName }}
<p compile="contactEmailCtrl.message">
</p>
<p>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
angular.module('myApp').controller('ContactController', ['$scope', 'Global', 'TemplateService', $scope, Global, TemplateService]) {
let vm = this;
vm.sendEmail = function(params) {
//1. Prepare email template, Pass data to email template and compile it
$scope.contactEmailCtrl = {
user: Global.user,
message: $scope.emailCommunication.message || null,
};
TemplateService.getTemplate('views/templates/emails/contact_email.html', $scope).then(function(emailBody) {
console.log('--> | emailBody ', emailBody);
//Todo: Send email
let emailParams = {
tos: '[email protected]',
subject: 'subject goes here',
emailBody: emailBody
}
// EmailService.sentEmail(emailParams); // Either send by PHP or Nodejs Or Ruby whatever
}).catch(function(err) {
console.log(' err ', err);
});
};
}
This is whole implementation. Hope this will help who wants to maintain clean architecture and separate email html and inject on the fly to send email.
Upvotes: 0
Reputation: 33
I had to do the very same thing. But my setup is somewhat different. My Backend is a Firebase.com database. Loaded into my frontend via angularFire, the library for loading stuff into an angular project. I have a mail template in the front-end. In fact, i plan to let users choose their e-mail template from several provided ones. I just fill in the fields, a but like a mail-merge in MS-Office. On the serverside, i'm using php-mailer (google it!) In big lines, this is what's happening: - Create vars like mailTo (all the emails where i have to send mail to) and bind them to the $scope (yeah i know i shouldn't do that but stay with me) - other stuf from the database records that should be in the mail, i bind to the $scope again. - and then i do this:
$templateRequest("templates/mail-packs/mail-1.html")
.then(function(emailtemplate) {
var base = angular.element('<div></div>');
base.html(emailtemplate);
$compile(base)($scope);
$timeout(function(){
mail = base.html()
console.log(mail);
constructMail(mail)
}, 300)
})
the base variabel was needed beceause you are not compling to the DOM. You have to trick angular there and start with a blank DOM. The function constructMail() is a function just doing that, prepping the data to send to the php-mailer.
Upvotes: 1