Using post from Angular.js does not work - javascript

Ive built a rest-API to add todos in a mongodb. I can successfully save instances by using the following setup in postman:
http://localhost:3000/api/addtodo x-www-form-urlencoded with values text="Test", completed: "false".
Now when I try to replicate this with Angular, it doesnt work, the todo is saved but without the text and completed attributes, I cant seem to access the text or completed values from body. What am I doing wrong? Code below:
Angular-HTML:
<div id="todo-form" class="row">
<div class="col-sm-8 col-sm-offset-2 text-center">
<form>
<div class="form-group">
<!-- BIND THIS VALUE TO formData.text IN ANGULAR -->
<input type="text" class="form-control input-lg text-center" placeholder="I want to buy a puppy that will love me forever" ng-model="formData.text">
</div>
<!-- createToDo() WILL CREATE NEW TODOS -->
<button type="submit" class="btn btn-primary btn-lg" ng-click="createTodo()">Add</button>
</form>
</div>
</div>
Angular-js:
$scope.createTodo = function() {
$http.post('/api//addtodo', $scope.formData)
.success(function(data) {
$scope.formData = {}; // clear the form so our user is ready to enter another
$scope.todos = data;
console.log(data);
})
.error(function(data) {
console.log('Error: ' + data);
});
};
REST-API:
router.post('/addtodo', function(req,res) {
var Todo = require('../models/Todo.js');
var todo = new Todo();
todo.text = req.body.text;
todo.completed = req.body.completed;
todo.save(function (err) {
if(!err) {
return console.log("created");
} else {
return console.log(err);
}
});
return res.send(todo);
});

$http.post sends it's data using application/json and not application/x-www-form-urlencoded. Source.
If you're using body-parser, make sure you've included the JSON middleware.
app.use(bodyParser.json());
Either that or change your default headers for angular.
module.run(function($http) {
$http.defaults.headers.post = 'application/x-www-form-urlencoded';
});

Related

$http.get unable to fetch data from SpringBoot controller

I am creating an application which will run queries on my store's database, based on what the user enters on the webpage. I have successfully created the backend method. And it successfully returns the response. But I am unable to retrieve the data and display it on my webpage in the form of a dynamic table. I am a bit new to AngularJS, so please bear with me, but any help is appreciated.
StoreController.java
#RequestMapping(value = "/runQuery", method = RequestMethod.GET)
public List<Map<String, Object>> runQuery(#RequestParam(value="query", defaultValue="* FROM items") String statement, Model model) {
List<Map<String, Object>> answer = storeService.executeUserQuery(statement);
model.addAttribute("resultList", answer);
return answer;
}
I tried to model my controller in such a way that it can dynamically take the data received from the Java controller and assign it to the $scope variable.
app.module.js
(function(){
'use strict';
angular.module('app', []);
})();
store.controller.js
angular
.module('app').controller('StoreController', ['$scope','StoreService','StoreController','$q', function ($scope,StoreService, StoreController, $q) {
$scope.runQuery = function () {
StoreService.runQuery($scope.statement)
.then (function (data){
$scope.rows = response.data;
$scope.cols = Object.keys($scope.rows[0]);
},
function error(response){
if (response.status == 404){
$scope.errorMessage = response.data[0];
}
else {
$scope.errorMessage = 'Error displaying result user!';
}
});
}
}
]);
app.service('StoreService',['$http', function ($http,$q) {
this.runQuery = function runQuery(statement){
return $http({
method: 'GET',
url: 'http://localhost:8080/runQuery/',
params: {statement:statement},
headers: 'Accept:application/json'
}).then( function(response){
return reponse.data;
});
}
index.html
<body data-ng-app="app" data-ng-controller="StoreController">
<div class="container">
<form th:action="#{/logout}" method="get">
<button class="btn btn-md btn-danger btn-block"
style="color: #fff; background-color: #e213a2; border-color: #c3c2c0;"
name="registration" type="Submit">Logout</button>
</form>
<div class="panel-group" style="margin-top: 40px">
<div class="panel panel-primary">
<div class="panel-heading">
<span th:utext="${userName}"></span>
</div>
<div>
<form name="queryForm" method="get" data-ng-submit="runQuery()">
<div class="panel-body">
<h3 id="queryLabel">Select Query:</h3>
<textarea id="query" wrap="soft"
placeholder="Please do not enter SELECT with your query, it's added automatically!!" data-ng-model="statement"></textarea>
<button type="submit">Run Query</button>
</div>
</form>
<div class="panel-body" id="results">
<h3 id="queryLabel">Result:</h3>
<table border="1">
<tr>
<th data-ng-repeat="column in cols">{{column}}</th>
</tr>
<tr data-ng-repeat="row in rows">
<td data-ng-repeat="column in cols">{{row[column]}}</td>
</tr>
</table>
</div>
</div>
<div>
<p class="admin-message-text text-center" th:utext="${adminMessage}"></p>
</div>
</div>
</div>
</div>
</body>
The table on the html page, works because I received it from this link
http://jsfiddle.net/v6ruo7mj/1/
But it's not populating the tables with the data received from my backend controller method. I do not have any entities as this is just querying an existing database, so I need not to add any entities.
The issue probably is this line here in the service callback within your controller:
.then (function (data){
$scope.rows = response.data;
// ...
}
try with:
.then (function (data){
$scope.rows = data;
// ...
}
You already return the responses data in your service when calling:
}).then( function(response){
return reponse.data;
});
Aside from your question I should mention that your Spring controller seems to be vunerable to SQL injection. It's in general not a good idea to allow the user to access your database directly. Although I don't know how your StoreService on the backend is implemented. But it seems as if an attacker could easily send a HTTP call to your endpoint and drop your database.
You have a typo in the runQuery function:
app.service('StoreService',['$http', function ($http,$q) {
this.runQuery = function runQuery(statement){
return $http({
method: 'GET',
url: 'http://localhost:8080/runQuery/',
params: {statement:statement},
headers: 'Accept:application/json'
}).then( function(response){
̶r̶e̶t̶u̶r̶n̶ ̶ ̶r̶e̶p̶o̶n̶s̶e̶.̶d̶a̶t̶a̶;̶
return response.data
});
}
}]);

How to check in AngularsJS a unique Database value filled in a form

I have created an application managing contacts. The user can add a contact. After filling the name, I would like to check if the value already exists in the DB.
Can you please help for doing that?
I have created a new field username and I created a directive but I don't know if this way is the best solution. The query is correctly executed. But I improve some difficulties for displaying the results "username exists already" (during the loading it's correctly displayed "checking.....").
Here the file app.js (with the module and the controler "ctrlContacts"):
var app=angular.module('ContactsApp', ['ngRoute', 'ui.bootstrap', 'ngDialog']);
// register the interceptor as a service
app.factory('HttpInterceptor', ['$q', '$rootScope', function($q, $rootScope) {
return {
// On request success
request : function(config) {
// Return the config or wrap it in a promise if blank.
return config || $q.when(config);
},
// On request failure
requestError : function(rejection) {
//console.log(rejection); // Contains the data about the error on the request.
// Return the promise rejection.
return $q.reject(rejection);
},
// On response success
response : function(response) {
//console.log(response); // Contains the data from the response.
// Return the response or promise.
return response || $q.when(response);
},
// On response failure
responseError : function(rejection) {
//console.log(rejection); // Contains the data about the error.
//Check whether the intercept param is set in the config array.
//If the intercept param is missing or set to true, we display a modal containing the error
if (typeof rejection.config.intercept === 'undefined' || rejection.config.intercept)
{
//emitting an event to draw a modal using angular bootstrap
$rootScope.$emit('errorModal', rejection.data);
}
// Return the promise rejection.
return $q.reject(rejection);
}
};
}]);
// MY DIRECTIVE FOR CHECKING IF THE USERNAME IS ALREADY USED
app.directive('usernameAvailable', function($timeout, $q, $http, ContactService) {
return {
restrict: 'AE',
require: 'ngModel',
link: function(scope, elm, attr, ngModel) {
ngModel.$asyncValidators.usernameExists = function() {
return ContactService.searchContactByName('ADAM').success(function(contact){
$timeout(function(){
ngModel.$setValidity('usernameExists', contact);
ngModel.$setValidity('unique', false);
scope.contacts = contact;
alert(contact.length);
}, 1000);
});
};
}
}
});
app.controller('ctrlAddContacts', function ($scope, ContactService){
$scope.title="Add a contact";
ContactService.getCountry().success(function(countries){
$scope.countries = countries;
});
ContactService.loadCategory('undefined',0).success(function(categories){
$scope.categories = categories;
});
$scope.Category = function (contactType) {
if (contactType){
ContactService.loadCategory(contactType,0).success(function(categories){
$scope.categories = categories;
});
}
}
$scope.submitForm = function(contact){
if($scope.ContactForm.$valid){
ContactService.addNewPerson(contact).success(function(Person){
$scope.ContactForm.$setPristine();
$scope.contact= Person;
var personID = Person[0]["ID"];
window.location="#/view-contacts/" + personID;
});
}
}
});
the file for the factories: "appServices.js":
app.factory('ContactService', function($http){
var factory={};
factory.searchContactByName=function(string){
if (string){
chaine='http://myapp/contacts.cfc?method=searchContactByName&contactName=' + string;
}else{
chaine='';
}
//alert(chaine);
return $http.get(chaine);
};
return factory;
})
the file for my view "manageContact.html":
<h3>{{title}}</h3>
<div class="panel panel-default">
<div class="panel-heading">
<div class="panel-title">Person Sheet</div>
</div>
<div class="panel-body">
<form name="ContactForm" class="form-horizontal" role="form" novalidate ng-submit="submitForm(contact)">
<!--------------------- USERNAME FIELD AND CHECK IF IT EXISTS ------------------START-->
<div>
<input type="text"
name="username"
ng-model="username"
username-available
required
ng-model-options="{ updateOn: 'blur' }">
<div ng-if="ContactForm.$pending.usernameExists">checking....</div>
<div ng-if="ContactForm.$error.usernameExists">username exists already</div>
</div>
<!---------------------- USERNAME FIELD AND CHECK IF IT EXISTS --------------------END-->
<div class="form-group">
<label for="txtLastName" class="col-sm-2 control-label">Last Name *</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="txtLastName" maxlength="100" placeholder="Enter Last Name" required ng-model="contact.LASTNAME">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<input type="submit" class="btn btn-primary" value="Submit" ng-disabled="ContactForm.$invalid">
Cancel
</div>
</div>
</form>
</div>
</div>
Thank you in advance for your help.
Regards,
it should be
<div ng-if="ContactForm.$pending.usernameExists">checking....</div>
<div ng-if="ContactForm.username.$error.unique">username exists already</div>
Use ng-show and ng-hide instead of ng-if
<div ng-show="ContactForm.$pending.usernameExists">checking....</div>
<div ng-show="ContactForm.$error.usernameExists">username exists already</div>

User Data is not inserting into mongodb using Node API

I am creating a Restful API on Node.js and storing data into Mongodb. and working on user registration API.
app.js
apiRoutes.post('/signup', function(req, res) {
if (!req.body.name || !req.body.password) {
res.json({success: false, msg: 'Please pass Name and Password.'});
} else {
var newUser = new User({
name:req.body.name,
password:req.body.password
});
console.log(req.body.name);
// save the user
newUser.save(function(err, data) {
if (err) {
return res.json({success: false, msg: 'Username already exists.'});
}else{
console.log(data);
res.json({success: true, msg: 'Successful created new user.'});}
});
}
});
Consuming API using Angular.js
//factory for user register
app.factory('RegistrationFactory', function($resource){
return $resource('/api/signup/:id',{id:'#_id'},{update:{method:'PUT'}});
});
//controller for registration
app.controller('registerCtrl', function($scope, RegistrationFactory, $location){
$scope.regUser=new RegistrationFactory();
$scope.register=function(){
console.log($scope.newUser);
$scope.regUser.$save(function(){
console.log("User Registerd");
});
} ;
})
register.html
<div class="post" ng-controller="registerCtrl">
<form method="post">
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" name="name" ng-model="newUser.name" />
</div>
<div class="form-group">
<label>Password</label>
<input type="text" class="form-control" name="password" ng-model="newUser.password"/>
</div>
<div class="form-group">
<button class="btn btn-success" ng-click="register()">Register</button>
</div>
</form>
</div>
So, My problem is that, this API is working fine on POSTMAN but its not working on my HTML form. Please review my code. Whenever I click on Register button its seems like that on button click API is not hitting. nothing is happening.
Please review my code and suggest me solution.
Thanks.
from angular controller you are not passing the newUser object to $resource or regUser change the controller code to below
//controller for registration
app.controller('registerCtrl', function($scope, RegistrationFactory, $location){
$scope.register=function(){
console.log($scope.newUser);
$scope.regUser=new RegistrationFactory($scope.newUser);
$scope.regUser.$save(function(){
console.log("User Registerd");
});
} ;
})

Angularjs how to upload multipart form data and a file?

I'm a beginner to angular.js but I have a good grasp of the basics.
What I am looking to do is upload a file and some form data as multipart form data. I read that this isn't a feature of angular, however 3rd party libraries can get this done. I've cloned angular-file-upload via git, however I am still unable to post a simple form and a file.
Can someone please provide an example, html and js of how to do this?
First of all
You don't need any special changes in the structure. I mean: html input tags.
<input accept="image/*" name="file" ng-value="fileToUpload"
value="{{fileToUpload}}" file-model="fileToUpload"
set-file-data="fileToUpload = value;"
type="file" id="my_file" />
1.2 create own directive,
.directive("fileModel",function() {
return {
restrict: 'EA',
scope: {
setFileData: "&"
},
link: function(scope, ele, attrs) {
ele.on('change', function() {
scope.$apply(function() {
var val = ele[0].files[0];
scope.setFileData({ value: val });
});
});
}
}
})
In module with $httpProvider add dependency like ( Accept, Content-Type etc) with multipart/form-data. (Suggestion would be, accept response in json format)
For e.g:
$httpProvider.defaults.headers.post['Accept'] = 'application/json, text/javascript';
$httpProvider.defaults.headers.post['Content-Type'] = 'multipart/form-data; charset=utf-8';
Then create separate function in controller to handle form submit call.
like for e.g below code:
In service function handle "responseType" param purposely so that server should not throw "byteerror".
transformRequest, to modify request format with attached identity.
withCredentials : false, for HTTP authentication information.
in controller:
// code this accordingly, so that your file object
// will be picked up in service call below.
fileUpload.uploadFileToUrl(file);
in service:
.service('fileUpload', ['$http', 'ajaxService',
function($http, ajaxService) {
this.uploadFileToUrl = function(data) {
var data = {}; //file object
var fd = new FormData();
fd.append('file', data.file);
$http.post("endpoint server path to whom sending file", fd, {
withCredentials: false,
headers: {
'Content-Type': undefined
},
transformRequest: angular.identity,
params: {
fd
},
responseType: "arraybuffer"
})
.then(function(response) {
var data = response.data;
var status = response.status;
console.log(data);
if (status == 200 || status == 202) //do whatever in success
else // handle error in else if needed
})
.catch(function(error) {
console.log(error.status);
// handle else calls
});
}
}
}])
<script src="//unpkg.com/angular/angular.js"></script>
This is pretty must just a copy of that projects demo page and shows uploading a single file on form submit with upload progress.
(function (angular) {
'use strict';
angular.module('uploadModule', [])
.controller('uploadCtrl', [
'$scope',
'$upload',
function ($scope, $upload) {
$scope.model = {};
$scope.selectedFile = [];
$scope.uploadProgress = 0;
$scope.uploadFile = function () {
var file = $scope.selectedFile[0];
$scope.upload = $upload.upload({
url: 'api/upload',
method: 'POST',
data: angular.toJson($scope.model),
file: file
}).progress(function (evt) {
$scope.uploadProgress = parseInt(100.0 * evt.loaded / evt.total, 10);
}).success(function (data) {
//do something
});
};
$scope.onFileSelect = function ($files) {
$scope.uploadProgress = 0;
$scope.selectedFile = $files;
};
}
])
.directive('progressBar', [
function () {
return {
link: function ($scope, el, attrs) {
$scope.$watch(attrs.progressBar, function (newValue) {
el.css('width', newValue.toString() + '%');
});
}
};
}
]);
}(angular));
HTML
<form ng-submit="uploadFile()">
<div class="row">
<div class="col-md-12">
<input type="text" ng-model="model.fileDescription" />
<input type="number" ng-model="model.rating" />
<input type="checkbox" ng-model="model.isAGoodFile" />
<input type="file" ng-file-select="onFileSelect($files)">
<div class="progress" style="margin-top: 20px;">
<div class="progress-bar" progress-bar="uploadProgress" role="progressbar">
<span ng-bind="uploadProgress"></span>
<span>%</span>
</div>
</div>
<button button type="submit" class="btn btn-default btn-lg">
<i class="fa fa-cloud-upload"></i>
<span>Upload File</span>
</button>
</div>
</div>
</form>
EDIT: Added passing a model up to the server in the file post.
The form data in the input elements would be sent in the data property of the post and be available as normal form values.
It is more efficient to send the files directly.
The base64 encoding of Content-Type: multipart/form-data adds an extra 33% overhead. If the server supports it, it is more efficient to send the files directly:
Doing Multiple $http.post Requests Directly from a FileList
$scope.upload = function(url, fileList) {
var config = {
headers: { 'Content-Type': undefined },
transformResponse: angular.identity
};
var promises = fileList.map(function(file) {
return $http.post(url, file, config);
});
return $q.all(promises);
};
When sending a POST with a File object, it is important to set 'Content-Type': undefined. The XHR send method will then detect the File object and automatically set the content type.
Working Demo of "select-ng-files" Directive that Works with ng-model1
The <input type=file> element does not by default work with the ng-model directive. It needs a custom directive:
angular.module("app",[]);
angular.module("app").directive("selectNgFiles", function() {
return {
require: "ngModel",
link: function postLink(scope,elem,attrs,ngModel) {
elem.on("change", function(e) {
var files = elem[0].files;
ngModel.$setViewValue(files);
})
}
}
});
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app">
<h1>AngularJS Input `type=file` Demo</h1>
<input type="file" select-ng-files ng-model="fileList" multiple>
<h2>Files</h2>
<div ng-repeat="file in fileList">
{{file.name}}
</div>
</body>
You can check out this method for sending image and form data altogether
<div class="form-group ml-5 mt-4" ng-app="myApp" ng-controller="myCtrl">
<label for="image_name">Image Name:</label>
<input type="text" placeholder="Image name" ng-model="fileName" class="form-control" required>
<br>
<br>
<input id="file_src" type="file" accept="image/jpeg" file-input="files" >
<br>
{{file_name}}
<img class="rounded mt-2 mb-2 " id="prvw_img" width="150" height="100" >
<hr>
<button class="btn btn-info" ng-click="uploadFile()">Upload</button>
<br>
<div ng-show = "IsVisible" class="alert alert-info w-100 shadow mt-2" role="alert">
<strong> {{response_msg}} </strong>
</div>
<div class="alert alert-danger " id="filealert"> <strong> File Size should be less than 4 MB </strong></div>
</div>
Angular JS Code
var app = angular.module("myApp", []);
app.directive("fileInput", function($parse){
return{
link: function($scope, element, attrs){
element.on("change", function(event){
var files = event.target.files;
$parse(attrs.fileInput).assign($scope, element[0].files);
$scope.$apply();
});
}
}
});
app.controller("myCtrl", function($scope, $http){
$scope.IsVisible = false;
$scope.uploadFile = function(){
var form_data = new FormData();
angular.forEach($scope.files, function(file){
form_data.append('file', file); //form file
form_data.append('file_Name',$scope.fileName); //form text data
});
$http.post('upload.php', form_data,
{
//'file_Name':$scope.file_name;
transformRequest: angular.identity,
headers: {'Content-Type': undefined,'Process-Data': false}
}).success(function(response){
$scope.IsVisible = $scope.IsVisible = true;
$scope.response_msg=response;
// alert(response);
// $scope.select();
});
}
});

TypeError: this.mRef.auth is not a function

Back again with a new type error. Working on authentication right now. Working with AngularJS and firebase. Right now when I run my function on click of the submit button I get this in my console "TypeError: this.mRef.auth is not a function". I'm thinking it's something simple but here is my login controller:
.controller('Login', ['$scope', 'angularFire',
function($scope, angularFire) {
$scope.signin = function(){
var ref = "https://myappurl.firebaseio.com";
var auth = new FirebaseAuthClient(ref, function(error, user) {
if (user) {
// user authenticated with Firebase
console.log(user);
} else if (error) {
// an error occurred authenticating the user
console.log(error);
} else {
// user is logged out
console.log("hello");
}
});
console.log($scope);
var user = $scope.cred.user;
var pass = $scope.cred.password;
auth.login('password', {
email: user,
password: pass,
rememberMe: false
});
}
}])
Next is the html. I have it inside a controller called login and here is what is in it:
<div class="inner loginbox" ng-controler="Login"
<fieldset>
<label class ="white">Username</label>
<input type="text" id="username" ng-model="cred.user">
<span class="help-block"></span>
<label class ="white">Password</label>
<input type="password" id="password" ng-model="cred.password">
<div class="centerit rem-me">
<label class="checkbox">
<div class="white">Remember me?
<input type="checkbox" ng-model="cred.remember">
</div>
</label>
</div>
<div class="spacer1">
</div>
<a class="btn btn-inverse btn-large btn-width" id="signupsubmit" ng-click="signin()">Sign in</a>
</fieldset>
</div>
The type error I get refers to firebase-auth-client.js on line 79. In chrome I have this in the console: Uncaught TypeError: Object https://kingpinapp.firebaseio.com has no method 'auth'
When instantiating the FirebaseAuthClient, you should pass an actual Firebase reference, not just the string representation of one.
Updating your code to use the following snippet should fix your problem:
var ref = new Firebase("https://myappurl.firebaseio.com");
var auth = new FirebaseAuthClient(ref, function(error, user) {

Categories