Typeahead search function - angularjs

So I am using the typeahead directive that's part of Angular UI project. I have a function that calls a factory (using $resource to call an api). The first function didn't work but the second one did. What's happening differently here? I assumed these would produce the exact same result but apparently I am wrong:
// this didn't work, it doesn't display a list of items in typeahead, no errors.
$scope.getLocation = function(val) {
return LocationService.search({ term: val }, function (res) {
return res.data.map(function (item) {
return item;
});
});
};
// this worked
$scope.getLocation = function(val) {
return LocationService.search({ term: val }).$promise.then(function (res){
return res.data.map(function (item) {
return item;
});
});
};

Do you have $resource wrapped in LocationService? Something like:
function LocationService($resource) {
return {
search : function(query){
var locationResource = $resource('url/',
{},
{
search : {
method: 'POST',
responseType : 'json'
}
});
return locationResource.search({ q : query });
}
};
}
If so, in your first example, you're just passing a callback as second variable to LocationService, which isn't handled in the function definition. The returned function of $resource can take a callback as a second parameter, but not if you've wrapped it. If you wanted, you could pass the callback to the service itself, like:
function LocationService($resource) {
return {
search : function(query, cb){
var locationResource = $resource('url/',
{},
{
search : {
method: 'POST',
responseType : 'json'
}
});
return locationResource.search({ q : query }, cb);
}
};
}

Related

Empty var in second service function

I have a service:
.service('VacanciesService', function($http) {
var vacancies = [];
var usedVacancies = [];
return {
getVacanciesForUniversity: function(university_id) {
return $http.get("http://jobs.app/api/vacancies/" + university_id).then(function(response){
vacancies = response.data.vcancies;
return vacancies;
}, function(error){
return error;
});
},
getRandomVacancy: function() {
console.log(vacancies);
}
}
})
This is the calling controller
.controller('jobsCtrl', function($ionicLoading, locker, UniversitiesService, VacanciesService) {
var vm = this;
user = locker.get('userDetails');
UniversitiesService.getUniversity(user.university.id).then(function(university) {
vm.university = university.university;
});
VacanciesService.getVacanciesForUniversity(user.university.id).then(function(vacancies) {
vm.vacancies = vacancies;
}, function error(error) {
});
vm.addCard = function(name) {
newVacancy = VacanciesService.getRandomVacancy();
};
vm.addCard();
})
And I can't figure out why the vacancies variable in in the console.log is empty in the second function? I assumed as it was set in the initial function (called prior) that it should be populated?
TIA!
if you call getVacanciesForUniversity getRandomVacancy like below, you will get empty array
VacanciesService.getVacanciesForUniversity(uniId)
VacanciesService.getRandomVacancy() //you will get empty
you must getRandomVacancy inside getVacanciesForUniversity returned promise
VacanciesService.getVacanciesForUniversity(uniId).then(function(){
VacanciesService.getRandomVacancy()
})
alo you misstype response.data.vcancies; instead response.data.vacancies;
The answer is READ YOUR CODE PROPERLY.
There was a glaringly obvious typo in my code that I missed from staring at it too long.
Big thanks to Daniel Dawes and aseferov for attempting to help!
In your service :
getVacanciesForUniversity: function(university_id) {
return $http.get("http://jobs.app/api/vacancies/" + university_id);
}
In your controller :
$scope.getVacancies = function () {
your_service.getVacanciesForUniversity().then(
function(response) {
if (response.status = 200) {
$scope.vacancies = response.data.vacancies;
}, function errorCallback (response) {
...
}
);
};
$scope.getVacancies(); // you call one time your function here
$scope.getRandomVacancy : function() {
console.log($scope.vacancies);
};

Http request in constructor doesn't change attribute value

I've got a problem with this constructor:
function ApiManager() {
this.api= new ApiInterface();
this.apiVersion = -1;
this.api.getVersion()
.then(function(version) {
console.log(version); // "1.0"
this.apiVersion = version;
console.log(this.apiVersion); // "1.0"
}, function(error) {
console.log("Couldn't find API version.")
});
}
ApiManager.prototype = {
getApiVersion: function() {
return this.apiVersion; // "-1"
}
};
I have an object with the attribute apiVersion, which is initialized with the value -1. After that an HTTP request is executed by the ApiInterface and assigns apiVersion the value 1.0. Later I call the function getApiVersion and it returns the old value -1.
I'm new to AngularJS and probably it's a silly rookie mistake, but I don't see what I've got wrong.
This is what the Promises/A+ Spec says about the this keyword inside .then functions:
That is, in strict mode this will be undefined inside of them; in sloppy mode, it will be the global object.
-- Promises/A+ Spec -- Note 3.2
So in your code, you need to explicitly bind instead of using the this keyword.
function ApiManager() {
this.api= new ApiInterface();
this.apiVersion = -1;
//bind 'this' keyword to a var
var vm = this;
this.api.getVersion()
.then(function(version) {
console.log(version); // "1.0"
//use that binding
vm.apiVersion = version;
console.log(vm.apiVersion); // "1.0"
}, function(error) {
console.log("Couldn't find API version.")
});
}
I also tried the version with the promise and this is the result:
function ApiManager() {
this.api= new ApiInterface();
this.apiVersion = api.getVersion();
}
ApiManager.prototype = {
getApiVersion: function() {
return this.apiVersion;
}
};
The ApiInterface returns a promise in the getVersion method.
getVersion: function() {
return $http({
method: 'GET',
url: myUrl;
}).then(function successCallback(response) {
return response.data.jsonapi.version;
}, function errorCallback(response) {
return $q.reject(response.data);
});
},
Later on, I use it this way in my controller:
$scope.printApiVersion = function () {
var promise = manager.getApiVersion();
promise.then(function(version) {
console.log(version);
}, function(error) {
console.log("Couldn't retrieve API version.")
});
}
This works great for me, but I don't know if it is considered good style.

Restangular - Specific Function to Specific Factory

I'm working with restangular and so far, everything works very well, but, i have this issue that cannot resolve.
I define a abstract repository with the basic operations like this:
app.factory('AbstractRepository', [
function(){
function AbstractRepository(restangular, route) {
this.restangular = restangular;
this.route = route;
};
AbstractRepository.prototype = {
getList: function (params) {
return this.restangular.all(this.route).getList(params).$object;
},
get: function (id) {
return this.restangular.one(this.route, id).get();
},
getView: function (id) {
return this.restangular.one(this.route, id).one(this.route + 'view').get();
},
update: function (updatedResource) {
return updatedResource.put().$object;
},
create: function (newResource) {
return this.restangular.all(this.route).post(newResource);
},
remove: function (object) {
return this.restangular.one(this.route, object.id).remove();
},
};
AbstractRepository.extend = function (repository) {
repository.prototype = Object.create(AbstractRepository.prototype);
repository.prototype.constructor = repository;
}
return AbstractRepository;
}
]);
And the specific respository:
app.factory('ServiceRepository', ['Restangular', 'AbstractRepository',
function (restangular, AbstractRepository) {
function ServiceRepository() {
//restangular.setBaseUrl("http://192.168.0.144:8080/api/rest/services/");
AbstractRepository.call(this, restangular,'http://192.168.0.144:8080/api/rest/services/');
}
AbstractRepository.extend(ServiceRepository);
return new ServiceRepository();
}
And i call the methods :
ServiceRepository.getList();
And now i want to implement and function (getServicesByOperatorId) that only works in the specific repository, not in the abstract. So i can call it like this:
ServiceRepository.getServicesByOperatorId({"operatorId":7});
If i define the function in the prototype of the abstract it works, but i want i way to define in the specific.
Thank you very much for your time.
Finally i find a way to do what i want:
In the specific factory define the prototype and extend from the abstract prototype like this:
ServiceRepository.prototype = {
getServicesByOperatorId: function (id) {
return this.restangular.all(this.route + 'getServicesByOperatorId').getList(id).$object;
}
}
angular.extend(ServiceRepository.prototype, AbstractRepository.prototype);
And in the abstract repository, remove this definition:
AbstractRepository.extend = function (repository) {
repository.prototype = Object.create(AbstractRepository.prototype);
repository.prototype.constructor = repository;
}
No i can access to de getList() method and the getServicesByOperatorId().

Angularjs $http my second then before first then is done.

I am not sure what I am doing wrong here, but the Report.xls gets downloaded before report.students gets updated.
How can I make it wait for report.students to be updated before Report.xls get downloaded?
Here is my code
`data service function
function getStudentsForExcel() {
var filter = studentFilter;
filter.data.perPage = StudentsModel.data.countTotal;
return $http.post(url + "/summeries", filter.data)
.then(onStudentSummeries)
.catch(onError);
function onStudentSummeries(response) {
return response.data;
}
}`
This function in my controller
`
function tocsv() {
studentData.getStudentsForExcel().then(function(data) {
report.students = data;
}).then(function() {
var blob = new Blob([document.getElementById('tableReport').innerHTML], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"
});
saveAs(blob, "Report.xls");
});
}`

AngularJS - self referencing services?

I'm building an Angular app that will have a top-level Controller and a second-level controller. There will be n number of second-level controllers, but I want to put global-level functions someplace. I'm doing this in a service.
I'm starting down the path of creating a single service that return an api, really, containing lots of functions (below). The service is returning an object with two property branches that each contain a set of functions. How can I call one of these from the other?
globalModule.factory('global', function($http) {
var squares = MyApp.squares; // this is the *only* link from Global namespace to this app
return {
squareMgr: {
getSquaresEarned: function() {
return squares.earned;
},
getSquaresPlaced: function() {
return squares.placed;
},
setThisSquareEarned: function(value) {
squares.earned.push(value);
},
setThisSquarePlaced: function(value) {
squares.placed.push(value);
}
},
missionMgr: {
missionInfo: {},
setMissionInfo: function(missionInfo) {
this.missionInfo = missionInfo
},
complete: function(missionData) {
log('complete called on video at ' + new Date());
missionData.complete = true;
log(angular.toJson(missionData));
$http({
url: '/show/completeMission',
method: "POST",
data: missionData
})
.then(function(response) {
if (response.data.success === true) {
log('completeMission success');
// increment squares earned counter
this.squareMgr.setThisSquareEarned(missionData.id);
// above is an attempt to run a function contained in this
// same service in a different parent property branch.
// how *should* I do this?
}
});
}
}
}
});
How about something like this:
globalModule.factory('global', function($http) {
var glob = {
squareMgr: {
// ...
},
missionMgr: {
foo: function() {
glob.squareMgr.xyz();
}
}
};
return glob;
});

Resources