Trouble in authorization with post request in Angular - javascript

I have a some problem with authorization in my app. I realize it through factory and controller, post method send request, but in response i have log from server, that values are wrong.
But if I change body of doLogin function to jQuery ajax method and don't use factory, all is OK. What is wrong with my Angular way?
My AngularJS Code
Form:
<form ng-submit="doLogin(credentials)">
<div class="list">
<label class="item item-input">
<span class="input-label">Username</span>
<input type="text" ng-model="credentials.email">
</label>
<label class="item item-input">
<span class="input-label">Password</span>
<input type="password" ng-model="credentials.password">
</label>
<label class="item">
<button class="button button-block button-positive" type="submit">Log in</button>
</label>
</div>
</form>
Factory:
.factory('Somepost', function ($http) {
return{
doPost: function (credentials, callback) {
console.log('service');
console.log(credentials);
return $http({
url:'http://cronicls.ru/auth/login',
method: 'POST',
data: credentials,
async : true
}).success(callback);
}}})
Login function in controller:
$scope.doLogin = function(credentials) {
var successCallback = function (data) {
console.log(data);
}
Somepost.doPost(credentials, function(data) {
console.log(data);
});
};
Function doLogin with $.ajax (working successfully):
$scope.doLogin = function(credentials) {
var successCallback = function (data) {
console.log(data);
}
var login = function(credentials, successCallback) {
$.ajax({
type: "POST",
url: 'http://cronicls.ru/auth/login',
async : true,
data: credentials,
success: function(data){
console.log('login success');
console.log(data);
successCallback();
},
error: function(data){
console.log('/auth/login: error');
console.log(data);
}
});
};
login(credentials, successCallback);
};

but in response i have log from server, that values are wrong.
Actually not, because it returns a promise and you have to do something like this in your callback:
As per your comment :
It's PHP with ZF on server side. Actually you need to change the default content Type header from application/json to application/x-www-form-urlencoded
Change in factory:
.factory('Somepost', function ($http) {
return{
doPost: function (credentials, callback) {
console.log('service');
console.log(credentials);
return $http({
url:'http://cronicls.ru/auth/login',
method: 'POST',
data: credentials,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}, // <-- override the default contentType header
async : true
}).then(callback); // change to then instead of success
}}})

I found the answer of my problem. Thanks to #Jai for hint about ZF. Actually we need to wrap data in $.param(). So, working factory is:
.factory('Somepost', function ($http) {
return{
doPost: function (credentials, callback) {
return $http({
url:'http://cronicls.ru/auth/login',
method: 'POST',
data: $.param(credentials),
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).then(callback);
}
}
})

Related

How to bind value with $scope to view with ng-model from controller that define in state ui-router?

I used mechanism for transferring state ui-router. With state "inputcontract" that I have defined, when processed (http://cem.survey.local/#/inputcontract/SGD621262), it will pass parameter "sohd" to function "$scope.getSurveyContent($scope,sohd)" in controller "accountController" , this function will send the request to the server to retrieve data returns in json structures. The problem is that I cannot bind value to view by using $scope with json return "$scope.account =response.data_cusinfo[0]", if bind successfully it will appear dynamic on view HTML. How can i do that? Thank you very much.
Here is app.js
var app = angular.module('outbound', ['ngMaterial', 'ui.router'])
.constant('API_URL', 'http://cem.survey.local/');
app.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('inputcontract', {
url: "/inputcontract/:sohd",
controller: 'accountController'
})
})
Here is accountController.js
app.controller('accountController', function ($scope, $http,$templateRequest, $sce, $compile, $mdDialog, $mdSidenav, $mdMedia, API_URL, $stateParams) {
if (typeof $stateParams.sohd === 'undefined') {
return;
}
$scope.account = {};
var sohd=$stateParams.sohd;
$scope.getSurveyContent= function($scope,sohd)
{ var url = API_URL + "account/search";
$http({
method: 'POST',
url: url,
data: {sohd: sohd},
headers: {'Content-Type': 'application/json'}
}).success(function (response) {
$scope.account =response.data_cusinfo[0];
}).error(function (response) {
});
}
//Send Request to server with sohd
$scope.getSurveyContent($scope,sohd);
Here is the view
<html lang="en-US" ng-app="outbound">
...
<div ng-controller="accountController">
...
<td style="width: 150px">Khách hàng
<div class="form-group">
<input class="form-control" id="inputdefault" type="text"
ng-model="account.CustomerName" >
</div></td>
<td>CMND
<div class="form-group">
<input class="form-control" id="inputdefault" type="text"
ng-model="account.Passport" >
</div>
</td>
<td>Ngày tháng năm sinh
<div class="form-group">
<input class="form-control" id="inputdefault" type="text"
ng-model="account.Birthday">
</div></td>
...
</div>
...
</html>
Assuming the $http post is successful, you don't need to pass $scope on your getSurveyContent function. Also, success and error are deprecated - you should use then. Try this:
$scope.getSurveyContent = function(sohd) {
var url = API_URL + "account/search";
$http({
method: 'POST',
url: url,
data: {sohd: sohd},
headers: {'Content-Type': 'application/json'}
}).then(
function successCallback (response) {
$scope.account = response.data.data_cusinfo[0];
},
function errorCallback (response) {
}
);
}
//Send Request to server with sohd
$scope.getSurveyContent(sohd);

How do I send a GET request while typing in AngularJS?

I'm new to AngularJS.
I want to set it up so that as I type, I send a GET request, but only if what I've typed in the input field is at least three characters long.
Here's index.html:
<html ng-app="myApp">
<div ng-controller="fetchTagsCtrl">
<input type="text" ng-model="userInput.fetchTag" placeholder="Type something">
</div>
</html>
My Javascript:
var app = angular.module('myApp',[]);
app.controller('fetchTagsCtrl',function($scope){
$scope.userInput = {
fetchTag: ''
};
$http({
url: '/myURL',
method: 'GET',
param: {
someParameter: $scope.userInput
}
}).success(function(response){
console.log(response);
})
});
But this doesn't seem to work. How do I fix this?
You must use keyup event for that.
<input type="text" ng-model="userInput.fetchTag" ng-keyup="fetchdata()" placeholder="Type something">
In your controller:
$scope.fetchdata = function() {
// condition to check for characters greater than 3.
if($scope.userInput.fetchTag.length < 4) return;
$http({
url: '/myURL',
method: 'GET',
params : {
someParameter: $scope.userInput
}
}).success(function(response){
console.log(response);
});
}
Also inject $http in your controller.
Your html dom was right. Just simply change would be on your script. Follow the step which provided below
Step 1:
Inject $http to your controller
Ex: app.controller('fetchTagsCtrl',function($scope,$http)
Step 2:
Use $scope.$watch to get your typing event from your input
Let's look at the code below will be look like
var app = angular.module('myApp',[]);
app.controller('fetchTagsCtrl',function($scope,$http){
$scope.userInput = {
fetchTag: ''
};
$scope.$watch('userInput.fetchTag',function(){
$http({
url: '/myURL',
method: 'GET',
param: {
someParameter: $scope.userInput
}
}).success(function(response){
console.log(response);
})
});
});
You can use ng-change directive instead of ng-keyup .because for every change in input it calls to the fetchdata method in controller.
<input type="text" ng-model="userInput.fetchTag" ng-change="fetchdata(userInput.fetchTag)" placeholder="Type something">
$scope.fetchdata = function() {
// condition to check for characters greater than 3.
if($scope.userInput.fetchTag.length > 3)
$http({
url: '/myURL',
method: 'GET',
params : {
someParameter: $scope.userInput
}
}).success(function(response){
console.log(response);
});
}
Watch the model for changes, do a check, then fire your request. Here's how I'd write it:
app.controller('fetchTagsCtrl',function($scope){
$scope.userInput = {
fetchTag: ''
};;
$scope.$watch('userInput.fetchTag',function(value){
if(value.length >= 3){
makeRequest();
}
});
function makeRequest(){
$http({
url: '/myURL',
method: 'GET',
param: {
someParameter: $scope.userInput.fetchTag
}
}).success(function(response){
console.log(response);
})
}
});

Receiving a 404 error even though page exists while trying to POST with AngularJS

POST http://api.link/api/v1/articlerevision 404 (NOT FOUND)
I get the following error when I try to add a new item through AngularJS and Django-Tastypie API. If I open the link in browser, it works, bet when I submit the form, it doesn't. I have set allowed_methods to get, put, post, delete and that doesn't seem to solve anything. What other options could there be?
EDIT:
view.tpl.html
<div ng-controller="CreateCtrl">
<form class="form-horizontal">
<fieldset>
<label>
Title
<input class="form-control" type="text" ng-model="revision.title" placeholder="Title">
</label>
<br />
<label>
Description
<textarea class="form-control" type="text" ng-model="revision.content"></textarea>
</label>
<button ng-click="create()">Save</button>
</fieldset>
</form>
</div>
Angular
var tastypieDataTransformer = function ($http) {
return $http.defaults.transformResponse.concat([
function (data, headersGetter) {
var result = data.objects;
result.meta = data.meta;
return result;
}
]);
};
bosApp.factory('Revision', function($resource, $http) {
return $resource('http://api.link/api/v1/articlerevision/:id/', {
id: '#is'
},
{
update: {
method: 'POST',
params: {"update": true},
isArray: false
},
save: {
method: 'PUT'
},
query: {
method: 'GET',
isArray: true,
transformResponse: tastypieDataTransformer($http)
},
create: {
method: 'POST'
}
}
);
});
var CreateCtrl = function($scope, $location, Revision) {
$scope.create = function() {
Revision.create($scope.revision);
};
};

Angular.js accessing model from controller (server validation)

i now trying to migrate my legace app to Angular and now stuck with following issue.
I have this simple form:
<form name="loginForm" ng-controller="LoginCtrl" ng-submit="doLogin()">
<input type="text" name="login" ng-model="login.login" />
<span class="errors" ng-show="loginForm.login.$error.required">Required</span>
<span class="errors" ng-show="loginForm.login.$error.bad_login">Login or pass incorrect</span>
<input type="password" ng-model="login.pass"/>
</form>
Server returns error as this type of JSON: { login: 'bad_login', pass: 'incorrect' }
And in controller:
function LoginCtrl($scope, $http) {
$scope.doLogin = function() {
var model = $scope.login;
var req = { "login": model.login, "pass": model.pass };
$http({ method: "POST", url: "/login", data: req }).success(function (resp) {
if(resp.status != "ok") {
angular.forEach(resp, function (value, key) {
// ex: model['login'].$setValidity('bad_login', false);
model[key].$setValidity(value, false);
});
}
});
};
}
I try to mark each field in loop, not to hardcode every field by hand. but this approach not working. I get this error: TypeError: Cannot call method '$setValidity' of undefined, even when field is left empty i have another error: TypeError: Cannot read property 'login' of undefined
So i think i need to get instance of model for every field in form, any ideas ?
The reason it's coming back undefined is because unless you actually specify something for $scope.login.login or $scope.login.pass to begin with, they aren't set. If you put a space and delete it, you'll see they are set as blank. What you're going to want to do is at the beginning of your controller define the login on the scope like so:
function LoginCtrl($scope, $http) {
$scope.login = {
login: "",
pass: ""
};
$scope.doLogin = function() {
var req = { "login": $scope.login.login, "pass": $scope.login.pass };
$http({ method: "POST", url: "/login", data: req }).success(function (resp) {
if(resp.status != "ok") {
angular.forEach(resp, function (value, key) {
// ex: model['login'].$setValidity('bad_login', false);
$scope.login[key].$setValidity(value, false);
});
}
});
};
}

AngularJS passing data to $http.get request

I have a function which does a http POST request. The code is specified below. This works fine.
$http({
url: user.update_path,
method: "POST",
data: {user_id: user.id, draft: true}
});
I have another function for http GET and I want to send data to that request. But I don't have that option in get.
$http({
url: user.details_path,
method: "GET",
data: {user_id: user.id}
});
The syntax for http.get is
get(url, config)
An HTTP GET request can't contain data to be posted to the server. However, you can add a query string to the request.
angular.http provides an option for it called params.
$http({
url: user.details_path,
method: "GET",
params: {user_id: user.id}
});
See: http://docs.angularjs.org/api/ng.$http#get and https://docs.angularjs.org/api/ng/service/$http#usage (shows the params param)
You can pass params directly to $http.get() The following works fine
$http.get(user.details_path, {
params: { user_id: user.id }
});
Starting from AngularJS v1.4.8, you can use
get(url, config) as follows:
var data = {
user_id:user.id
};
var config = {
params: data,
headers : {'Accept' : 'application/json'}
};
$http.get(user.details_path, config).then(function(response) {
// process response here..
}, function(response) {
});
Solution for those who are interested in sending params and headers in GET request
$http.get('https://www.your-website.com/api/users.json', {
params: {page: 1, limit: 100, sort: 'name', direction: 'desc'},
headers: {'Authorization': 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=='}
}
)
.then(function(response) {
// Request completed successfully
}, function(x) {
// Request error
});
Complete service example will look like this
var mainApp = angular.module("mainApp", []);
mainApp.service('UserService', function($http, $q){
this.getUsers = function(page = 1, limit = 100, sort = 'id', direction = 'desc') {
var dfrd = $q.defer();
$http.get('https://www.your-website.com/api/users.json',
{
params:{page: page, limit: limit, sort: sort, direction: direction},
headers: {Authorization: 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=='}
}
)
.then(function(response) {
if ( response.data.success == true ) {
} else {
}
}, function(x) {
dfrd.reject(true);
});
return dfrd.promise;
}
});
You can even simply add the parameters to the end of the url:
$http.get('path/to/script.php?param=hello').success(function(data) {
alert(data);
});
Paired with script.php:
<? var_dump($_GET); ?>
Resulting in the following javascript alert:
array(1) {
["param"]=>
string(4) "hello"
}
Here's a complete example of an HTTP GET request with parameters using angular.js in ASP.NET MVC:
CONTROLLER:
public class AngularController : Controller
{
public JsonResult GetFullName(string name, string surname)
{
System.Diagnostics.Debugger.Break();
return Json(new { fullName = String.Format("{0} {1}",name,surname) }, JsonRequestBehavior.AllowGet);
}
}
VIEW:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script type="text/javascript">
var myApp = angular.module("app", []);
myApp.controller('controller', function ($scope, $http) {
$scope.GetFullName = function (employee) {
//The url is as follows - ControllerName/ActionName?name=nameValue&surname=surnameValue
$http.get("/Angular/GetFullName?name=" + $scope.name + "&surname=" + $scope.surname).
success(function (data, status, headers, config) {
alert('Your full name is - ' + data.fullName);
}).
error(function (data, status, headers, config) {
alert("An error occurred during the AJAX request");
});
}
});
</script>
<div ng-app="app" ng-controller="controller">
<input type="text" ng-model="name" />
<input type="text" ng-model="surname" />
<input type="button" ng-click="GetFullName()" value="Get Full Name" />
</div>
For sending get request with parameter i use
$http.get('urlPartOne\\'+parameter+'\\urlPartTwo')
By this you can use your own url string

Categories