I'm trying to use more vanilla javascript instead if jquery. I have no problem making ajax calls with $.post but I can't seem to get it to work with vanilla javascript. This is my ajax call:
$(document).ready(function () {
$('#addAssignment').click(function () {
$('#addAssignmentModal').modal('toggle');
});
$('#submitAssignment').click(function () {
if(checkModal()){
var assignment = {
title: $('#newAssignmentTitle').val(),
type: $('#assignmentSelection').val(),
date: $('#newAssignmentDate').val(),
details: $('#newAssignmentDetails').val()
}
console.log(assignment);
submitAssignment(assignment);
}
});
});
function submitAssignment(assignment) {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
//Do stuff
}
};
request.open("POST", '/data/api/create-assignment/', true);
request.setRequestHeader('X-CSRFToken', cookies['csrftoken']);
//assignment is equal to: {title: "Title", type: "Homework", date: "02/18/2017", details: "Detais"}
request.send(JSON.stringify(assignment));
}
When I try and print out the data in my Djano view, it prints out an empty queryset every time.
def createAssignment(request):
if request.method == 'POST':
print(request.POST) # this prints an empty queryset
# assignment = Assignments()
# assignment = request.POST.get('assignment')
# assignment.save()
data = {}
data['status'] = "Success"
return HttpResponse(json.dumps(data), content_type="application/json")
else:
data = {}
data['status'] = "Data must be sent via POST"
return HttpResponse(json.dumps(data), content_type="application/json")
How do I prepare my data and receive it properly?
UPDATE:
I was able to get this working. The ajax call stays the same. In order to print the data in my django view, I used the following code:
body_unicode = request.body.decode('utf-8')
body = json.loads(body_unicode)
print(body)
Printing body gives the following:
{'details': 'Here are some details', 'title': 'Title', 'date': '02/18/2017', 'type': 'Homework'}
body_unicode = request.body.decode('utf-8')
body = json.loads(body_unicode)
print(body)
Related
I'm trying to submit a form in a Rails 5.1 app that uses Vue.js and Dropzone. During the sendingEvent I am using JSON.stringify on the object before sending it over to the controller. However, I don't feel this is the correct way to do it, as I am then having problems with using strong params in the controller.
JS:
import Vue from 'vue/dist/vue.esm'
import VueResource from 'vue-resource'
import vue2Dropzone from 'vue2-dropzone'
Vue.use(VueResource)
document.addEventListener('DOMContentLoaded', () => {
if(document.getElementById('listing-multistep') !== null) {
Vue.http.headers.common['X-CSRF-Token'] = document.querySelector('input[name="authenticity_token"]').getAttribute('value');
var listingForm = document.getElementById('listing_form');
var listing = JSON.parse(listingForm.dataset.listing);
var locale = document.getElementsByTagName('html')[0].getAttribute('lang');
const myForm = new Vue({
el: '#listing-multistep',
components: {
vueDropzone: vue2Dropzone
},
data: function () {
return {
id: listing.id,
locale: locale,
slug: listing.slug,
activeStep: 0,
// More data
dropzoneOptions: {
url: `/${locale}/listings`,
method: 'post',
acceptedFiles: 'image/*',
uploadMultiple: true,
autoProcessQueue: false,
parallelUploads: 15,
maxFiles: 15,
addRemoveLinks: true,
thumbnailWidth: 150,
maxFilesize: 5,
dictDefaultMessage: "<i class='fa fa-cloud-upload'></i> Drop files here to upload (max. 15 files)",
headers: { 'X-CSRF-Token': Vue.http.headers.common['X-CSRF-Token'] }
}
}
},
methods: {
sendingEvent: function(file, xhr, formData) {
// This function gets called by Dropzone upon form submission.
var listingObj = this.setupListingObj()
formData.append('listing', JSON.stringify(listingObj))
},
listingRedirect: function(files, response) {
window.location = `/${this.locale}/listings/${response.slug}`
},
submitListing: function() {
var numFiles = this.$refs.listingDropzone.getAcceptedFiles().length
// If there are images to upload, use Dropzone
// Else submit the form normally.
if(numFiles > 0) {
this.$refs.listingDropzone.processQueue()
} else {
var listingObj = this.setupListingObj()
if(this.id === null) {
// POST if it's a new listing
this.$http.post(`/${this.locale}/listings`, {listing: listingObj}).then(
response => {
window.location = `/${this.locale}/listings/${response.body.slug}`
}, response => {
console.log(response)
})
} else {
// PUT if it's an existing listing
this.$http.put(`/${this.locale}/listings/${this.slug}`, {listing: listingObj}).then(
response => {
window.location = `/${this.locale}/listings/${response.body.slug}`
}, response => {
console.log(response)
})
}
}
},
setupListingObj: function() {
// do some processing...
var listingObj = {
id: this.id,
name: this.name,
// set more attributes
}
return listingObj
},
}
}
});
as you can see I am using formData.append('listing', JSON.stringify(listingObj)) on the sendingEvent.
My controller:
class ListingsController < ApplicationController
def create
#listing = Listing.new JSON.parse(params[:listing])
#listing.owner = current_user
respond_to do |format|
if #listing.save
format.html { redirect_to listing_path(#listing), notice: 'Listing was created successfully!' }
format.json { render :show, status: :created, location: #listing }
else
format.html { render :new }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
private
def listing_params
params.require(:listing).permit(
:name,
:bedrooms,
:beds,
:bathrooms,
:price_cents,
:price_currency,
:property_type,
:city,
:state,
:address,
:lat,
:lng,
:description,
:amenities => []
)
end
end
It seems to work in development, but when I run a test with this code in RSpec I get errors like:
Internal Server Error no implicit conversion of ActionController::Parameters into String
When I try to swap #listing = Listing.new JSON.parse(listing_params) it fails to work in development.
I have a feeling I'm not sending the form data across properly. What is the correct way to send the data over via Javascript to my Rails controller? Does it need to be strigified and then posted? How can I access it via strong params instead?
Thanks in advance!
UPDATE
This is what my spec looks like:
RSpec.feature 'Listing owners can create new listings' do
let(:owner) { create(:user, :owner) }
before do
login_as owner
visit new_listing_path
end
scenario 'successfully', js: true do
fill_in 'Property name', with: 'Example property'
select 'Apartment', from: 'Property type'
fill_in 'Address', with: 'Somewhere'
click_button 'Next'
fill_in 'Property description', with: Faker::Lorem.paragraph(2)
click_button 'Create Listing'
expect(page).to have_content 'Listing was created successfully!'
end
end
I am using Chrome headless for these tests in order to parse the Vue.js stuff on the form. In my rails_helper.rb I have:
require 'spec_helper'
require 'rspec/rails'
require 'capybara/rails'
require 'capybara/rspec'
require 'pundit/rspec'
require 'selenium/webdriver'
RSpec.configure do |config|
# ...
Capybara.javascript_driver = :headless_chrome
end
and I have a support/chrome_driver.rb file with the following:
Capybara.register_driver(:headless_chrome) do |app|
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
chromeOptions: { args: %w[headless disable-gpu] }
)
Capybara::Selenium::Driver.new(
app,
browser: :chrome,
desired_capabilities: capabilities
)
end
I'm new to JavaScript and REST, and I need to implement JSON as datasource to devextreme using knockout.js.
My problem is, that I can fetch the json, but it is not added to the datasource. I used console.log() for testing and noticed that the json is correctly loaded, but the datasource is empty (see comments in code below). How can I achieve the usage of my json as datasource?
Note: I used DevExtreme load JSON as datasource using knockout as base for getting my JSON-contents.
I have a sample JSON-File looking like this:
{
"ID":"3",
"content":
{
"ProdId":"000176491264",
"ProdDesc":"Sample 1",
"Type":"A",
}
}
And my current viewmodel looks like this:
MyApp.overview = function (params) {
"use strict";
var getData = function () {
var deferred = $.Deferred();
var xmlhttp = new XMLHttpRequest(), json;
xmlhttp.onreadystatechange = function() {
if(xmlhttp.readyState === 4 && xmlhttp.status === 200) {
json = JSON.parse(xmlhttp.responseText);
// prints needed content:
console.log(json.content);
deferred.resolve(json.content);
}
};
xmlhttp.open('GET', 'http://localhost:56253/test/3?format=json', true);
xmlhttp.send();
return deferred.promise();
};
var viewModel = {
overviewDatagridOptions: {
dataSource: getData(),
selection: {
mode: "single"
},
columns: [{
dataField: "ProdId",
caption: "ID"
}, {
dataField: "ProdDesc",
caption: "Description"
}, {
dataField: "Type",
caption: "Type"
}],
rowAlternationEnabled: true
},
// Returns {}
console.log("Datasource: " + JSON.stringify(viewModel.overviewDatagridOptions.dataSource));
return viewModel;
};
Edit: I changed my datasource to this:
dataSource: {
load: function (loadOptions) {
var d = new $.Deferred();
var params = {};
//Getting filter options
if (loadOptions.filter) {
params.filter = JSON.stringify(loadOptions.filter);
}
//Getting sort options
if (loadOptions.sort) {
params.sort = JSON.stringify(loadOptions.sort);
}
//Getting dataField option
if (loadOptions.dataField) {
params.dataField = loadOptions.dataField;
}
//If the select expression is specified
if (loadOptions.select) {
params.select= JSON.stringify(loadOptions.select);
}
//Getting group options
if (loadOptions.group) {
params.group = JSON.stringify(loadOptions.group);
}
//skip and take are used for paging
params.skip = loadOptions.skip; //A number of records that should be skipped
params.take = loadOptions.take; //A number of records that should be taken
var obj;
$.getJSON('http://localhost:56253/test/3?format=json', params).done(function (data) {
d.resolve(data);
});
//return obj;
return d.promise();
}, [...]
Based on the demo found here: https://www.devexpress.com/Support/Center/Question/Details/KA18955
Now, the output from the datasource is no longer empty, and looks like this:
Object
- load:(loadOptions)
- arguments:(...)
- caller:(...)
- length:1
- name:"load"
- prototype:Object
- __proto__:()
- [[FunctionLocation]]
- [[Scopes]]:Scopes[1]
- totalCount:(loadOptions)
- arguments:(...)
- caller:(...)
- length:1
- name:"totalCount"
- prototype:Object
- __proto__:()
- [[FunctionLocation]]
- [[Scopes]]:Scopes[1]
- __proto__:Object
I have created a form in netsuite such that after it has been posted it should redirect to the the selected record. It's not occuring - what am I doing wrong?
if (request.getMethod() == 'GET') {
var slcustomer = form.addField('custpage_selectfield', 'select',
'Customer', 'customer');
form.addSubmitButton('Submit'); //For submiting as i will check for post back
response.writePage(form); //Write the form or display the form
} else {
if (request.getMethod() == 'POST') {
var task = request.getParameter('slcustomer');
nlapiSetRedirectURL('RECORD', 'task', null, false);
}
}
I tried using your code inside a suitelet function and it worked for me.
function suitelet(request, response){
if (request.getMethod() == 'GET') {
var form = nlapiCreateForm('My Custom Form', false);
var slcustomer = form.addField('custpage_selectfield', 'select',
'Customer', 'customer');
form.addSubmitButton('Submit'); //For submiting as i will check for post back
response.writePage(form); //Write the form or display the form
} else {
if (request.getMethod() == 'POST') {
var customerid = request.getParameter('custpage_selectfield');
nlapiLogExecution('debug', 'selected id', customerid);
nlapiSetRedirectURL('RECORD', 'task', null, false);
}
}
}
var slcustomer = form.addField('custpage_selectfield', 'select',
'Customer', 'customer');
This line creates a drop down list of Customer records.
var task = request.getParameter('custpage_selectfield');
nlapiLogExecution('debug', 'selected id', task);
nlapiSetRedirectURL('RECORD', 'task', null, false);
The task variable should contain the internal id of the selected customer. Your nlapiSetRedirectURL call is incorrect. If you want to redirect to the selected customer, it should be
nlapiSetRedirectURL('RECORD', 'customer', task);
I'm trying to pass my uploaded photo to javascript on a page, but I get this error. How can I fix it?
werkzeug.routing.BuildError
BuildError: ('uploaded_file', {'filename': u'user/user-1/scan.jpeg'}, None)
class AdminController(BaseController):
route_base = ''
route_prefix = '/admin'
trailing_slash = True
decorators = [login_required]
def __init__(self):
self.theme = "admin"
g.theme = self.theme
g.currentUser = g.auth.getUser()
self.viewData = {
"layout" : self.theme + "/" + "layouts/main.html"
}
class BaseMethodView(MethodView):
pass
class UserJsonDataController(AdminController, BaseMethodView):
def __init__(self):
super(UserJsonDataController, self).__init__()
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
def get(self):
json = {}
users = User.select()
a = []
for user in users:
obj = {
"user_avatar":url_for("uploaded_file", filename = user.user_avatar)
}
a.append(obj)
json["rows"] = a
return flask.jsonify(json)
module.add_url_rule('/index/show', view_func=UserJsonDataController.as_view('show'))
$(document).ready(function () {
$("#grid").kendoGrid({
dataSource: {
transport: {
read: {
url: '{{ url_for("user_admin.show") }}',
dataType: "json"
}
},
schema: {
data: "rows"
}
},
columns: [{
field: "user_avatar",
title: "Profil",
template: "<img src='/#=user_avatar #' /> "
}
});
});
I know this is old but why not. #huseyin, you mentioned that your image is located in: app/upload/user/user-1/scan.jpeg. Your url_for() first argument should match that path and in your code it's 'uploaded_file'. Try changing it to 'upload'
I've got a script that generates a form panel:
var form = new Ext.FormPanel({
id: 'form-exploit-zombie-' + zombie_ip,
formId: 'form-exploit-zombie-' + zombie_ip,
border: false,
labelWidth: 75,
formBind: true,
defaultType: 'textfield',
url: '/ui/modules/exploit/new',
autoHeight: true,
buttons: [{
text: 'Execute exploit',
handler: function () {
var form = Ext.getCmp('form-exploit-zombie-' + zombie_ip);
form.getForm().submit({
waitMsg: 'Running exploit ...',
success: function () {
Ext.beef.msg('Yeh!', 'Exploit sent to the zombie.')
},
failure: function () {
Ext.beef.msg('Ehhh!', 'An error occured while trying to send the exploit.')
}
});
}
}]
});
that same scripts then retrieves a json file from my server which defines how many input fields that form should contain. The script then adds those fields to the form:
Ext.each(inputs, function(input) {
var input_name;
var input_type = 'TextField';
var input_definition = new Array();
if(typeof input == 'string') {
input_name = input;
var field = new Ext.form.TextField({
id: 'form-zombie-'+zombie_ip+'-field-'+input_name,
fieldLabel: input_name,
name: 'txt_'+input_name,
width: 175,
allowBlank:false
});
form.add(field);
}
else if(typeof input == 'object') {
//input_name = array_key(input);
for(definition in input) {
if(typeof definition == 'string') {
}
}
} else {
return;
}
});
Finally, the form is added to the appropriate panel in my interface:
panel.add(form);
panel.doLayout();
The problem I have is: when I submit the form by clicking on the button, the http request sent to my server does not contain the fields added to the form. In other words, I'm not posting those fields to the server.
Anyone knows why and how I could fix that?
Your problem is here:
id: 'form-exploit-zombie-'+zombie_ip,
formId: 'form-exploit-zombie-'+zombie_ip,
what you are doing is that you are setting the id attribute of the form panel and the id attribute of the form (form tag) to the same value. Which means that you have two elements with the same id and that is wrong.
Just remove this line
formId: 'form-exploit-zombie-'+zombie_ip,
and you should be fine.
Did you check the HTTP Request parameter for the form values?
If you server side is in PHP, what do you get from response by passing any field name? For example, if one of your input name was "xyz" what do you get by
$_POST[ 'txt_xyz' ]