"undefined is not a function" error using angularFire - angularjs

i am trying to display data from firebase and i have below code. I already declared firebase dependency for my app.
.controller('AdvMainCtrl', ['$scope', 'dataLoad',
function($scope, dataLoad, $route, $routeParams, $location, $resource, angularFire) {
var categoryPromise = dataLoad.loadCategories($scope, 'categories'),
tmPromise = dataLoad.loadTransportationMode($scope, 'tModes'),
tourPromise = dataLoad.loadAdventures($scope, 'tours');
categoryPromise.then(function() {
console.log('data loaded');
});
$scope.$watch('category', function() {
if (typeof $scope.category === 'undefined') return;
console.log('category changed');
console.log($scope.category.name);
});
$scope.$watch('tMode', function() {
if (typeof $scope.tMode === 'undefined') return;
console.log('tm changed');
//console.log($scope.transportationMode.name);
});
var ref = new Firebase("https://wpladv.firebaseio.com/adventure");
$scope.tours = [];
angularFire(ref, $scope, "tours");
}
])
in the console i see the error occurring at angularFire(ref, $scope, "tours"); statement. I am not sure how to fix this.
the entire code in my controller is
.controller('AdvMainCtrl', ['$scope', 'dataLoad',
function($scope, dataLoad, $route, $routeParams, $location, $resource, angularFire) {
var categoryPromise = dataLoad.loadCategories($scope, 'categories'),
tmPromise = dataLoad.loadTransportationMode($scope, 'tModes'),
tourPromise = dataLoad.loadAdventures($scope, 'tours');
categoryPromise.then(function() {
console.log('data loaded');
});
$scope.$watch('category', function() {
if (typeof $scope.category === 'undefined') return;
console.log('category changed');
console.log($scope.category.name);
});
$scope.$watch('tMode', function() {
if (typeof $scope.tMode === 'undefined') return;
console.log('tm changed');
//console.log($scope.transportationMode.name);
});
var ref = new Firebase("https://wpladv.firebaseio.com/adventure");
$scope.tours = [];
angularFire(ref, $scope, "tours");
}
])
the error is showing at "var categoryPromise = dataLoad.loadCategories($scope, 'categories')," statement
i have the following code in my api js file.
angular.module('localAdventuresApp')
.factory('dataLoad', ['angularFire',
function(angularFire) {
var dbUrl = 'https://wpladv.firebaseio.com/';
return {
loadCategories: function(scope, items) {
var cat = '/category';
return angularFire(dbUrl + cat, scope, items, []);
},
loadTransportationMode: function(scope, items) {
var cat = '/transportMode';
return angularFire(dbUrl + cat, scope, items, []);
},
loadAdventures: function(scope, items) {
var cat = '/adventures';
return angularFire(dbUrl + cat, scope, items, {});
}
}
}
])
the error is being displayed in the "return angularFire(dbUrl + cat, scope, items, []);" statement here. The error which i am seeing in my console is "Error: Please provide a Firebase reference instead of a URL, eg: new Firebase(url)".

you need to inject the dependencies to your controller
.controller('AdvMainCtrl', ['$scope', 'dataLoad', '$route', '$routeParams', '$location', '$resource', 'angularFire',
function($scope, dataLoad, $route, $routeParams, $location, $resource, angularFire) {
// your code here
}
])

the error "Please provide a Firebase reference instead of a URL, eg: new Firebase(url)" was occuring because i had angularfire version > 0.3.0. All i had to do was to change dbUrl + cat to new Firebase(dbUrl + cat). That fixed the issue. Thank you all for your valuable suggestions.
code after change
angular.module('localAdventuresApp')
.factory('dataLoad', ['angularFire',
function(angularFire) {
var dbUrl = 'https://wpladv.firebaseio.com';
return {
loadCategories: function(scope, items) {
var cat = '/category';
console.log(dbUrl);
var ref = new Firebase(dbUrl + cat);
return angularFire(ref, scope, items, []);
},
loadTransportationMode: function(scope, items) {
var cat = '/transportMode';
var ref = new Firebase(dbUrl + cat);
return angularFire(ref, scope, items, []);
},
loadAdventures: function(scope, items) {
var cat = '/adventure';
var ref = new Firebase(dbUrl + cat);
return angularFire(ref, scope, items, {});
}
}
}
])

Related

defining current state in unit tests

I've moved this 'reports' feature from a single module (called 'aam') into the core, so that other modules (such as 'bbc') can use it.
Now I'm rewriting the unit test(s).
The grunt error I'm getting is
should go state aam.reports with URL_NOT_SPECIFIED
reports-state spec
TypeError: 'null' is not an object
(evaluating 'BbpcConfiguration.getProperty(configProperty).then')
which indicates to me that $state is empty or not structured correctly.
Here is the report controller:
(function() {
'use strict';
angular.module('com.ct.bbpcCore')
.controller('reportController', ['$window', '$state', 'BbpcUserService', 'BbpcConfiguration', function ($window, $state, BbpcUserService,BbpcConfiguration) {
angular.element(document).ready(function () {
//Get url base on locale
var reportUrl = "URL_NOT_SPECIFIED";
var currentState = $state.current.name;
var configProperty = "";
var title = "";
if (currentState.indexOf('aam.reports')) {
configProperty = 'report.aam.link';
title = "AAM.REPORT";
};
if (currentState.indexOf('bbc.reports')) {
configProperty = 'report.bbc.link';
title = "BBC.REPORT";
};
BbpcConfiguration.getProperty(configProperty).then(function(response) {
if (response) {
var language = BbpcUserService.getLanguageCd() || "en_CA";
reportUrl = response[language] || reportUrl;
}
var spec = "width=" + $window.outerWidth + ", height=" + $window.outerHeight;
$window.open(reportUrl, title, spec);
});
});
}]);
}());
And here is report-controller.spec:
describe('reports-state spec', function() {
'use strict';
var $injector, $window, $rootScope,
$state, BbpcConfiguration, reportController, $controller, BbpcUserService;
beforeEach(function() {
module('com.ct.bbpcCore', function($provide) {
$provide.value('BbpcConfiguration', BbpcConfiguration = {
getProperty: function(key){
if('report.aam.link' === key){
return {
"fr_CA": "https://eng-link",
"en_CA": "https://fre-link"
};
}
return null;
}
});
});
inject(function(_$injector_) {
$injector = _$injector_;
$window = $injector.get('$window');
$state = $injector.get('$state');
$rootScope = $injector.get('$rootScope');
$controller =$injector.get('$controller');
BbpcUserService =$injector.get('BbpcUserService');
});
});
it('should go state aam.reports with URL_NOT_SPECIFIED', function() {
$state.current = {'name': 'aam.reports' };
spyOn($window, 'open').andCallFake(function(){});
reportController = $controller('reportController', {'$window':$window, '$state':$state, 'BbpcUserService':BbpcUserService, 'reportLink':undefined});
$state.go('aam.reports');
$rootScope.$apply();
expect($state.current.name).toEqual('aam.reports');
expect($window.open).toHaveBeenCalledWith('URL_NOT_SPECIFIED', 'AAM.REPORT', 'width=0, height=0');
});
});
I tried simply adding the line $state.current = {'name': 'aam.reports' }; in the 'it' block, but that's not what it's looking for.
Not sure how to debug unit tests. :P I can't use a console.log($state) to peek into it.

Use data from factory in controller in angularjs

I am very new to AngularJS.
I want to pass an array data from my app factory to app controller.
Here is my app.factory code.
App.factory('buyFactory', ['$http', function($http) {
factory.Search = function(scope, d) {
var data = scope.search;
scope.CarsData = [];
all_cars = [];
scope.isLoading = true;
$http.post(ajaxurl + '?action=search_car', d)
.success(function(response) {
angular.forEach(response, function(c) {
c.price = parseFloat(c.price);
c.driven = parseFloat(c.driven);
c.year = parseFloat(c.year);
});
angular.forEach(response, function(value, key) {
all_cars.push(value);
scope.CarsData = all_cars;
scope.TotalItems = scope.CarsData.length;
scope.isLoading = false;
})
.error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
scope.isLoading = false;
});
}
return factory;
}]);
and this is app.controller as
App.controller('buyController', ['$scope', '$http', 'buyFactory', '$filter', function($scope, $http, buyFactory, $filter) {
$scope.CarsScroll = buyFactory.Search.CarsData();
$scope.loadMore = function() {
var last = $scope.CarsScroll[$scope.CarsScroll.length - 1];
for (var i = 1; i <= 3; i++) {
$scope.CarsScroll.push(last + i);
}
};
//scroll
}]);
I want to use output obtained from factory i.e. CarsData as a variable in my app controller. But I am not able to get it. I have tried using services also. Is there method to use array data in a simplest way.
Your syntax is completely broken, i would recommend following any course of AngularJS. As for how to correctly do what you are trying to would look something like this
app.factory('buyFactory', ['$http', '$q', function($http, $q) {
var factory = {
search: function(d) {
return $q(function(resolve, reject) {
$http.post(ajaxurl + '?action=search_car', d).then(function(response) {
angular.forEach(response, function(c) {
c.price = parseFloat(c.price);
c.driven = parseFloat(c.driven);
c.year = parseFloat(c.year);
});
var carsData = [];
angular.forEach(response, function(value, key) {
carsData.push(value);
})
var result = {
carsData: carsData,
total: carsData.length
}
resolve(result);
}, function(error) {
reject(error);
})
});
}
}
return factory;
}]);
app.controller('buyController', ['$scope', '$http', 'buyFactory', '$filter', function($scope, $http, buyFactory, $filter) {
buyFactory.search().then(function(result) {
var cars = result.carsData;
var total = result.total;
})
}]);
Note: i do not know what the d parameter is for neither why the angular.forEach statements so it might not be fully functional. But this is more as guideline for how your factory should look and be used.

Cleaning JSON data

I am trying to clean the JSON data i have i.e. remove the N/A and null data. I am trying to use $.each to clean the data however it has no effect on the data.
.controller('APICtrl', function($scope, $http, $localstorage, $window, $state, $sce) {
// Search function
//var offices = [];
var n;
$scope.query = {}
$scope.queryBy = '$'
// gets the data from offices.json
$http.get('js/offices.json').then(function(resp) {
console.log('Success', resp);
$scope.offices = $.each(resp.data.office, function(key,value){
//console.log(value);
if(value==""||value==null){
delete resp.data.office[key];
}
});
//console.log(offices)
}, function(err) {
console.error('ERR', err);
// err.status will contain the status code
});
instean jquery functions
$scope.offices = $.each(resp.data.office, function(key,value){
use standart angular functions
$scope.offices = angular.forEach(resp.data.office, function(key,value){
https://docs.angularjs.org/api/ng/function/angular.forEach
Do you have jQuery included? Otherwise my guess is that you're getting an error that is being silenced because it's inside of a then. This should work:
.controller('APICtrl', function($scope, $http, $localstorage, $window, $state, $sce) {
// Search function
//var offices = [];
var n;
$scope.query = {};
$scope.queryBy = '$';
// gets the data from offices.json
$http.get('js/offices.json').then(function(resp) {
console.log('Success', resp);
var office = resp.data.office;
angular.forEach(office, function(value, key){
if (value == "" || value == null) {
delete office[key];
}
});
$scope.offices = office;
//console.log(offices)
}, function(err) {
console.error('ERR', err);
// err.status will contain the status code
});
});

How to test vm.variable - function(){..} unit testing with jasmine?

I am using karma- jasmine framework to test my angular application. I'm facing a problem in calling the functions of the controller or service form my test-spec. I tried using controller. as well as scope. but both of them didn't work for me.
The controller code is
(function () {'use strict';
angular.module('selfUi').controller('AttendeesController', AttendeesController);
AttendeesController.$inject = ['$state', '$stateParams', 'AttendeeService', 'settings', '$log'];
function AttendeesController($state, $stateParams, AttendeeService, settings, $log) {
var vm = this;
if ($stateParams.attendeeData === null) {
vm.pageType = "Add Attendee";
vm.isEdit = false;
} else {
var tempAttendee = $stateParams.attendeeData;
vm.pageType = "Edit Attendee";
vm.isEdit = true;
vm._id = tempAttendee._id;
vm.firstName = tempAttendee.firstName;
vm.lastName = tempAttendee.lastName;
}
vm.checkAvailable = function(email){
//Check email
if(email === null || angular.isUndefined(email) || email.trim().length === 0){
vm.invalidEmail = true;
}else{
// Check if email is already present or not
success = function(data, status, headers, config) {
if(data[0].success){
vm.validEmail = true;
}else{
if(data[0].message){
modalData = {
success : false,
};
}else{
vm.validEmail = false;
}
}
};
failure = function(data, status, headers, config) {
vm.invalidEmail = false;
};
AttendeeService.checkEmail(email, success, failure);
}
};
} })();
My test spec is:
describe('AttendeesController', function(){
beforeEach(module('SS'));
var state, $stateParams, stateParams, settings, AttendeeService, log;
var email= "temp#email.com";
var controller, $scope;
var vm;
$stateParams= {_id : "1",
attendeeType : "attendee",
firstName : "Pen",
lastName : "Red",
email : "temp#email.com",
company : "SWG",
jobTitle : "Speaker",
biography : "bio",
tagsInterest : "interests"}
beforeEach(inject(function($rootScope, _AddAttendeeService_, $controller, $state, $stateParams,settings, $log) {
AttendeeService= _AttendeeService_;
state= $state;
$scope = $rootScope.$new();
controller = function() {
return $controller('AttendeesController', {
$scope : scope,
$stateParams : $stateParams
});
};
}));
it('should be instantiated', function() {
expect(AttendeeService).toBeDefined();
});
it('should have controller.methods defined', function(){
expect(controller).toBeDefined();
expect(controller.checkAvailable).toBeUndefined();
controller.checkAvailable(email);
});
});
My service code looks like this:
(function() {
'use strict';
angular.module('SS').service('AttendeeService', AttendeeService);
AttendeeService.$inject = ['SSFactory', 'settings', '$rootScope'];
function AttendeeService(SelfSFactory, settings, $rootScope){
this.addAttendee = function(data, success, failure){
var responsePromise = SelfServiceFactory.httpPostRequest(settings.createAttendeeURL, data, config);
responsePromise.success(success);
responsePromise.error(failure);
return responsePromise;
};
}});
When I run my test spec, it gives me a error
TypeError: 'undefined' is not a function (evaluating 'controller.checkAvailable(email)')
at C:/Users/IBM_ADMIN/WebstormProjects/Self/self-service-ui.git/src/tests/addAttendees.controller.spec.js:53
I tried calling the checkAvailable function with the scope variable too, but it didn't work. I need to know how to call such methods in the controller from my test spec.

Angularjs and qunit testing

I have a angularjs web application and want to use qunit for unit testing in it. I have a controller:
function RootCtrl($scope, $rootScope, $window, $location) {
// logger is empty at the start
$scope.logger = '';
// we have no login error at the start
$scope.login_error = '';
//
// Get values array of object
//
$rootScope.values = function (obj) {
var vals = [];
for( var key in obj ) {
if(key !== '$$hashKey' && key !== 'checked')
vals.push(obj[key]);
}
return vals;
}
}
Now i want to write unit test for values function with qunit. I included all js files to the test/index.html and qunit.css. Now my test.js has following content:
var injector = angular.injector(['ng', 'myApp']);
var init = {
setup : function () {
this.$scope = injector.get('$rootScope').$new();
}
}
module('RootCtrl', init);
test('RootCtrl', function(){
var $controller = injector.get('$controller');
$controller('RootCtrl', {
$scope : this.$scope,
$location : this.$location
});
equal(['value'], $controller.values({'key' : 'value'}))
});
But i'm getting error: http://docs.angularjs.org/error/$injector/unpr?p0=$rootElementProvider%20%3C-%20$rootElement%20%3C-%20$location%20%3C-%20$route at:
$controller('RootCtrl', {
$scope : this.$scope,
$location : this.$location
});
How to inject correctly controller and use $scope, $rootScope, $location and another services from it?
Thank you.
Try this instead of your controller
$controller('RootCtrl',['$scope', '$rootScope', '$location','$route', function ($scope, $rootScope, $location, $route) {
$scope : this.$scope,
$location : this.$location
}]);
Had similar problem, so since no other answer here.
I ended up using:
client side code:
var myApp= angular.module('myApp', []);
myApp.controller('myCtrl', function ($scope) {
//angular client side code
$scope.canSubmit = function () {
//some logic
return true;
}
}
Qunit tests:
var ctrl, ctrlScope, injector;
module("Testing the controller", {
setup: function () {
angular.module('myApp');
injector = angular.injector(['ng', 'myApp']);
ctrlScope = injector.get('$rootScope').$new();
ctrl = injector.get('$controller')('myCtrl', { $scope: ctrlScope });
ctrlScope.model = {
//model object
};
},
teardown: function () {
}
});
test("Given something happened then allow submit", function () {
ok(ctrlScope.someFunction(...), "some functionality happened");
equal(true, ctrlScope.canSubmit());
});
This blog post was useful.
One can easily inject more into the controller under test.

Resources