I am trying to use Symfony 3.4 components in a legacy project. There is a form that has two fields city and state. I want to send those two fields to a class method. So, I built an intermediate PHP file to pass the data to using javascript. The form and javascript are here.
<form class="form-inline" id="addpharmacies">
<div class="form-group">
<label for="city" ><?php print xlt("City");?></label>
<input type="text" class="form-control" id="city">
</div>
<div class="form-group">
<label for="state"><?php print xlt("State");?></label>
<input type="text" class="form-control" id="state">
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary" >Submit</button>
</div>
</form>
let f = document.getElementById('addpharmacies');
f.addEventListener('submit', importPharm);
function importPharm() {
top.restoreSession();
let city = document.getElementById("city").value;
let state = document.getElementById("state").value;
if (city.length === 0 || state.length ===0) {
alert("City and state must both be filled out")
return false;
}
let body = {"city": city, "state": state};
let req = new Request('pharmacyHelper.php', {method: "POST", body: body});
fetch(req)
.then(response=> {
if (response.status === 200) {
return response.json()
} else {
throw new Error("Bad response from the server");
}
})
.then(json => {
alert(json) // Not a great UI experience
})
}
As you can see that I am using a listener to submit the form by way of the javascript function importPharm. The javascript gets the data from the form via a getElementById call to city and state fields.
A request is created and the data is passed into the request and the helper file is called to pass the data. I have verified that something is being sent to the helper file. But I can see is [object Object] when I do a getContent().
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
$request = Request::createFromGlobals();
$content = $request->getContent();
file_put_contents("api.txt", $content);
When I try:
$request->request->get('city','');
I get nothing. I have tried every combination I could find on the Symfony Site
Any suggestion will be greatly appreciated.
Well you haven't specified any headers clarifying your content-type so it's ambiguous for Symfony to detect your content type and map them to the Parameter Bag (although it displays the content body) , try adding the :
Content-Type : application/x-www-form-urlencoded
header and send your form inputs as form-data and try again , else you will need to json_decode the content body and deal with it as an array or \StdClass object .
N.B : Using form-data your request would look like this
let body = "city="+city+"&state="+state;
let req = new Request('pharmacyHelper.php', {
method: "POST",
headers: {
'Content-Type': 'application/x-www-form-url-encoded',
'Accept': 'application/json'
},body: body});
fetch(req).then(response=> {
if (response.status === 200) {
return response.json()
} else {
throw new Error("Bad response from the server");
}
})
.then(json => {
alert(json) // Not a great UI experience
})
Related
I am testing strip payment integration in PHP and downloaded the test files directly from the stripe. I want to be able to add "receipt_email" to the workflow. If I define it directly on the create.php and that works fine, but the trouble comes when I define it as a hidden input in the form on checkout.html I don't know how to read it into the create.php since the client.js is fetching the create.php
checkout.htm
<form id="payment-form">
<input type="hidden" id="email" value="email#domain.com">
<div id="card-element"><!--Stripe.js injects the Card Element--></div>
<button id="submit">
<div class="spinner hidden" id="spinner"></div>
<span id="button-text">Pay</span>
</button>
<p id="card-error" role="alert"></p>
<p class="result-message hidden">
Payment succeeded, see the result in your
Stripe dashboard. Refresh the page to pay again.
</p>
</form>
client.js
// The items the customer wants to buy
var purchase = {
items: [{ id: "shirt" }]
};
var formData = {
'email': document.getElementById("email").value
};
// Disable the button until we have Stripe set up on the page
document.querySelector("button").disabled = true;
fetch("create.php", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(purchase) //I have tried using FormData Here but
need purchase also
})
.then(function(result) {
return result.json();
})
.then(function(data) {
var elements = stripe.elements();
create.php
function calculateOrderAmount(array $items): int {
// Replace this constant with a calculation of the order's amount
// Calculate the order total on the server to prevent
// customers from directly manipulating the amount on the client
return 1400;
}
header('Content-Type: application/json');
try {
// retrieve JSON from POST body
$json_str = file_get_contents('php://input');
$json_obj = json_decode($json_str);
$paymentIntent = \Stripe\PaymentIntent::create([
'amount' => calculateOrderAmount($json_obj->items),
'currency' => 'usd',
'receipt_email' => ??, //ok if defined here but I need to pull it from
input in checkout.html
]);
I have a checkout form on my django website:<form class="row contact_form" action="." method="post" id="form">. That form has a submit button at the end:<input id="form-button" class="btnabc btnabc-outline-info btnabc-lg" type="submit" value="Continue to Payment">
On clicking this button I want to redirect the user to the payment gateway and if his transaction is successful I want to save his information that he entered in the form:
This is the javascript code for the button:
document.getElementById('payment-info').addEventListener('click', function (e) {
submitFormData()
})
function submitFormData() {
console.log('Payment Button Clicked')
var userFormData = {
'name': null,
}
var shippingInfo = {
'address': null,
}
shippingInfo.address = form.address.value
userFormData.name=form.name.value
var url = "/process_order/"
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken,
},
body:JSON.stringify({'form': userFormData, 'shipping': shippingInfo }),
})
.then((response) => response.json())
.then((data) => {
console.log('Success:', data);
alert('Transaction Completed')
window.location.href = "{% url 'index' %}"
})
}
This is my views.py:
def processOrder(request):
transaction_id = datetime.datetime.now().timestamp()
data = json.loads(request.body)
if request.user.is_authenticated:
customer=request.user.customer
order, created=Order.objects.get_or_create(customer=customer, complete=False)
total=float(data['form']['total'])
order.transaction_id=transaction_id
if total == order.get_cart_total:
order.complete = True
order.save()
ShippingAddress.objects.create(
customer=customer,
order=order,
address=data['shipping']['address'],
city=data['shipping']['city'],
state=data['shipping']['state'],
zipcode=data['shipping']['zipcode'],
name=data['form']['name'],
email=data['form']['email'],
mobile=data['form']['mobile'],
)
param_dict = {
'MID': 'DIY12386817555501617',
'ORDER_ID': str(order.id),
'TXN_AMOUNT': '4',
'CUST_ID': 'j',
'INDUSTRY_TYPE_ID': 'Retail',
'WEBSITE': 'WEBSTAGING',
'CHANNEL_ID': 'WEB',
'CALLBACK_URL':'http://127.0.0.1:8000/handlerequest/',
}
param_dict['CHECKSUMHASH'] = Checksum.generate_checksum(param_dict, MERCHANT_KEY)
return render(request, 'paytm.html', {'param_dict': param_dict})
return HttpResponse('Done')
#csrf_exempt
def handlerequest(request):
# paytm will send you post request here
form = request.POST
response_dict = {}
for i in form.keys():
response_dict[i] = form[i]
if i == 'CHECKSUMHASH':
checksum = form[i]
verify = Checksum.verify_checksum(response_dict, MERCHANT_KEY, checksum)
if verify:
if response_dict['RESPCODE'] == '01':
print('order successful')
else:
print('order was not successful because' + response_dict['RESPMSG'])
return render(request, 'paymentstatus.html', {'response': response_dict})
This handlerequest function is basically for checking if the transaction is verified or not.
This is my paytm.html
<form action="https://securegw-stage.paytm.in/theia/processTransaction" method="post" name="paytm">
{% for key,value in param_dict.items %}
<input type="hidden" name="{{key}}" value="{{value}}">
{% endfor %}
</form>
</body>
<script>
document.paytm.submit()
</script>
Currently whenever I click on the payment button it just saves the information of the form (submitformdata() in javascript) without verifying the transaction and also i am not taken to the payment page where the user can pay.
The error is with the place where I am calling the submitformdata function and I cant figure out a way to call that function only when the transaction is verified. Please help me figuring out a way to do so. Any help would be appriciated.
actually the reason is when you try to implement this you haven't put this in the server right now so the paytm cant get access to the callback url for transaction verification just like i cant able to access 127.0.0.1:8000 from my laptop right now so you have to deploy that app so there is one thing you can do is use 'pagekite.net' and you get run temparary app on that url and make call back url accorging to that
Dynamic Form
Adding and removing boxes works fine and data is fed well upon entering text on form. Even the photo is being captured very well
<form>
<div class="box" v-for="(data,i) in datas" :key="i">
<input type="text" v-model="data[i]['key1']>
<input type="text" v-model="data[i]['key2']>
<input type="file" #change="selectImage($event,i)">
// I have not included add/delete methods to reduce codes
<button #click.prevent="method_to_add_box">Add</button>
<button #click.prevent="method_to_delete_box">Del</button>
<button #click.prevent="submitData">Submit</button>
</div>
</form>
Vuejs scripts
datas: [
{key1:'value1',key2:'value2',photoToUpload:null}
],
methods: {
submitData() {
let theData = new FormData();
theData.append('datas',JSON.stringify(this.datas));
let config = {
headers: {
'Content-Type':'multipart/form-data',
}
};
axios.post('/url', theData, config)
.then(res => console.log(res))
.catch(err => console.log(err))
},
selectImage(event, i) {
let theImage = event.target.files[0];
this.datas[i].photoToUpload = theImage;
}
}
I receive the data in Laravel backend
$datas = json_decode($request->datas);
if(is_array($datas)) {
foreach($datas as $data) {
$object = new Object();
$object->field1 = $data->key1;
$object->field2 = $data->key2;
// problem starts here - photo seen as an empty object so can't store()
$path = $data->photoToUpload->store('/path');
$path = explode('/',$path); $filename = $path[2]
$object->photo = $filename;
if($object->save()) {
return new ObjectResource($object);
}
}
}
Troubleshooting & Results
Tried to return response immediately after json_decode($request->datas) and here are the results;
$datas = json_decode($request->datas);
return \response([$datas[0]->photoToUpload]);
Developer Tools Network Tab response returns
[{ }], status is OK
have also tried returning extension of the photo
return \response([$datas[0]->photoToUpload->extension()]);
Developer Tools Network Tab preview returns message below
"Call to undefined method stdClass::extension()", Status Code: 500 Internal Server Error
However, if I don't put the fileToUpload inside an array in Vuejs data I can append to formdata, receive in Laravel backend and upload without troubles.
What am I doing wrong here? Please assist
I'm setting up a website page, and want to submit a form with multiple fields, and the Back-end API handles the request is prepared.
Simplified Code shows below:
<form id="contact-form" #submit="postForm" ref="aGeniusForm">
<input type="text" name="companyName">
<input type="email" name="email">
<textarea type="text" name="question"></textarea>
<input type="file" name="file">
<form>
The Back-End is powered by Sprint Boot, and the Controller code is:
#RestController
#RequestMapping("/v1/emails")
class EmailController(
val emailService: EmailService,
val objectMapper: ObjectMapper
){
#PostMapping("/applications", consumes = ["multipart/form-data"])
#ApiOperation("Send a apply email")
fun sendApplyEmail(
#RequestPart body: ApplyEmailPostDto,
#RequestPart("files", required = false) files: List<MultipartFile>
): EmptyResponse {
emailService.sendApplyEmail(body, files)
return EmptyResponse
}
}
The front-end code that creates an http request, the trouble is in postForm method.
// Form component data
export default {
name: "SignupForm",
components: {},
data() {
return {
return {
form: {
companyName: "",
email: "",
question: ""
},
files: []
};
},
methods: {
postForm() {
let formData = new FormData();
// Blob is the point ↓ ↓ ↓
formData.append(
"body",
new Blob([JSON.stringify(this.form)], {
type: "application/json"
})
))
// It is the point ↑ ↑ ↑
// post request, "multipart/form-data"
axios.post(
URL,
formData, // the data to post
{
headers: {
"Content-type": "multipart/form-data"
}
}
)
.then(response => {
//...
})
.catch(error => {
//...
});
}
}
I know that Blob is not widely supported in mobile browsers and in webviews and I don't think using Blob is necessary.
But back-end developer insisted on making me do so.
If front-end code as below
formData.append("body",this.form))
//or
formData.append("body",JSON.stringify(this.form)))
The Back-end API return code 400 with message: "media-type not supported"
The kotlin developer who designed the API declared that he cannot support other media-type easily.
I'm not quite familiar with Spring Boot framework or kotlin. So I need you guys to tell me is that true?
What's the best practice for this condition?
I want to display Bootstrap alert when the user has saved the data.
my code is as below:
html page:
<div class="alert alert-success" *ngIf="saveSuccess">
<strong>Success!</strong>
</div>
<form #f="ngForm" (submit)="saveUser(f.value)">
/////Some form fields
<button class="form-control btn btn-primary" type="submit">save</button>
</form>
app.component.ts:
export class UserProfileComponent{
saveSuccess: boolean;
user: IUser;
saveUser(user:IUser) {
this.headers = new Headers();
this.headers.append('Content-Type', 'application/json');
this.editUserForm = user;
this._http.post('api/user/'+this._current_user._id, JSON.stringify(this.editUserForm),{
headers: this.headers
}).subscribe(function(data) {
// if the update is successful then set the value to true
// this is getting updated
if (data){
this.saveSuccess = true;
}
else{
this.saveSuccess = false;
}
});
}
}
I want to display the alert when a successful POST is done.
I think i am missing how to bind the 'saveSuccess' variable to html so that alert can be displayed when the successful save is done. (I am new to Angular2)
Last night I didn't see it, it was probably too late. But your problem is not having the this context in the inline function where you set saveSuccess.
I'd suggest you use lambdas or "fat arrow function". Instead of
function(data) { ... }
you do
(data) => { ... }
This way the this context will be preserved. Just use it wherever you need inline function and you will have no problems anymore! :)
Your code with the lambda function:
export class UserProfileComponent{
saveSuccess: boolean;
user: IUser;
saveUser(user:IUser) {
this.headers = new Headers();
this.headers.append('Content-Type', 'application/json');
this.editUserForm = user;
this._http.post('api/user/'+this._current_user._id, JSON.stringify(this.editUserForm),{
headers: this.headers
})
.map((data: Response) => data.json) // <-- also add this to convert the json to an object
.subscribe((data) => { // <-- here use the lambda
// if the update is successful then set the value to true
// this is getting updated
if (data){
this.saveSuccess = true;
}
else{
this.saveSuccess = false;
}
});
}
}
Consider this dynamic alert component:
Angular2 Service which create, show and manage it's inner Component? How to implement js alert()?
for example:
.
this.alertCtmService.alertOK("Save changes???").subscribe(function (resp) {
console.log("alertCtmService.alertOK.subscribe: resp=" + resp.ok);
this.saveData();
}.bind(this) );
See this Demo here