Unable to show questions of the second page - javascript

I'm working on a flask app, where there're questions paginated in 2 pages,
the problem is that clicking on the number 2 to change the page doesn't change the questions, I don't know which part of the code should be responsible for that, if there any code snippets required to help solving this problem just tell me to edit the question.
backend
def paginate_questions(request, selection):
page = request.args.get('page', 1, type=int)
start = (page - 1) * QUESTIONS_PER_PAGE
end = start + QUESTIONS_PER_PAGE
questions = [question.format() for question in selection]
current_questions = questions[start:end]
return current_questions
#app.route('/questions')
def get_paginated_questions():
categories = Category.query.order_by(Category.id).all()
selection = Question.query.order_by(Question.id).all()
current_questions = paginate_questions(request, selection)
if len(current_questions) == 0:
abort(404)
return jsonify({
'success': True,
'questions': current_questions,
'total_questions': len(selection),
'current_category': None,
'categories': {category.format()['id']: category.format()['type']
for category in categories}
})
frontend
getQuestions = () => {
$.ajax({
url: `/questions`, //TODO: update request URL
type: "GET",
success: (result) => {
this.setState({
questions: result.questions,
totalQuestions: result.total_questions,
categories: result.categories,
currentCategory: result.current_category })
return;
},
error: (error) => {
alert('Unable to load questions. Please try your request again')
return;
}
})
}
selectPage(num) {
this.setState({page: num}, () => this.getQuestions());
}

Related

How to autofill form based on the selected 'id' using javascript or ajax in django

I am new ,i want to autofill form when i select vehicle id from template .hre is my models .
class Fuel(models.Model):
vehicle = models.ForeignKey(Vehicle, on_delete=models.CASCADE)
previous_km = models.IntegerField(blank=False, null=False)
progressive_km = models.IntegerField(blank=False, null=False)
when i select vehicle then corresponding vehicle previous_km automatically filled in form.
here a write simple javascript code manually but i want to take from database.
<script>
let usersData = [
{
id: 1,
email: "u1#gmail.com",
fname: "fname-1",
lname: "lname-1",
previous_km : 1000,
},
{
id: 2,
email: "u2#gmail.com",
fname: "fname-2",
lname: "lname-2",
previous_km : 2000,
},
];
document.getElementById('vehicle').onchange = (e) => {
let selectedUser = usersData.find(userdata => userdata.id == e.target.value);
console.log(selectedUser);
document.getElementById('previous_km').value = selectedUser.previous_km;
};
This is generally what I would do. It uses JQuery + Ajax to handle the posting.
Javascript (JQuery)
$(document).ready(function() {
$("#vehicle").change(function(){
if ($(this).val() == ''){
// value is blank, don't post
return;
};
postdata = {
'vehicle_pk': $(this).val(),
// token if being logged in is required
'csrfmiddlewaretoken': $('[name=csrfmiddlewaretoken]').val(),
// This needs to be in template: {% csrf_token %}
};
$.ajax({
method: 'post',
url: 'url_to_view', // put your url here
data: data,
beforeSend: function(){
$('#ajaxSendingDiv').fadeIn().attr({'reload':1});
},
success: function(data){
console.log(data);
if (data['status']){
$('#previous_km').val(data['previous_km']);
// do thing
}else{
alert(data['msg']);
};
},
error: function(event,xhr,settings,errorText){
//xhr.status general meanings:
// 0 = Server didn't Reply (server down)
// 400 = Bad Request (Syntax Error)
// 403 = Forbidden (Login Token Expired)
// 403 = Not Found (Invalid Url)
// 500 = Server Error (Django Crash)
},
});
});
};
View.oy (general)
def GetPrevKM(request):
if request.method == 'POST':
data = {'status':False}
# do your query + return the data..
# I'm not 100% on how your models are set up
# but this is the general format
obj = Fuel.objects.filter(pk=request.POST.get('vehicle_pk'))
if obj:
data['status'] = True
data['previous_km'] = obj.previous_km
data['progressive_km'] = obj.progressive_km
data['msg'] = 'Returned Fuel Information'
else:
data['msg'] = 'No Fuel found on row: {0}'.format(request.POST.get('vehicle_pk'))
import json
return HttpResponse(
json.dumps(data),
content_type="application/json"
)
# Post only View!
from django.http import Http404
raise Http404
and I recommend trying to use JQuery more, you can get a lot more done quicker (imo) and it seems like a lot of people use it for things like this

Stripe Payment Element and one page checkout - what is the correct payment flow?

I want to upgrade my simple Stripe one-page checkout to use the new Payment Element that unifies a lot of different payment methods under one component. By simple I mean, the customer chooses between a few variants of one product, provides needed info and submits the order. Collect money, send emails, fulfil the order etc. Just vanilla HTML/CSS/JS and a bit of PHP. Using Payment Intents API to process the payments, was on Charges API before.
I love the premise of this unified element so I decided to give it a go. It turns out I have trouble understanding what to do with both stripe.confirmPayment method and return_url parameter.
I guess the return_url should be my checkout page? Also, is there a way to redirect without hard refresh? Ideally, I would be able to do some server-side stuff before redirect happens, but it seems that stripe.confirmPayment automatically redirects if resolved successfully.
Here is my code. I am a designer btw, so guess I am missing something obvious as always.
// init Stripe elements
fetch('/config.php', {
method: 'get',
headers: {
'Content-Type': 'application/json'
}
})
.then((response) => {
return response.json();
})
.then((response) => {
return setupElements(response.publishableKey)
})
var setupElements = function (publishableKey) {
stripe = Stripe(publishableKey);
// create payment intent to setup payment element
fetch('/setup-elements.php', {
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(order)
})
.then(function (response) {
return response.json()
})
.then(function (data) {
const appearance = {
theme: 'none',
labels: 'floating',
// etc.....
};
elements = stripe.elements({
clientSecret: data.clientSecret,
fonts: [{
cssSrc: 'https://use.typekit.net/hly2qug.css'
}, ],
appearance
});
const paymentElement = elements.create("payment", {
fields: {
billingDetails: {
email: 'never',
address: {
line1: 'never',
city: 'never',
state: 'never',
country: 'never',
postalCode: 'never'
}
}
}
});
paymentElement.mount("#payment-element");
})
}
form.addEventListener('submit', function (e) {
e.preventDefault();
var isFormValid = validate.validateAll(form);
if (isFormValid.length < 1) {
loading(true);
collectFormInfo();
confirmPayment();
}
})
var confirmPayment = function () {
stripe.confirmPayment({
elements,
confirmParams: {
return_url: 'checkout-page?',
payment_method_data: {
billing_details: {
email: order.customer.email,
address: {
line1: order.delivery.address,
city: order.delivery.city,
state: order.delivery.state,
country: order.delivery.country,
postal_code: order.delivery.postcode
}
}
}
}
})
.then(function (result) {
// This is where I get stuck. How to do stuff after
// payment is confirmed
// and not get redirected immediately? If
//redirected, where to and is it
// possible to do so asynchronously?
if (result.error.type === "card_error" || result.error.type === "validation_error") {
showMessage(result.error.message);
} else {
// get client secret
const clientSecret = new URLSearchParams(window.location.search).get(
"payment_intent_client_secret"
);
// bail if no client secret
if (!clientSecret) {
return;
} else {
stripe.retrievePaymentIntent(clientSecret).then(function (response) {
switch (response.paymentIntent.status) {
case "succeeded":
showMessage("Payment succeeded!");
break;
case "processing":
showMessage("Your payment is processing.");
break;
case "requires_payment_method":
showMessage("Payment failed. Please try another payment method.");
break;
default:
showMessage("Something went wrong.");
break;
}
});
}
}
})
}
Nudge in the right direction is all I need, at least I hope so
Yes the return_url should be your own page that Stripe will automatically redirect after your customer completed the Payment: Stripe Doc. 'checkout-page?' doesn't look like a valid URL. Normally you would want something like 'http://localhost:4242/success'
This action is done automatically on client and you can't intercept it. Any action you want to perform on server should be handled via webhook, at Step 6 "Handle post-payment events" at the same article above.

Change data in DOM after successful fetch PUT

I have an SPA in vanilla JS, using classes and modules.
The main idea is creating visits of customers and render them. When I fill in the form, data are sent to the server in JSON, after successful fetch, a visit card is created in the #content section.
The rendered card has two options: edit and delete. I made deletion without problems, I send DELETE, then just remove() the element onclick.
But I have some difficulties when editing the card.
I wrote the code to pop up modal form when click on the Edit button, and this form is filled with the card's data, so that the user can change them, click on Submit and send PUT to the server. The response is successful.
This is the edit form submit
edit(id) {
const readData = document.querySelector('.form-edit');
readData.addEventListener('submit', (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const data = Array.from(formData.entries()).reduce((memo, pair) => ({
...memo,
[pair[0]]: pair[1],
}), {});
editCard(data, id)
.then((response) => {
if (response.ok) {
return response.json();
} else {
throw new Error('Something went wrong');
}
})
document.querySelector(".closeBtnEdit").click();
});
}
What I want, is to change the info of existing card in DOM after submitting the edited data.
This is the code of card rendering:
render(parent){
this.elem.fullName.textContent = this.fullName;
this.elem.purpose.textContent = `Purpose of the visit: ${this.purpose}`;
this.elem.desc.textContent = `Description: ${this.desc}`;
this.elem.priority.textContent = `Priority: ${this.priority}`;
this.elem.date.textContent = `Visit Date: ${this.date}`;
this.elem.delBtn.textContent = `Delete`;
this.elem.editBtn.textContent = `Edit`;
}
Edit card API:
function editCard(newCard, cardId) {
return fetch(`${API}/${cardId}`,{
method: "PUT",
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(newCard)
})
}

Problem w/state of a vue data object in component

I am updating my original vue project and am getting an error w/data object sports_feeds_boxscores_*. The site has three tabs to pull down scores for the three major leagues. I am adding the player stats for each game now. I first did baseball and all worked fine. Now I am doing football and the problem arises. I have three objects setup for the stats for each league. The nfl also contains an object with the three days of the week they play. What is happening is the stats for Sunday get pulled down ok but then Thursday's stats which should only be one game instead has all sunday's games plus the one thursday game. And then Monday has both Sunday & Thursdays results in it besides Mondays. I have made all the components separate as well as three separate data objects for the component props. And if I first click the nfl tab and then go to the mlb tab all results from nfl data object are in sports_feeds_boxscores_mlb. I setup a site here to better understand whats going on in using Vue.js devtools. Here is the pertinent code:
index.html:
<component
v-if="currentTabComponent === 'tab-mlb'"
v-bind:is="currentTabComponent"
v-bind:props_league_data="sports_feeds_data"
v-bind:props_league_standings="standings"
v-bind:props_baseball_playoffs="baseball_playoffs"
v-bind:props_end_of_season="end_of_season[this.currentTab.toLowerCase()]"
v-bind:props_box_game_scores_mlb="sports_feeds_boxscores_mlb"
class="tab"
>
</component>
<component
v-if="currentTabComponent === 'tab-nfl'"
v-bind:is="currentTabComponent"
v-bind:props_league_data="sports_feeds_data"
v-bind:props_league_data_nfl="nfl_feeds"
v-bind:props_league_standings="standings"
v-bind:props_nfl_playoffs="nfl_playoffs"
v-bind:props_end_of_season="end_of_season[this.currentTab.toLowerCase()]"
v-bind:props_box_game_scores_nfl="sports_feeds_boxscores_nfl"
class="tab"
>
</component>
vue.js:
data() {
return {
sports_feeds_boxscores_mlb: null,
sports_feeds_boxscores_nfl: {
sun: null,
mon: null,
thurs: null
},
sports_feeds_boxscores_nba: null,
etc
/* Component Code */
// First let's get the Game and BoxScores Data
const nflScores = async () => {
this.nfl_feeds.sunday_data = await getScores(
nflDate.sundayDate,
config
);
this.nfl_feeds.thurs_data = await getScores(
nflDate.thursdayDate,
config
);
this.nfl_feeds.mon_data = await getScores(nflDate.mondayDate, config);
// Next we need the gameid's to retrieve the game boxscores for each day
this.nfl_feeds.sunday_data.forEach(function(item, index) {
if (item.isCompleted === "true") {
nflGameIDs.sunday[index] = item.game.ID;
}
});
this.nfl_feeds.thurs_data.forEach(function(item, index) {
if (item.isCompleted === "true") {
nflGameIDs.thursday[index] = item.game.ID;
}
});
this.nfl_feeds.mon_data.forEach(function(item, index) {
if (item.isCompleted === "true") {
nflGameIDs.monday[index] = item.game.ID;
}
});
// Check if boxscores have been retrieved on previous tab click for each day
// if not retrieve the boxscores
this.sports_feeds_boxscores_nfl.sun =
this.sports_feeds_boxscores_nfl.sun ||
(await getBoxScores(nflGameIDs.sunday, url, params));
this.sports_feeds_boxscores_nfl.thurs =
(await getBoxScores(nflGameIDs.thursday, url, params));
this.sports_feeds_boxscores_nfl.mon =
this.sports_feeds_boxscores_nfl.mon ||
(await getBoxScores(nflGameIDs.monday, url, params));
}; /* End nflScores Async function */
getBoxScores.js:
try {
const getBoxScores = async (gameIDs, myUrl, params) => {
gameIDs.forEach(function(item) {
promises.push(
axios({
method: "get",
headers: {
Authorization:
"Basic &&*&&^&&=="
},
url: myUrl + item,
params: params
})
);
});
// axios.all returns a single Promise that resolves when all of the promises passed
// as an iterable have resolved. This single promise, when resolved, is passed to the
// "then" and into the "values" parameter.
await axios.all(promises).then(function(values) {
boxScores = values;
});
console.log(`boxScores is ${boxScores.length}`)
return boxScores;
};
module.exports = getBoxScores;
} catch (err) {
console.log(err);
}
I have split up all the sports_feeds_boxscores objects and at a loss as to why they are sharing state??? Sorry for verbosity of the question but it is somewhat complex. That is why I provided the site where you can see devtools that for instance this.sports_feeds_boxscores_nfl.thurs has 14 elements instead of one after the call to API. And if mlb tab is clicked after nfl tab then mlb results include the nfl results. I would really appreciate help in figuring this out. Thanks in advance...
Update:
I have added getBoxScores.js cause it seems as if I am returning the extra stats from this call.
This was my bad. I didnt realize I had created a closure in getBoxScores.js:
let boxScores = [];
let promises = [];
try {
const getBoxScores = async (gameIDs, myUrl, params) => {
gameIDs.forEach(function(item) {
promises.push(
axios({
method: "get",
headers: {
Authorization:
"Basic &&^^&^&&^FGG="
},
url: myUrl + item,
params: params
})
);
});
Moving declarations inside async function quickly solved trouble. URRRRGGGHHH!!!

Typeahead.js include dynamic variable in remote url

I have tried for hours now, to get a variable in my "remote" path. The variable will change, depending on another input. Here is the code:
school_value = $('#school').val();
$('#school').change(function () {
school_value = $(this).val();
$('#programme').typeahead('destroy'); // I have also tried with destroy - but it doesnt work.
});
$('#programme').typeahead({
remote: 'typeahead.php?programme&type=1&school_name=' + school_value,
cache: false,
limit: 10
});
The variable 'school_type' is not set in the remote addr, and therefore not called.
Do you have any clue how to get it working? I have just switched from Bootstrap 2.3 to 3, and then noticed typeahead was deprecated. Above code worked on Bootstrap 2.3, but it seems like when the script is initialized, the remote path is locked.
I have found the solution! Code:
$('#programme').typeahead({
remote: {
url: 'typeahead.php?programme&type=1&school_name=',
replace: function () {
var q = 'typeahead.php?programme&type=1&school_name=';
if ($('#school').val()) {
q += encodeURIComponent($('#school').val());
}
return q;
}
},
cache: false,
limit: 10
});
Based on this threads answer: Bootstrap 3 typeahead.js - remote url attributes
See function "replace" in the typeahead.js docs
I believe the accepted answer is now out of date. The remote option no longer has replace. Instead you should use prepare:
$('#programme').typeahead({
remote: {
url: 'typeahead.php?programme&type=1&school_name=',
prepare: function (query, settings) {
settings.url += encodeURIComponent($('#school').val());
return settings;
}
}
});
One issue I ran into was pulling the value from another typeahead object. Typeahead essentially duplicates your input, including all classes, so you have two nearly identical objects, one with the tt-hint class and the other with tt-input. I had to specify that it was the tt-input selector, otherwise the value I got was an empty string.
$('.field-make').val(); // was "" even though the field had a value
$('.field-make.tt-input').val(); // gave the correct value
Bloodhound remote options
There is actually a slight refinement of Mattias' answer available in the newer Bloodhound js, which reduces duplication and opportunity for error:
$('#programme').typeahead({
remote: {
url: 'typeahead.php?programme&type=1&school_name=',
replace: function (url, query) {
if ($('#school').val()) {
url += encodeURIComponent($('#school').val());
}
return url;
}
},
cache: false,
limit: 10
});
#Mattias, Just as a heads up, you could clean up your replace method a little by supplying the optional url parameter.
$('#programme').typeahead({
remote: {
url: 'typeahead.php?programme&type=1&school_name=',
replace: function (url, query) {
// This 'if' statement is only necessary if there's a chance that the input might not exist.
if ($('#school').val()) {
url += encodeURIComponent(('#school').val());
}
return url;
}
},
cache: false,
limit: 10
});
Am I looking at the same thing as all of you?
http://www.runningcoder.org/jquerytypeahead/
It looks like it has changed AGAIN! It is not very obvious how to do it in the documentation, but there is example code. I pulled this straight from the code in the documentation.
There is a second example in the documentation where they do it yet a different way! This way is the most succinct I think.
// Set a function that return a request object to have "dynamic" conditions
dynamic: true,
source: {
tag: {
ajax: function (query) {
if (query === "hey") {
query = "hi"
}
return {
url: "http://www.gamer-hub.com/tag/list.json",
dataType: "jsonp",
path: data,
data: {
q: query
}
}
}
}
}
And here is my working example:
source: {
ajax: function() {
var filter = {
partnerId: #Model.PartnerId,
productTypeId: #Model.ProductTypeId,
unitType: $("[name=UnitType]").val(),
manufacturer: "",
columnName: "#nameof(SaleViewModel.Manufacturer)"
};
var queryString = $.param(filter);
return {
url: recentEntriesBaseUrl + "?" + queryString
}
}
},
If you want to use wildcard parameter %QUERY, then add url = url.replace("%QUERY", q);
$('#programme').typeahead({
remote: {
url: 'typeahead.php?programme&q=%QUERY',
replace: function (url, q) {
url = url.replace("%QUERY", q);
let val = $('#school').val();
if(val) url += '&school_name=' + encodeURIComponent(val);
return url;
}
},
limit: 10
});

Categories