Django submit form without page refresh - javascript

I'm using Django-Angular and trying to post a form and obtain data in back-end..I'm able to achieve this but found that the page is reloading while saving the form. How can we achieve the same without page render?
forms.py
def home(request):
if 'application/json' in request.META['CONTENT_TYPE']:
print 'hi'
print request.body
return render(request, 'home.html', {})
home.html
<form name="indexForm" ng-submit="submitForm()">
<div class="form-group">
<label>File Path</label>
<input type="text" name="path" class="form-control" ng-model="file.path">
</div>
<div class="form-group">
<label>File Name</label>
<input type="text" name="file_name" class="form-control" ng-model="file.file_name">
</div>
<div class="form-group">
<label>ext</label>
<input type="text" name="ext" class="form-control" ng-model="file.ext">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
script
$scope.submitForm = function() {
console.log('from submit')
$http({
url: 'http://127.0.0.1:8000/',
data: $scope.file,
method: 'POST',
headers: {
'X-CSRFToken': $cookies['csrftoken']}
})
}
Please let me know code above is correct way of posting data? How can we post data from angular to backend(django) without page refresh
Thanks in advance...Any help is much appreciated

In your home request you should not render the page again, but rather return a string or some JSON to the client. If you are using a newish version of django you can do something like this:
from django.http import JsonResponse
def home(request):
if 'application/json' in request.META['CONTENT_TYPE']:
print 'hi'
print request.body
return JsonResponse({'foo':'bar'})
return render(request, 'home.html', {})

Replace type="submit with type="button". Then you can just call any method in the backend with ng-click="ctrl.foo()"
At least that is what I have been doing so far. Looking at the docs however indicates that is not the issue.

Related

Flask Error "The method is not allowed for the requested URL." when using Ajax post call

I used ajax call to send data to server from a form and receive data as a jsonify. But I'm getting Error that "The method is not allowed for the requested URL." and I cannot what is wrong with the code.
This is form data.
<form class="form-submit" method="post" role="form">
<div class="input-group">
<input name="userID" id="userID" type="text" class="form-control width100" placeholder="Input User ID" style="width: 80%;">
<span class="input-group-btn">
<button id="button" class="btn btn-secondary" type="submit"><i class="fa fa-search"></i></button>
</span>
</div>
</form>
Following is ajax call to post data. Here I'm calling from post.html.
$('#button').click(function (event) {
$.ajax({
data:{
userID : $('#userID').val()
},
type : "POST",
url : '/charts'
}).done(function (data) {
console.log(data.id);
});
event.preventDefault();
});
And Here is my relevant code.
#app.route('/posts',methods=["POST"])
def posts():
if request.method == "POST":
id = request.form['userID']
return jsonify({"id": id})
return render_template('posts.html')
I cannot figure out what is the problem with this. For this I'm getting both errors which are,
POST http://127.0.0.1:5000/posts 405 (METHOD NOT ALLOWED)
and
GET http://127.0.0.1:5000/favicon.ico 404 (NOT FOUND)
Can anyone help me with this. I checked all the relevant questions and didn't found a help.

JSON Post request is showing 200 success, but script is not executing

FrontEnd
this gets the name, age, city puts it in a JSON format and sends it to localhost:5100/getJson which is my backend.
<form>
<div class="form-group">
<label for="text">Name:</label>
<input type="text" class="form-control" id="name" placeholder="Enter name" name="name">
</div>
<div class="form-group">
<label for="text">Age:</label>
<input type="text" class="form-control" id="age" placeholder="Age" name="age">
</div>
<div class="form-group">
<label for="text">City:</label>
<input type="text" class="form-control" id="city" placeholder="Enter city" name="city">
</div>
<button onclick = "MyFunction()" id = "submitButton" type="submit" class="btn btn-default">Submit</button>
<p id = "demo">
</p>
<script>
function MyFunction() {
var name = document.getElementById("name").value
var age = document.getElementById("age").value
var city = document.getElementById("city").value
jsonRequest = {"name":name, "age":age, "city":city}
fetch('http://localhost:5100/acceptJson', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: jsonRequest
}).then(res => res.json())
}
</script>
my backend is a flask server in python.
Backend
app = Flask(__name__)
#app.route('/acceptJson',methods=['GET', 'POST'])
def acceptJson():
jsonData = request.json
name = jsonData['name']
age = jsonData['age']
city = jsonData['city']
postToDatabase(name,age,city)
return "Succesful"
if __name__ == '__main__':
app.run(host = "localhost", port = 5100)
Now when I make the same JSON post request using software like Postman it works, returns 200 and runs the script.
but when I do it through the code, it return 200 and doesn't run the script, so it's clearly something wrong with the POST in the javascript, but I do not understand where it's wrong.
The problem seems to be related to your front-end. In the following answer, I assume your form is submitted by "MyFunction".
In this line of HTML:
<button onclick = "MyFunction()" id = "submitButton" type="submit" class="btn btn-default">Submit</button>
The button is a submit type button. When you click the button, the browser submits the form as usual. With no "action" attribute in the tag, the request is submitted to the webpage you open i.e. no request was sent to the back-end.
The solution can be found in this question: Form not submitting with JS. However, I would suggest another method to do so.
You may add "event.preventDefault();" before you call the function of handling the request or add it to the beginning of the function to stop the form from being submitted automatically in a traditional way.
<button onclick = "event.preventDefault();MyFunction()" id = "submitButton" type="submit" class="btn btn-default">Submit</button>
The reason why to use preventDefault is that it only stop the browser default behavior while other solution (return false) stop the event propagating the DOM.

Convert HTML form into Angular POST request

I have this form in HTML and I am trying to convert it into a POST request using a frontend framework (either AngularJS or Angular2). The purpose of this form is to allow a client to subscribe to my wordpress blog. I am trying to convert it from PHP to Angular2 (if someone knows how to convert it to AngularJS I can convert to Angular2 from there). How would I do this? What would have to be in the body of the POST request vs query strings? I am having trouble understanding exactly what role each part of this form plays in the POST request.
EDIT: Just to clarify, I know how to use AngularJS and Angular2 and how to use the HTTP service in both of them. I am wondering how to convert the form into the body/query strings of the request.
<form action="/blog/" class="form-inline" role="form" method="POST" accept-charset="utf-8" id="subscribe-blog">
<!-- add hidden inputs for wordpress jetpack widget -->
<input type="hidden" name="action" value="subscribe" />
<input type="hidden" name="source" value="http://www.mywebsite.com/blog/" />
<input type="hidden" name="sub-type" value="widget" />
<input type="hidden" name="redirect_fragment" value="blog_subscription-2" />
<label class="sr-only" for="exampleInputEmail">Email address</label>
<input type="email" class="form-control wide" id="exampleInputEmail" placeholder="Enter email address">
<button type="submit" name="jetpack_subscriptions_widget" class="btn btn-submit">Subscribe</button>
</form>
Would something along the lines of this be correct?
postForm() {
var body = {
action: 'subscribe',
source: 'http://www.mywebsite.com/blog/',
sub-type: 'widget',
redirect_fragment: 'blog_subscription-2',
email: 'clientEmailAddress#gmail.com', // don't think this is right
// not sure what to do with `jetpack_subscriptions_widget` attribute on the submit button either
};
return this.http.post(`http://www.mywebsite.com/blog/`, body)
.map(res => res.json())
.toPromise()
.then(data => {
return data;
});
}
You need to include angular.min.js and script.js
html
<body ng-app="myApp" ng-controller="myCtrl">
<input type="text" ng-model="name" />
<input type="submit" value="Send" ng-click="send(name)"/>
</body>
angular js code:
script.js
angular.module('myApp', [])
.controller('myCtrl', ['$scope', '$http', funtion($scope, $http){
$scope.name = ""; // intially the input field is empty. As you type in the input field, the value will be updated here.
$scope.send = function(name){
alert(name);
var url = $scope.name; // try to enter an url
$http.get(url).then(function Success(res){
// here you can do anything with res
}, function Error(err){
alert(error);
})
}
}]);
Using angular, you split the application in parts:
view (html)
process some validations, etc (controller)
and do some model logic processing (service).
If you want to make the http request completely with angular to an endpoint (backend service, REST, or any other), usually in this case:
You use ng-model for each input field you need to send in the request, something like <input type="text" ng-model="val">. In your case your html would be something like:
html
<form ng-submit="send()" class="form-inline" role="form" accept-charset="utf-8" id="subscribe-blog">
<!--no need of 'action' attribute in the form since the post will be done using angular-->
<!-- add hidden inputs for wordpress jetpack widget -->
<input type="hidden" name="action" value="subscribe" ng-model="subscribe"/>
<input type="hidden" name="source" value="http://www.mywebsite.com/blog/" ng-model="source"/>
<input type="hidden" name="sub-type" value="widget" ng-model="widget" />
<input type="hidden" name="redirect_fragment" value="blog_subscription-2" ng-model="redirect_fragment"/>
<label class="sr-only" for="exampleInputEmail">Email address</label>
<input type="email" class="form-control wide" id="exampleInputEmail" placeholder="Enter email address" ng-model="email">
<button type="submit" name="jetpack_subscriptions_widget" class="btn btn-submit">Subscribe</button>
</form>
Then in your controller you can process all your ng-model if needed and then pass those values to a (angular) service like this
//....angular controller
function send(){
//..collect params using the ng-models
var params = [];
params['email'] = $scope.email; //here you define 'email' as the name of the param received by the webservice as input !!!
myService.sendValues(params).then(function(data){
})
}
...where you would finally send the values to the php service like code below:
//... angular service
function sendValues(params){
var url = "miendpointurl/subscribe";
//... at this pont in params you have all those params you named like 'email', 'subscribe' and so on
return $http.post(url, params).then(function(response){
return response.data;
},
function(responseOnError){
return responseOnError.data;
}
}
Angular will interact with the php service transparently to you and will give you back the server response.

Laravel timeout on auth login

Laravel 5.3 - My goal is to send login form via ajax to login controller (AuthenticatesUsers trait), and to get a response (json would be ok), so i could set timeout before redirect to "dashboard" section (authenticated). I need that timeout for some frontend stuff.
So could it be done? If it could, hint would suffice.
Thanks in advance.
Javascript example:
$("#login-form").submit(function (e) {
var url = "/login"; // the script where you handle the form input.
$.ajax({
type: "POST",
cache : false,
url: url,
data: $("#login-form").serialize(), // serializes the form's elements.
success: function ()
{ //Do the timeout part, then redirect
topbar.addClass('success');
form.addClass('goAway');
article.addClass('active');
tries = 0;
},
error: function () {
location.reload();
input.addClass('disabled');
topbar.addClass('error');
}
});});
Login form is sent via post, and i would like to do a redirect by myself, not via controller, and my main concern is the csrf token on javascript redirect would change.
edit:
Another thing that I discovered is including token inside ajax setup:
$.ajaxSetup({
headers: {'X-CSRF-TOKEN': _token}
});
and prevent form default action:
$("#login-form").submit(function (e) {
e.preventDefault();
Here's my login form (all js and css is included in parent view):
#extends('layouts.app')
#section('content')
<form class="form form-horizontal" id="login-form" role="form" method="POST" action="{{ url('/login') }}">
{{ csrf_field() }}
<div class="forceColor"></div>
<div id="logosm_wrapper">
<img id="logosm_login" src="img/ipism_100x50.png" alt="logo" >
</div>
<div class="forceColor"></div>
#if (count($errors))
<div class="topbar error">
#else
<div class="topbar">
#endif
<div class="spanColor"></div>
<input id="email" type="email" class="input form-control" name="email" placeholder="E-mail" value="{{ old('email') }}">
</div>
#if (count($errors))
<div class="topbar error">
#else
<div class="topbar">
#endif
<div class="spanColor"></div>
<input id="password" type="password" class="input form-control" name="password" placeholder="Password"/>
</div>
<button class="submit" id="submit">Login</button>
<!--input class="submit" id="submit" type="submit" value="Login"-->
</form>
#endsection
This is working as intended by Laravel Auth, my intention was to green out input fields on authorisation via JS, and then redirect user to dashboard...
I suggest u add this in your ajax:
$.ajax({
....
async : false,
....

Take string from input and make an AJAX request in AngularJS

Here is my code :
http://jsfiddle.net/n8t2born/1/
there are 3 js files , and it works pretty much good when I use static URL (without inputCity variable inside) . How should I tell angular correctly to take that info from my input and put it into the link and show weather info for a particular city ?
This is my form:
<form class="form-container" ng-submit="Weather.getWeather(inputCity)">
<input class="input-field" type="text" ng-model="inputCity" placeholder="City">
<input class="button-style" type="submit" value="Show Weather">
</form>
and it is my angular.factory:
angular
.module('weather.factory', [])
.factory('Weather', [
'$http',
function($http) {
return {
getWeather : function(inputCity) {
return $http({
url: 'http://api.wunderground.com/api/KEY/conditions/q/' + inputCity + '.json',
method: 'GET'
})
}
}
}
]);
You should never call you service method from your controller which has promise, It should call from controller & then update you required location data in ajax sucess
HTML
<form class="form-container" ng-submit="submitForm(inputCity)">
<input class="input-field" type="text" ng-model="inputCity" placeholder="City">
<input class="button-style" type="submit" value="Show Weather">
</form>
Code
$scope.submitForm =function(inputCity){
Weather.getWeather(inputCity).success(function(){
//data updation will lie here
}).error(function(error){
//do error handling here
})
};

Categories