Pass an array as a query string in AngularJS? - angularjs

I have a form with firstname, lastName, zipcode..etc, in addition to multi value input, in which the user check many checkboxes (which will be an array).
I wanna submit this form using angular js $http, and pass them as a query string, currently I have it like this:
firstName=test&lastName=test&homeZip=44551&carInterested=honda%2Cford%2Ctoyota
but my requirement is to be like this:
firstName=test&lastName=test&homeZip=44551&carInterested=honda&carInterested=ford&carInterested=toyota
here is my code:
$scope.signUp = function() {
$scope.formData.carInterested= $scope.selection
console.log ($scope.formData);
$http({
method : 'POST',
url : '/sonmeUr/../',
transformRequest: transformRequestAsFormPost,
data : $scope.formData
})
.success(function(data) {
console.log(data);
});
}
and in my service I have this:
.factory( "transformRequestAsFormPost", function() {
function transformRequest( data, getHeaders ) {
var headers = getHeaders();
headers[ "Content-type" ] = "application/x-www-form-urlencoded; charset=utf-8";
return( serializeData( data ) );
}
return( transformRequest );
function serializeData( data ) {
if ( ! angular.isObject( data ) ) {
return( ( data == null ) ? "" : data.toString() );
}
var buffer = [];
for ( var model in data ) {
if ( ! data.hasOwnProperty( model ) ) {
continue;
}
var value = data[ model ];
buffer.push(
encodeURIComponent( model ) +
"=" +
encodeURIComponent( ( value == null ) ? "" : value )
);
}
var source = buffer
.join( "&" )
.replace( /%20/g, "+" )
;
return( source );
}
}
);

Related

Error displaying data - scope - AngularJS

I have a problem with displaying data using AngularJS.
So my application is based on AngularJS and CodeIgniter 3.
I've created a validation in CodeIgniter written in the form, everything works.
public function create()
{
$this->form_validation->set_error_delimiters('','');
$this->form_validation->set_rules( 'login' , 'Imię' , 'required|min_length[3]' );
$this->form_validation->set_rules( 'email' , 'Email' , 'required|valid_email|is_unique[users.email]' );
$this->form_validation->set_rules( 'password' , 'Hasło' , 'required|matches[passconf]' );
$this->form_validation->set_rules( 'passconf' , 'Powtórz hasło' , 'required|matches[password]' );
if ( $this->form_validation->run())
{
$user = $this->input->post('user');
unset($user['passconf']);
$user['password'] = crypt($user['password'], config_item('encryption_key'));
$this->Users_model->create($user);
}
else
{
$errors['login'] = form_error( 'login' );
$errors['email'] = form_error( 'email' );
$errors['password'] = form_error( 'password' );
$errors['passconf'] = form_error( 'passconf' );
echo '{"records":' . json_encode( $errors ) . '}';
}
}
On the AngularJS side, I wanted errory to appear.
controllersAdmin.controller('userCreate', function( $scope, $http, $timeout ){
$scope.user = {};
$scope.user.role = 'user';
$scope.createUser = function( user ){
$http({
method: 'POST', url: 'api/admin/users/create/' ,
data: {
user : user,
login : user.login,
email : user.email,
password : user.password,
passconf : user.passconf
}}
).then(function ( errors ){
if ( errors )
{
$scope.errors = errors;
}
else
{
$scope.success = true;
$timeout(function(){
$scope.success = false;
$scope.user = {};
} , 3000 );
}
},function (error){
console.log('Blad we wczytywaniu danych');
});
}
});
I created $scope.errors = errors;
When I display it with {{errors}} - data is displayed.
{"data":{"records":{"login":"Pole Imię jest wymagane.","email":"Pole Email jest wymagane.","password":"Pole Hasło jest wymagane.","passconf":"Pole Powtórz hasło jest wymagane."}},"status":200,"config":{"method":"POST","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":"callback","url":"api/admin/users/create/","data":{"user":{"role":"user"}},"headers":{"Accept":"application/json, text/plain, */*","Content-Type":"application/json;charset=utf-8"}},"statusText":"OK","xhrStatus":"complete"}
However, when I give {{errors.login}}, the data is not displayed. Can I count on little help?
There's your problem. Login is not a property of the errors object but a sub property. It should be errors.data.records.login.

How to wait for multiple requests based on _.each iteration in angular using $resource

Hi I have a method that does multiple request based on _.each iteration. What I want to do is initialize vm.job = job in the getAllJobSublinesByJobline after the _.each iteration
var vm = this;
function getAllJobSublinesByJobline () {
return $resource( '/api/joblines/get_all_jobsublines_by_jobline/:pageLimit', {
'jobLineId' : '#jobLineId',
'page' : '#page',
'search' : '#search',
'sortField' : '#sortField',
'sortType' : '#sortType'
} );
}
function getJobsublinesByJoblineId ( joblines, job ) {
_.each( joblines, function ( jobline ) {
if ( parseInt( jobline.num_sublines ) ) {
var jobsublineFetchDetails = {
'pageLimit' : 10,
'jobLineId' : jobline.id
};
return getAllJobSublinesByJobline().save( jobsublineFetchDetails ).$promise.then( function ( jobsubline ) {
jobline.jobsublines = jobsubline.data;
job.joblines.push( jobline );
} );
}
job.joblines.push( jobline );
} );
vm.job = job; // initializes right away even though _.each iteration is not finished yet
}
My problem is that it initializes right away even though the _.each iteration has not finished fetching data yet. Why is this happening?
From the Docs:
It is important to realize that invoking a $resource object method immediately returns an empty reference (object or array depending on isArray). Once the data is returned from the server the existing reference is populated with the actual data.
-- AngularJS $resource API Reference
So as said in another answer, push promises, and use $q.all.
function getJobsublinesByJoblineId ( joblines, job ) {
var promises = [];
_.each( joblines, function ( jobline ) {
if ( parseInt( jobline.num_sublines ) ) {
var jobParams = {
'pageLimit' : 10,
'jobLineId' : jobline.id
};
var details = getAllJobSublinesByJobline().save( jobParams );
promises.push(details.$promise);
}
} );
$q.all(promises).then (function (detailsArray) {
//assemble job object
vm.job = job;
});
}
You could probably push all promises to an array and use something like
$q.all(yourPromises).then(function(allCompletedResponse){...}).
Since I needed to initialize the jobline on having the jobsubline what I did with mine was similar to the answer above.
function getJobsublinesByJoblineId ( joblines, job ) {
var promises = _.map( joblines, function ( jobline ) {
var jobParams = {
'jobLineId' : jobline.id
};
var deferred = $q.defer();
apiService.getAllJobSublinesByJobline().save( jobParams ).$promise.then( function ( jobsubline ) {
jobline.jobsublines = jobsubline.data;
deferred.resolve( jobline );
} );
return deferred.promise;
} );
$q.all( promises ).then( function ( joblines ) {
job.joblines = joblines
vm.job = job;
} );
}

NgTable using API and groupBy with a global filter

I'm having difficulty with NgTable, however the functionality I'm looking for may be a limitation on the table framework.
I'm using an API call within the getData, and the data is being grouped (via the groupBy property in the settings param).
I want to be able to use a global filter on the data, I can't seem to get it work with grouping. There's two examples, except they don't mix:
Grouping: http://ng-table.com/#/grouping/demo-grouping-basic
Global filtering: http://ng-table.com/#/filtering/demo-api
Any suggestions?
Table declaration/config
$scope.tableNotesParams = new ngTableParams({
page: 1, // show first page
count: 10, // count per page: use total result set in this case,
sorting: {
created_at: 'desc'
}
}, {
groupBy: function( note ) {
return moment( note.created_at ).format( 'YYYY' );
},
getData: function ( $defer, params ) {
$scope.request.notes.state = 'started';
$scope.request.notes.notesSpinner = true;
var offset = params.count() * ( params.page() - 1 );
// Default
var urlQueryParams = {
'email': member.accounts.email,
'offset': offset,
'limit': params.count() || 10
};
notesApiService.getNotes( urlQueryParams ).then( function ( results ) {
$scope.notes = results.data;
$scope.noteMembers = extractionService.getAllUniqueMembers( $scope.notes );
// Get the range values, expecting value to be: items 1-10/655
var noteHeaders = results.headers();
var notesRangeValues = noteHeaders['content-range'].match( /(\d{1,})/g );
$scope.tableNotesMetaData = {
offsetStart: notesRangeValues[0] || 0,
offsetEnd : notesRangeValues[1] || 0,
totalCount : notesRangeValues[2] || 0
};
// Update parent controller count
$scope.tabs.notes.count = notesRangeValues[2] || 0;
// Update the total
params.total( $scope.tableNotesMetaData.totalCount );
var orderedData = params.sorting() ?
$filter('orderBy')($scope.notes, params.orderBy()) :
$scope.notes;
$defer.resolve( orderedData );
$scope.request.notes.state = 'completed';
$scope.request.notes.notesSpinner = false;
});
}
});
Edit:
The filtering example for a global filter doesn't do anything to the grouped data:
function applyGlobalSearch(){
var term = self.globalSearchTerm;
if (self.isInvertedSearch){
term = "!" + term;
}
self.tableParams.filter({ $: term });
}
I don't think it's performant to query your notesApiService.getNotes() in the getData()-function, but whatever. Since we don't have the HTML or a JSBin to work with, it's mostly guestimate:
notesApiService.getNotes( urlQueryParams ).then( function ( results ) {
var term = $scope.globalSearchTerm.toLowerCase();
if (term.length == 0) {
$scope.notes = angular.copy(results.data, []);
} else if (term.length > 1) {
$scope.notes = results.data.filter(function(item) {
var val = JSON.stringify(item).toLowerCase();
return (val.indexOf(term) != -1);
});
}

How to get prevent multiple promises from different functions

In my angular-app, I have 3 queries, each depends on the others. I am putting promise() to each of them. In this case how can i get $q.all for all this depended promise once done?
Can anyone clarify this for me, please?
Here is my code :
"use strict";
angular.module("tcpApp")
.controller("projectSummaryController",
['$scope', '$routeParams', '$location', 'server', 'modalService', '$q',
function ( $scope, $routeParams, $location, server, modalService, $q ) {
$scope.projectId = $routeParams.projectId;
$scope.subProjectId = $routeParams.subProjectId;
$scope.phaseId = 0;
$scope.disciplineId = 0;
$scope.contractorId = 0;
$scope.queryConractorInfo = function ( contractorId ) {
server.contractorInfo.get({
projectId:$scope.projectId,
subProjectId : $scope.subProjectId,
contractId : $scope.contractorId,
disciplineId : $scope.disciplineId,
staticId : 0 /* at present static */
}).$promise.then(function ( contractorInfo ) {
$scope.contractorInfo = contractorInfo;
})
}
$scope.queryConractorList = function ( phaseId, disciplineId ) {
var base = 'http://azvsptcsdev02:678/_vti_bin/CPMD.WEBSERVICE/ProjectInfoService.svc/Contracts/'
console.log( base+$scope.projectId+'/'+$scope.subProjectId+'/'+phaseId+'/'+disciplineId );
server.contractorsList.query(
{
projectId:$scope.projectId,
subProjectId : $scope.subProjectId,
phaseId : phaseId,
disciplineId: disciplineId
}).$promise.then(function ( contractorsList ) {
$scope.contractorId = contractorsList[0].Id; //setting the first contractor as default;
$scope.queryConractorInfo( $scope.contractorId );
});
}
$scope.queryProject = function ( prjId, subPrjId ) {
server.projectSummary.get({id:$scope.projectId})
.$promise.then(function (data) {
//only setting phase id and desciple id to get list of contractors
$scope.phaseId = data.PhaseIds[0].Id; //setting the first phase as default;
$scope.disciplineId = data.DisciplineIds[0].Id; //setting the first descipline as default;
$scope.queryConractorList( $scope.phaseId, $scope.disciplineId );
});
}
if($scope.projectId) {
$scope.queryProject();
}
$q.all([ $scope.queryProject, $scope.queryConractorList, $scope.queryConractorInfo ])
.then(function ( data1, data2, data3 ) {
console.log( data1, data2, data3 );// i get nothing here!
})
}]);
What is the best practice to handle this?

JQuery Ajax inside a loop

I'm trying to execute an Ajax function in a loop and I want that my loop go to next instruction only when the ajax call finishes. I've tried to put the ajax async to false, but my loading message didn't appear and my screen refreshs when all iterations of the loop finish. If async is set to true it executes all together at the same time.
Here's my code:
function pingAll( url )
{
var arrIDs = new Array();
var pattern = /[0-9]+/g;
$("input:checkbox[name=checkbox-router]:checked").each(function()
{
var strCheckboxID = $(this).attr( 'id' );
var routerID = strCheckboxID.match( pattern );
arrIDs.push( routerID );
});
for (var i in arrIDs)
{
pingRouter(url + arrIDs[i], arrIDs[i]);
}
}
function pingRouter( url, shortID )
{
$( '#ping-resp-' + shortID ).html( 'Loading...' );
var pingRequestTimeout = $( '#pingRequestTimeout' ).val();
url = url + "?timeout=" + pingRequestTimeout;
$.ajax
({
url: url,
async: true,
success: function( data )
{
var objData = $.parseJSON( data );
var response = objData.response.replace(/(\r\n|\n|\r)/gm,"")
.
.
.
var latency = parseFloat( objData.latency );
$( '#ping-resp-' + shortID ).html( latency + ' ms' );
}
});
return;
}
Thanks for your help.
You could use recursion as follows:
function pingRouter(baseurl, arrIDs , i) {
if( i < 0 || i > arrIDs.length - 1) {
return;
}
var url = baseurl + arrIDs[i];
var shortID = arrIDs[i];
$( '#ping-resp-' + shortID ).html( 'Loading...' );
var pingRequestTimeout = $( '#pingRequestTimeout' ).val();
url = url + "?timeout=" + pingRequestTimeout;
$.ajax
({
url: url,
async: true,
success: function( data )
{
var objData = $.parseJSON( data );
var response = objData.response.replace(/(\r\n|\n|\r)/gm,"")
.
.
.
var latency = parseFloat( objData.latency );
$( '#ping-resp-' + shortID ).html( latency + ' ms' );
}
}).always(function() {
if(i < arrIDs.length + 1) {
pingRouter(baseurl, arrIDs , i + 1);
}
});
return;
}
And change your calling function to:
pingRouter(url, arrIDs, 0);
See API for always.

Resources