I'm new to meteor and trying to make a simple blog application. But my insert function doesn't seem to be working properly. Here's my code.
This is my template
<template name="addpost">
<div class="container">
<h1> Add New Post</h1>
<form class="new-post">
<label class="title">
Title:
<input type="text" name="title" placeholder="Type to add new tasks" />
</label>
<label class="post-content">
Write here:
<input type="text" name="body" placeholder="Type to add new tasks" />
<button class="add-post">Add Post</button>
</label>
</form>
</div>
</template>
JS file content
Posts = new Meteor.Collection("posts");
if (Meteor.isClient) {
Template.addpost.events({
"submit .new-post": function(event){
var title = event.target.title.value;
var body = event.target.body.value;
Meteor.call("addPost", title, body);
}
});
}
Meteor.methods({
addPost: function(title, body){
Posts.insert({
title: title,
body: body,
createdAt : new Date()
});
}
});
I have not removed autopublish and insecure packages. And below is the mongoDB query output.
By default, when you submit a form it makes another HTTP request which will reload the page and halt whatever meteor was doing. To avoid this, you need to prevent the default action:
Template.addpost.events({
submit: function(event) {
event.preventDefault();
// the rest of your code goes here
}
});
Aside from that, your code worked correctly for me. You can verify it with: Posts.find().fetch() in either the web console or via meteor shell.
Related
I'm creating a site for my senior project and have run into some trouble creating a payment portal for my site. The site was working correctly the other night, and without making any changes, the buttons now fail to render and I am being spammed with errors regarding indicating a cookie in a cross site address. Attached is the checkout.html file which the PayPal js is included within, along with the error codes I am receiving from the console. Any help would be much appreciated!
I have tried to edit the global config and played around with the SameSite attribute, but to no avail :(
{% extends 'main.html' %}
{% load static %}
<!DOCTYPE html>
<head>
<link rel="stylesheet" type="text/css" href="{% static 'css/checkout.css' %}">
</head>
<body>
{% block content %}
<div class="row">
<div class="col-sm-6 mt-4 mb-4">
<div class="box-element" id="form-wrapper">
<h2>Recipient Information</h2>
<form id="form">
<div id="recipient-info">
<div class="form-field">
<input required class="form-control" type="text" name="recipient_first_name" placeholder="Recipient First Name..">
</div>
<div class="form-field">
<input required class="form-control" type="text" name="recipient_last_name" placeholder="Recipient Last Name..">
</div>
<br>
<div class="form-field">
<input required class="form-control" type="email" name="recipient_email" placeholder="Recipient Email..">
</div>
<div class="row ml-auto">
<label class = "mt-1" for="pickup_location">Select a pickup location: </label>
<select class="mt-2 ml-2" name="pickup_location" size="4" multiple>
<option value="nabatieh">Nabatieh</option>
<option value="tyre">Tyre</option>
<option value="saida">Saida</option>
<option value="beirut">Beirut</option>
</select><br><br>
</div>
</div>
<hr>
<input id="form-button" class="btn btn-success btn-block" type="submit" value="Continue">
</form>
</div>
<br>
<div class="box-element hidden" id="payment-info">
<h2>PayPal Options</h2>
<div id="paypal-button-container"></div>
</div>
</div>
<div class="col-sm-6 mt-4 mb-4">
<div class="box-element">
<a class="btn btn-outline-dark" href="{% url 'cart' %}">← Back to Cart</a>
<hr>
<h3>Order Summary</h3>
<hr>
{% for item in items %}
<div class="cart-row">
<div style="flex:2"><img class="row-image" src="{{item.product.imageURL}}"></div>
<div style="flex:2"><p>{{item.product.name}}</p></div>
<div style="flex:1"><p>{{item.product.price|floatformat:2}}</p></div>
<div style="flex:1"><p>{{item.quantity}}</p></div>
</div>
{% endfor %}
<h5>Items: {{order.get_cart_items}}</h5>
<h5>Total: ${{order.get_cart_total|floatformat:2}}</h5>
</div>
</div>
</div>
<script src="https://www.paypal.com/sdk/js?client-id=ASbTo6tPEAlA-TQ3zYFDMuuDgSWzmybQ3E3LeE3xi2s3hN6UmiREE30_atIal3f9ui2r3Eh6oGpxmil-¤cy=USD"></script>
<script>
var total = '{{order.get_cart_total}}'
paypal.Buttons({
// Set up the transaction
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
value: parseFloat(total).toFixed(2)
}
}]
});
},
// Finalize the transaction
onApprove: function(data, actions) {
return actions.order.capture().then(function(orderData) {
submitFormData()
console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
var transaction = orderData.purchase_units[0].payments.captures[0];
alert('Transaction '+ transaction.status + ': ' + transaction.id + '\n\nSee console for all available details');
// Replace the above to show a success message within this page, e.g.
// const element = document.getElementById('paypal-button-container');
// element.innerHTML = '';
element.innerHTML = '<h3>Thank you for your payment!</h3>';
actions.redirect('home.html');
});
}
}).render('#paypal-button-container');
</script>
<script type="text/javascript">
var form = document.getElementById('form')
var total = '{{order.get_cart_total|floatformat:2}}'
form.addEventListener('submit', function(e){
e.preventDefault()
console.log('Form submitted...')
document.getElementById('form-button').classList.add('hidden')
document.getElementById('payment-info').classList.remove('hidden')
})
function submitFormData(){
console.log('Payment button has been clicked...')
var orderData = {
'total':total,
}
var recipientInformation = {
'recipient_first_name':null,
'recipient_last_name':null,
'email':null,
'pickup_location':null,
}
recipientInformation.recipient_first_name = form.recipient_first_name.value
recipientInformation.recipient_last_name = form.recipient_last_name.value
recipientInformation.recipient_email = form.recipient_email.value
recipientInformation.pickup_location = form.pickup_location.value
var url = "/process_order/"
fetch(url, {
method:'POST',
headers:{
'Content-Type':'applicaiton/json',
'X-CSRFToken':csrftoken,
},
body:JSON.stringify({'form':orderData, 'recipient-information':recipientInformation}),
})
.then((response) => response.json())
.then((data) => {
console.log('Success:', data);
alert('Transaction completed');
window.location.href = "{% url 'store' %}"
})
}
</script>
{% endblock content %}
</body>
</html>
Error from console
Error information expanded
Here is how the portal was working the other night, note I made no changes on my end from then until now.
https://gyazo.com/7cfcc6a9d226af3604a7a597d39e7316
I don't know what your issue is, but it is wrong and bad design to use actions.order.create / capture on the client side and then perform server operations after the fact. This should never be done.
If server operations are to take place (such as saving form data or writing ot a database), the payment creation/capture should be done on the server, via API. With any luck, the problem in your question can be resolved as a byproduct of starting over and implementing things correctly:
Follow the PayPal Checkout integration guide and make 2 routes (url paths) on your django server, one for 'Create Order' and one for 'Capture Order'. You can use the Checkout-Python-SDK for the routes' API calls to PayPal, or your own HTTPS implementation of first getting an access token and then doing the call. Both of these routes should return only JSON data (no HTML or text). Inside the 2nd route, when the capture API is successful you should verify the amount was correct and store its resulting payment details in your database (particularly purchase_units[0].payments.captures[0].id, which is the PayPal transaction ID) and perform any necessary business logic (such as sending confirmation emails or reserving product) immediately before forwarding your return JSON to the frontend caller. In the event of an error forward the JSON details of it as well, since the frontend must handle such cases.
Pair those 2 routes with this frontend approval flow: https://developer.paypal.com/demo/checkout/#/pattern/server . (If you need to send any additional data from the client to the server, such as an items array or selected options or form data in your case, add a body parameter to the fetch with a value that is a JSON string or object of your serialized data)
I did not edit my blog successfully for this error. In my project this type of editing text comes one more time, firstly when I edited the text already store in MongoDB did not receive that error but today I repeated the same kind of code into my blog section and getting error like follwing>>
after seeing this error I went to see similar work that has done before without error one more time that is it now having any issue and run/ edit text of the previous section of the project but seeing same error what I now facing actually It did work earlier but now why this comes do not understand
here is blog_edit.ejs file
<form action="/admin/blog/<%=post._id%>/edit" method="post" >
<div class="form-group">
<label for="exampleFormControlInput1">Categories</label>
<select class="form-control" id="exampleFormControlSelect1" name="category_id">
<option selected>Open this select category</option>
<% categories.forEach(function(category){ %>
<option value="<%=category._id%>"><%=category.name%></option>
<%})%>
</select>
</div>
<div class="form-group">
<label for="exampleFormControlInput2">Title :</label>
<input type="text" name="title" class="form-control" id="exampleFormControlInput2" value="<%=post.title%>">
</div>
<div class="form-group">
<textarea id="editor1" name="content" rows="10" cols="80"> <%=post.content%>"</textarea>
</div>
<div class="form-group">
<input class="form-control" type="text" name="tags" value="<%=post.tags%>">
</div>
<div class="form-group">
<button type="submit" class="btn btn-success">Update Blog Post</button>
</div>
</form>
here is the middleware/rouer.js file
router.get('/admin/blog/:id/edit', serverController.isAuthenticated, serverController.blog_edit)
router.post('/admin/blog/:id/edit', serverController.isAuthenticated, serverController.blog_edit_post)
here also I have a controller file as serverController.js
exports.blog_edit = async function(req,res){
res.render('server/blog_edit',{
post : await blogCollection.findOne({_id : objectId(req.params.id)}),
categories : await categoryCollection.find().toArray()
})
}
exports.blog_edit_post = async function(req,res){
let post = new Blog(req.body, req.file, req.params.id)
post.edit().then(async()=>{
res.redirect('/admin/blog')
}).catch(()=>{
res.send('404')
})
}
Here the last I have is my model of this section as Blog.js
const blogCollection = require('../db').db().collection('blogs')
const objectId = require('mongodb').ObjectID
const Blog = function(blog, cover,id){
this.blog = blog
this.image = cover
this.id = id
}
Blog.prototype.edit = function(){
return new Promise(async(resolve,reject)=>{
await blogCollection.updateOne({_id : objectId(this.id)}, {$set : {
category_id : objectId(this.blog.category_id),
title: this.blog.title,
content : this.blog.content,
tags : this.blog.tags,
updated_at: date.getFullYear()+'-'+(date.getMonth()+1)+'-'+date.getDate()+'-'+date.getHours()+":"+date.getMinutes()+":"+date.getSeconds()
}})
console.log(this.blog)
resolve()
})
}
if I make changes in Blog.js that I called Model of this blog section like following ->>
category_id : objectId(this.id.category_id),
instead of
category_id : objectId(this.blog.category_id)
then this problem is fixed but I did not see category name in the client page
like follwing, it comes blank after editing
I am building a Zendesk app that will post a variety of information to a webhook. Currently, I am running into two issues. The client.invoke() function says it is not a function in the console when the send email button is pressed. Additionally, sometimes the after the button is pressed, the app will successfully post to the webhook, other times it won't post at all. I cannot narrow down what is causing the discrepancies on when it posts. I'm unsure if this is related to the app I've built or an issue interacting with Zendesk.
Here is the app:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="https://cdn.jsdelivr.net/bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet">
<link href="main.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript" src="https://assets.zendesk.com/apps/sdk/2.0/zaf_sdk.js"></script>
<script src="https://cdn.jsdelivr.net/handlebarsjs/4.0.8/handlebars.min.js"></script>
</head>
<body>
<script>
var client = ZAFClient.init();
client.invoke('resize', { width: '100%', height: '450px' });
client.get('ticket.brand.subdomain').then(
function(data) {
var subdomain = data['ticket.brand.subdomain'];
console.log('Zendesk Subdomain is ' + subdomain);
document.getElementById('subdomainform').value = subdomain;
}
);
client.get('ticket.organization.id').then(
function(data) {
var org_id = data['ticket.organization.id'];
console.log('Org id is ' + org_id);
document.getElementById('orgidform').value = org_id;
}
);
</script>
<form name="submissionForm">
<div class="formBox">
<label for="title">First Name</label>
<input type="text" id="firstName" placeholder="First Name"/>
</div>
<div class="formBox">
<label for="title">Last Name</label>
<input type="text" id="lastName" placeholder="Last Name"/>
</div>
<div class="formBox">
<label for="title">Email</label>
<input type="text" id="email" placeholder="Email"/>
</div>
<div class="formBox">
<select id="rescom">
<option value="residential">Residential</option>
<option value="commercial">Commercial</option>
</select>
</div>
<div class="formBox">
<button id="btn">Click to Send Email</button>
</div>
<div><p id="explain">The fields below are ready-only and required for submission. If you don't see them, please refresh the app.</p></div>
<div class="formBox">
<input type="text" id="subdomainform" readonly="readonly"/>
</div>
<div class="formBox">
<input type="text" id="orgidform" readonly="readonly"/>
</div>
</form>
<script>
let content = [];
const addDay1 = (ev)=>{
let information = {
id: Date.now(),
firstName: document.getElementById('firstName').value,
lastName: document.getElementById('lastName').value,
email: document.getElementById('email').value,
subdomain: document.getElementById('subdomainform').value,
orgid: document.getElementById('orgidform').value,
rescom: document.getElementById('rescom').value
}
content.push(content);
document.forms[0].reset();
const Url ='{PLACEHOLDER}';
$.ajax({
url: "{WEBHOOK URL}",
type: "POST",
dataType: 'json',
data: {information},
complete: function(){alert("Failure")}
});
}
document.addEventListener('DOMContentLoaded', ()=>{
document.getElementById('btn').addEventListener('click', addDay1);
});
</script>
</body>
</html>
What am I missing? Appreciate any and all help that can be provided.
This was solved my a community manager from Zendesk. See post below:
Make sure ZAFClient is fully registered before attempting to do
subsequent ZAFClient methods. Something like:
client.on('app.registered', e => {
client.get('ticket.brand.subdomain').then(
function(data) {
var subdomain = data['ticket.brand.subdomain'];
console.log('Zendesk Subdomain is ' + subdomain);
document.getElementById('subdomainform').value = subdomain;
}
);
client.get('ticket.organization').then(
function(data) {
var org_id = data['ticket.organization.id'];
console.log('Org id is ' + org_id);
document.getElementById('orgidform').value = org_id;
}
);
}) The "not a function in the console" error is caused from the app's HTML page being resubmitted again when you click the button. In
Zendesk Apps framework, the connection from the app (using
ZAFClient.init()) to the main agent window is done through parameters
that are passed to the app when the framework first loads it. You can
see this in your browser's Network tab if you look for something like
"iframe.html?origin=https%3A%2F%2Fyour_subdomain.zendesk.com&app_guid=ff7133010-abff-4f1c-a7bf-ff7133fff7133"
-- the origin and app_guid params are needed to make the connection. When you resubmit the page, those parameters no longer are passed on
the new page reload and the new call to ZAFClient.init() doesn't
successfully initialize. Thus leading the error when the now invalid
'client' object is attempting to be used to call 'invoke'. You have to
treat these app pages like single-page apps.
Phew! All that said -- you can still use HTML functionality,
just don't have it resubmit the entire page when the button is
pressed. You can do this by adding type="button" to the button tag.
Click to Send Email
See also: HTML button to NOT submit form
Hope this gets you on your way!
I've looked at several existing questions on here already. They're all for submitting post requests, but the mechanics should be the same for get requests, so I modified my code to work for get requests. But it's not working correctly.
What's wrong: I submit a form, but the page continues to reload (right now it's redirecting to a new page with the json data.
What I want to do: Submit a form, prevent it from reloading, and display the json data on the same html page
<div class="row">
<div class="col-md-3">
<form method="GET" action="/search">
<div class="form-group">
<input type="text" class="form-control" id="term" name="term" placeholder="Find">
<br>
<input type="text" class="form-control" id="location" name="location" placeholder="Near">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
<script>
$(function() {
$('form').submit(function(event) {
event.preventDefault();
var $this = $(this);
$.get($this.attr('action'), function(data) {
$('pre').text(data);
});
});
});
</script>
And in my express code, I have this:
app.get('/search', function(req, res) {
var apiUrl = getApiUrl(req.query);
var apiData = getApiData(apiUrl, function(statusCode, data) {
// console.log(data);
// res.render('api-guide', data);
res.send(data);
});
});
I should note, I'm using handlebars for templating. So the form is in its own template, while the jquery script is in the main template. Would this be why it's not working as expected?
Can someone please help me?
You are setting an action parameter in your form that is conflicting with your AJAX request. If you remove
action="/search"
and set the path directly in your AJAX request
$.get('/search', function(data) {
$('pre').text(data);
});
from your form declaration, it should work as you expect.
I am attempting to store information that is put into this form with meteor:
<form class="form-group" id="lost_form">
<label for="item_name">Type</label>
<input id="item_name" class="form-control" type="text" placeholder="What is the item? Ex: Water bottle" required/>
<label for="item_brand">Brand</label>
<input id="item_brand" class="form-control" type="text" placeholder="What brand is the item? Ex: Nalgene" required/>
<label for="item_desc">Description</label>
<input id="item_desc" class="form-control" type="text" placeholder="Describe the item. Ex: Green, name on bottom" required/>
<label for="item_loc">Location</label>
<input id="item_loc" class="form-control" type="text" placeholder="Where did you have it last? Ex: Main common room"/>
<label for="item_date">Date Missing</label>
<input id="item_date" class="form-control" type="date"/>
<br>
<input id="submit_lost_form" class="btn btn-primary btn-block" type="submit" value="Submit" />
</form>
The JS I am using to put it into a collection is below:
LostItems = new Meteor.Collection('lostitems');
Meteor.methods({
'insertItem': function(iname, ibrand, idesc, iloc, idate){
LostItems.insert({
user: Meteor.user(),
name: iname,
brand: ibrand,
description: idesc,
location: iloc,
date: idate
})
}
});
if (Meteor.isClient) {
Template.lost_form.events({
'submit form': function (event) {
event.preventDefault();
var itemName = event.target.item_name.value;
var itemBrand = event.target.item_brand.value;
var itemDesc = event.target.item_desc.value;
var itemLoc = event.target.item_loc.value;
var itemDate = event.target.item_date.value;
Meteor.call('insertItem', itemName, itemBrand, itemDesc, itemLoc, itemDate);
}
});
}
But whenever I submit the form, nothing happens. There are no errors in the developer console, or on the meteor console, and when I do LostItems.find().fetch() there is nothing there.
I am new to meteor so this is probably a really dumb question, but I appreciate any help!
You might need to use Meteor.userId() instead of Meteor.user() in your call to insert(). Without the autopublish package, the doc returned by Meteor.user() can be different on the client than it is on the server (for security reasons). That would mean that the client-side insert into your mini-mongodb and the server-side insert into the real mongodb could conflict with each other. I would expect the client-side insert to be ignored after the result of the server-side insert propagates back to the client. I'm not sure why it isn't being replaced by the server-side insert though. What does LostItems.find().fetch() return when you run it on the server (e.g. in meteor shell)?
I fixed the issue by adding insecure, yogiben:autoform-tags and autopublish to my package list. I think autopublish is the one that made the difference. I am sure there is a better way to do this and that this probably has some security flaws to it, but this is not a big project and it isn't storing sensitive data, so this will work for now.