I've written a form that has a n amount of steps, and after parsing the data into string object (to put inside the request body) inside JavaScript, I want to load it up and send it to my Flask backend server.
{
"0": {
"function": "go_to_url",
"values": {
"url": "https://valid.url/"
}
},
"1": {
"function": "refresh",
"values": {
"amount": "5"
}
},
"2": {
"function": "take_screenshot",
"values": {
"name": "screenshotname"
}
},
"3": {
"function": "send_keys_to_element",
"values": {
"xpath": "//*[#value='login']",
"keysToSend": "loginname"
}
},
"4": {
"function": "assert_element_exist",
"values": {
"xpath": "//button[#login]"
}
}
}
This is what I want to send with onclick function within a button inside mentioned form. My Js call looks like this
function submitScenario() {
const steps = Array.from(document.getElementsByClassName('scenario-creation-step'));
const data = {};
for (const c in steps) {
var currentStep_dict = {};
currentStep_dict['function'] = steps[c].childNodes[0].value;
let inputs = Array.from(steps[c].childNodes[1].getElementsByTagName('input'));
var values = {};
for (const i in inputs) {
values[inputs[i].getAttribute('data')] = inputs[i].value;
}
currentStep_dict['values'] = values;
data[c] = currentStep_dict;
}
var dataJson = JSON.stringify(data);
console.log(dataJson);
fetch(window.location.href + 'ed',
{
method: 'POST',
headers: {
'Content-Type':'application/json',
},
body: dataJson,
}
);
}
The form presents itself like that, with url set for 'scenario_added'
<form action="{{ url_for('scenario_added') }}" method="post" name="scenarioForm">
<!-- inputs hidden for data being fetched from flask -->
<input type="hidden" id="scenario_name" value="{{ scenario_details[0] }}" />
<input type="hidden" id="expected" value="{{ scenario_details[1] }}" />
<input type="hidden" id="author_id" value="{{ scenario_details[2] }}" />
<input type="hidden" id="steps_to_show" value="{{ step_names }}" />
<div id="scenario-creation-table" class="scenario-creation-table">
<button type="button" id="add_step">Add a step</button>
<!-- steps show here -->
</div>
<div class="scenario-creation-submitbuttons">
<div></div>
<div></div>
<input type="button" id="download_json" value="Pobierz scenariusz">
<input type="submit" id="submit_scenario_button" value="Dodaj Scenariusz" onclick="submitScenario()">
</div>
The view for scenario_added looks as follows:
#app.route("/scenario_added", methods = ["GET", "POST"])
def scenario_added():
if request.method == "GET":
return '<h6>bad request, it was get for /scenario_added</h6>' #TODO 404
scenario_data = request.json
return render_template('scenario_added.html', data = scenario_data)
Unfortunately, after sending such request, I'm presented with "Bad Request
Did not attempt to load JSON data because the request Content-Type was not 'application/json'."
Even though, when I send the request via POSTMAN on the url, I receive a 200 Code with expected result of the html view containing the data.
How should I rearrange the form or JavaScript function so it will send a request with data gathered from the form?
Related
I am trying to query the database based on what the user has clicked on the page and display the data retrieved by it without refreshing the page. I am using Ajax for this. Let me show you the codes
html
<label for="landacq" class="civil-label">Land Acquisation Cases</label>
<input class="civil-category" type="radio" name="civil-cat" id="landacq" value="land acquisation" hidden>
<label for="sc" class="civil-label">Supreme Court</label>
<input class="civil-court" type="radio" name="civil-court" id="sc" value="supreme court" hidden>
<label for="limitation" class="civil-label">Limitation</label>
<input class="civil-law-type" type="radio" name="civil-law-type" id="limitation" value="limitation" hidden>
js
for (i = 0; i < lawTypeInput.length; i++) {
lawTypeInput[i].addEventListener("click", (e) => {
e.preventDefault();
cat = civilCatval;
court = civilCourtval;
lawT = civillawTypeval;
console.log("this is from ajax : ", cat, court, lawT);
$.ajax({
type: "POST",
headers: { "X-CSRFToken": csrftoken },
mode: "same-origin", // Do not send CSRF token to another domain.
url: "civil",
data: {
"cat[]": civilCatval,
"court[]": civilCourtval,
"lawT[]": civillawTypeval,
},
success: function (query) {
showCivilQ(query);
// console.log(data);
},
error: function (error) {
console.log(error);
},
});
});
}
function showCivilQ(query) {
q.textContent = query;
console.log(query);
}
So here for example, if the user the click the radio button in the html, the values are grabbed by in js file and then sent to the url mentioned as a POST request. There these values are use to filter the database and return the objects like this
views.py
def civil_home(request):
if request.is_ajax():
get_cat = request.POST.get('cat[]')
get_court = request.POST.get('court[]')
get_lawT = request.POST.get('lawT[]')
query = Citation.objects.filter(law_type__contains ='civil' ,sub_law_type__contains= get_cat, court_name__contains = get_court, law_category__contains = get_lawT)
return HttpResponse(query)
else:
subuser = request.user
subscription = UserSubscription.objects.filter(user = subuser, is_active = True)
context = {
'usersub': subscription,
}
return render(request, 'civil/civil_home.html', context)
This is the result I am getting which is correct.
My Question is these objects contain attributes having some values in for eg, title, headnote etc. How can I display these attributes in the html rather than displaying the object names returned as shown in the Image like title of the citation, headnote of the citation etc
A solution could be to return a json object instead of the query resultset; because Ajax works well with json
You need a function that translates a Citation object into a dictionary (change it based on your real attributes). All elements must be translated into strings (see date example)
def citation_as_dict(item):
return {
"attribute1": item.attribute1,
"attribute2": item.attribute2,
"date1": item.date.strftime('%d/%m/%Y')
}
This dictionary must be translated into a json through import json package
def civil_home(request):
if request.is_ajax():
get_cat = request.POST.get('cat[]')
get_court = request.POST.get('court[]')
get_lawT = request.POST.get('lawT[]')
query = Citation.objects.filter(law_type__contains ='civil' ,sub_law_type__contains= get_cat, court_name__contains = get_court, law_category__contains = get_lawT)
response_dict = [citation_as_dict(obj) for obj in query]
response_json = json.dumps({"data": response_dict})
return HttpResponse(response_json, content_type='application/json')
else:
subuser = request.user
subscription = UserSubscription.objects.filter(user = subuser, is_active = True)
context = {
'usersub': subscription,
}
return render(request, 'civil/civil_home.html', context)
In your HTML page you should be able to parse the response as a normal JSON object
I figured out another way to do it, which is giving me the required results too.
Here I am filtering the values of the query, and then converting it to a list and passing it as a JsonResponse
views.py
def civil_home(request):
if request.method == "POST" and request.is_ajax():
get_cat = request.POST.get('cat[]')
get_court = request.POST.get('court[]')
get_lawT = request.POST.get('lawT[]')
query = Citation.objects.values().filter(law_type__contains ='civil' ,sub_law_type__contains= get_cat, court_name__contains = get_court, law_category__contains = get_lawT)
result = list(query)
return JsonResponse({"status": "success", "result": result})
else:
subuser = request.user
subscription = UserSubscription.objects.filter(user = subuser, is_active = True)
context = {
'usersub': subscription,
}
return render(request, 'civil/civil_home.html', context)
And then I am recieving the reponse here and iterrating over it to print the attributes in the html
js
for (i = 0; i < lawTypeInput.length; i++) {
lawTypeInput[i].addEventListener("click", (e) => {
e.preventDefault();
cat = civilCatval;
court = civilCourtval;
lawT = civillawTypeval;
console.log("this is from ajax : ", cat, court, lawT);
$.ajax({
type: "POST",
headers: { "X-CSRFToken": csrftoken },
mode: "same-origin", // Do not send CSRF token to another domain.
url: "civil",
data: {
"cat[]": civilCatval,
"court[]": civilCourtval,
"lawT[]": civillawTypeval,
},
success: function (response) {
console.log(response.result);
civilData = response.result;
if ((response.status = "success")) {
$("#queryResult").empty();
for (i = 0; i < civilData.length; i++) {
$("#queryResult").append(
`
${civilData[i].title}
<p>${civilData[i].headnote}</p>
`
);
}
} else {
$("#queryResult").empty();
$("#queryResult").append(
`
<p>No Citations Found</p>
`
);
}
},
error: function (error) {
console.log(error);
},
});
});
}
A csrf_token can be mentioned at the top of the html page and then it can be passed in the header to avoid any conflict.
I am creating a Package Tracking Form for a courier company.
Here is my html form
<h2>Track Package</h2>
<form>
<label for="trackingno">Tracking No:</label>
<input type="tel" id="trackingno" name="trackingno">
<input type="submit" value="Submit">
</form>
Company has provided the API Link
http://portal.activecourier.pk/api/v1/packet/00003711/status
When I click this link I get this data
{"packet_id": "0024-00003711", "consignee_name": "Nasir maqbool", "destination": "Lahore", "current_status": {"status": "Assigned to Courier", "datetime": "2020-12-27T17:55:05.414Z", "comment": null}, "statuses": [{"status": "Pickup request sent", "datetime": "2020-12-27T09:55:41.295Z", "comment": null}, {"status": "Booked", "datetime": "2020-12-26T10:13:15.333Z", "comment": null}]}
I want to use html form so visitor enters his package tracking # and get his package details
They usually use jquery to do this
$('#submit').click(function() {
const response = $('#response');
const trackingId = $('#trackingId').val();
let html = '';
$('#trackingId').val('');
response.html('Please Wait');
$.get('http://portal.activecourier.pk/api/v1/packet/'+trackingId+'/status', function(data) {
html += '<div><strong>Packet Id:</strong> '+data.packet_id+'</div>';
html += '<div><strong>Consignee Name:</strong> '+data.consignee_name+'</div>';
html += '<div><strong>Current Status:</strong> '+data.current_status.status+' at '+data.current_status.datetime+'</div>';
let statuses = data.statuses.map((e) => {
return e.status + ' at ' + e.datetime
});
html += '<div><strong>Statuses:</strong> <ul><li>'+statuses.join('</li><li>')+'</li></ul></div>';
response.html(html);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="response"></div>
<input type="text" id="trackingId"/>
<button type="button" id="submit">Submit</button>
I wrote this Vue.JS code to display JSON response received from PHP file in a conversation format. My current code looks like this:
const app = new Vue({
el: "#chatview",
data: {
messages:[],
txtInput: '',
mid:0
},
methods:{
GetBubbleType: function (name){
if(name === "AI")
return "yours messages";
else
return "mine messages";
},
},
mounted(){
axios.post('./ConversationGetter.php',{
function2call: 'getRecord',
id: 1,
}).then( response => {console.log(response.data);
this.data=response.data;
}).catch(error => {});
},
template: `
<div style ="font-family:Open Sans;font-size:16px">
<div v-for="message in messages">
<div class="fade-in">
<div v-bind:class="GetBubbleType(message.name)">
<div class="message last">
<p>{{message.message}}</p>
</div>
</div>
</div>
</div>
<form #submit.prevent="sendMessage('out')" id="person-form">
<p>
<input type="text" placeholder="Enter Your Query Here"style=" border-radius=25px" v-model="txtInput">
</input>
<input type="submit" placeholder="Send"style=" border-radius=25px">
</input>
</p>
</form>
</div>
`
})
The response recieved from PHP is (written on console):
{
"data": [
{
"Modified_Time": "2019-12-13T16:08:36+05:30",
"$currency_symbol": "$",
"Message": "Hey!",
"Created_Time": "2019-12-13T16:08:36+05:30",
"Name": "AI",
},
{
"Modified_Time": "2019-12-13T16:08:27+05:30",
"$currency_symbol": "$",
"Message": "Yo!",
"Created_Time": "2019-12-13T16:08:27+05:30",
"Name": "Me",
},
],
}
The return line of PHP is: echo $result; return $result;
For some reason, it does not show the messages in the chat view.. Where am I going wrong?
Your template is doing a v-for on the messages object from the component's data. However, you're assigning this.data=response.data. That's creating a property data on the component instance, not assigning the messages value.
Instead, just change this.data=response.data to this.messages=response.data.data.
As noted in the comments, your response body contains a data array at the root, and Axios returns the response body in response.data, hence response.data.data is what should be assigned to this.messages.
I'm creating a new custom RESTful web service (managed with Spring framework) on a Jhipster app that search on objects Request containing a text that I give in input.
I tested the REST call from html and Angular.js and it works fine. The only one problem is that I don't know how could I parse the result in a html page instead of .json format.
My html code (located in "src/main/webapp/app/layouts/navbar/navbar.html") that call REST is this:
<form class="navbar" method="GET" action="/api/search">
<input style="margin-top: 2.8%; margin-right:2px;" class="btn" type="text" name="content" placeholder="Search requests..." />
<input style="margin-top: 2.8%; margin-right:5px;" class="btn btn-primary" type="submit" text="Search" value="Search">
</form>
My "navbarController.js" is this:
(function () {
'use strict';
angular
.module('businessRequestApp')
.controller('NavbarController', NavbarController);
NavbarController.$inject = ['$state', 'Auth', 'Principal', 'ProfileService', 'LoginService', 'Request'];
function NavbarController($state, Auth, Principal, ProfileService, LoginService, Request) {
var vm = this;
vm.isNavbarCollapsed = true;
vm.isAuthenticated = Principal.isAuthenticated;
ProfileService.getProfileInfo().then(function (response) {
vm.inProduction = response.inProduction;
vm.swaggerEnabled = response.swaggerEnabled;
});
vm.login = login;
vm.logout = logout;
vm.toggleNavbar = toggleNavbar;
vm.collapseNavbar = collapseNavbar;
vm.$state = $state;
vm.requests = [];
loadAll();
function loadAll() {
Request.query(function (result) {
vm.requests = result;
vm.searchQuery = null;
});
}
function login() {
collapseNavbar();
LoginService.open();
}
function logout() {
collapseNavbar();
Auth.logout();
$state.go('home');
}
function toggleNavbar() {
vm.isNavbarCollapsed = !vm.isNavbarCollapsed;
}
function collapseNavbar() {
vm.isNavbarCollapsed = true;
}
}
})();
My java REST ("RequestResource.java") is this:
#GetMapping("/search")
#Timed
public ResponseEntity<List<Request>> searchRequest(#RequestParam String content) {
log.debug("REST request to get Request : {}", content);
List<Request> requestsFounded = findByContentContaining(content);
return ResponseUtil.wrapOrNotFound(Optional.ofNullable(requestsFounded));
}
When I click the button I receive this .json (that is a list of matching Request that I searched for - based on parameter content give in input):
[ {
"id" : 13,
"requestTitle" : "Titolo",
"content" : "Richiesta",
"creationDate" : "2017-06-23",
"authorUsername" : "admin",
"author" : null,
"referencedTable" : {
"id" : 3,
"usersOnIt" : "",
"name" : "Tavolo 1"
}
}, {
"id" : 14,
"requestTitle" : "Voglio vedere Tiziano Ferro",
"content" : "Mi piacerebbe vedere tiziano per fare ...",
"creationDate" : "2017-06-25",
"authorUsername" : "admin",
"author" : null,
"referencedTable" : {
"id" : 4,
"usersOnIt" : "alfa",
"name" : "Tavolo 3"
}
}, {
"id" : 19,
"requestTitle" : "Titolo",
"content" : "Voglio vedere Marco",
"creationDate" : "2017-06-26",
"authorUsername" : "user",
"author" : null,
"referencedTable" : null
} ]
So, my final question is: how could I translate that .json objects list into an html table?
I've been searching a lot on the web but I found nothing, I hope someone will help me.
Thanks in advice for your time,
Manuel.
You can call a function on form submit and get the json in your vm instance inside your function
HTML
<form class="navbar" ng-submit="vm.getJson()">
<input style="margin-top: 2.8%; margin-right:2px;" class="btn" type="text" name="content" ng-model="vm.content" placeholder="Search requests..." />
<input style="margin-top: 2.8%; margin-right:5px;" class="btn btn-primary" type="submit" text="Search" value="Search">
</form>
<tr ng-repeat="value in json"><td>{{value }}</td></tr>
JS:
vm.getJson=function(){
$http.get("YourUrl",vm.content).then(function(response){
vm.json=response.data;
console.log(response);
})
}
On my page, I'm rendering form, where data comes from api call
data looks like:
{
"id": 22,
"eventTypeId": 1,
"occuredDate": "2016-05-25T00:00:00",
"title": "event refresh",
"description": "check refresh table",
"studyId": 4,
"statusId": 5,
"severityId": 2,
"priorityId": 3,
"study.id": 4,
"study.name": "Study Y",
"status.id": 5,
"status.name": "Closed"
}
html:
<form style="padding: 15px" ng-submit="submitForm()">
<div class="form-group row">
<div ng-repeat="k in rowKeys | filter: '!id'" ng-model="rowValue">
<label for="rowValue" class="col-sm-2">
{{k | hide:'.name'}}:</label>
<div class=" col-sm-2" >
<input class="form-control rowValue" id="rowValue" ng-model="rowData[k]" ng-disabled="isDisabled()"/>
</div>
</div>
</div>
<button type="submit" class="btn btn-default" ng-if="rowData" >Submit</button>
</form>
My problem is when I edit fields such as "title" or "description", everything works fine, but when I try to edit fields such as "study.name" or "status.name" it just refresh the page and doesn't put any updates. Angular watch works fine and I see in console that value has been updated, so could anybody help me to find my mistake?
My submit function:
$scope.submitForm = function() {
$scope.$watch('rowData', function(newValue, oldValue) {
console.log('being watched oldValue:', oldValue, 'newValue:', newValue);
}, true);
$http({
method : 'PUT',
url : $scope.globalUrl + $scope.id,
data : $scope.rowData //form
})
.then(function (res) {
return res;
})
.then(function (){
$('#table').bootstrapTable('refreshOptions', {
'url': $scope.globalUrl
});
})
};
My load function
$scope.load = function (){
$http({
method: "GET",
url: $scope.globalUrl + $scope.id
}).then(function success(response) {
$scope.rowData = response.data;
}, function error(response) {
console.log("It has happend error in response")
});
}
When you have a dot in your key you need to use bracket notation:
obj['study.name']
Here is a quick example:
https://jsbin.com/fihogu/1/edit?js,console