I trying to get on my feet with angular.js using the seed app.
When the browser executes my controller i get the following error:
TypeError: Cannot set property 'players' of undefined
at new bankC (http://localhost:8888/monopoly/js/controllers.js:18:20)
at invoke (http://localhost:8888/monopoly/lib/angular/angular.js:2795:28)
at Object.instantiate (http://localhost:8888/monopoly/lib/angular/angular.js:2805:23)
at http://localhost:8888/monopoly/lib/angular/angular.js:4620:24
at update (http://localhost:8888/monopoly/lib/angular/angular.js:13692:26)
at http://localhost:8888/monopoly/lib/angular/angular.js:8002:24
at Array.forEach (native)
at forEach (http://localhost:8888/monopoly/lib/angular/angular.js:110:11)
at Object.Scope.$broadcast (http://localhost:8888/monopoly/lib/angular/angular.js:8000:11)
at http://localhost:8888/monopoly/lib/angular/angular.js:7185:26
this is the controller code which is the controller.js file
function bankC($scope) {
$scope.players = [
{
id: 0,
name: "Playe1",
balance: 1500
},
{
id: 1,
name: "Player2",
balance: 1500
},
{
id: 2,
name: "Player 3",
balance: 1500
}
];
}
bankC.$inject = [];
Thanks
EDIT:
its registered with angular js to be used when on a certain "page"
angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives']).
config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/view1', {templateUrl: 'partials/partial1.html', controller: MyCtrl1});
$routeProvider.when('/view2', {templateUrl: 'partials/partial2.html', controller: MyCtrl2});
$routeProvider.when('/bank', {templateUrl: 'partials/bank.html', controller: bankC});
$routeProvider.otherwise({redirectTo: '/bank'});
}]);
EDIT2:
Removing "bankC.$inject = [];" from the controller file solved the problem, so why does the angular.js seed app include it?
You are getting that error because of the last line
bankC.$inject = [];
This tells the angular injector to inject nothing into the controller while the controller is looking for $scope.
If you change this to
bankC.$inject = ['$scope'];
it should work fine.
That last line exists because angular uses Dependancy Injection. Angular looks for variables with name $scope when you request for it in a controller. But if the code is minified then the obfuscation will change the name of $scope to something else. In order to maintain sanity when this happens that last line is introduced. When ever you declare a new controller the best practice would be to include that last line with all the variables you want angulars DI to inject into that controller.
Note : If you are interested in getting more things injected into that controller ( or similiar controllers ) then you will have to update bankC.$inject as well.
Related
I can't find any similar problems on SO, so I suspect my issue is due to my setup, so I hope someone is able to spot a flaw in my code
I've used DataTables successfully in the past, but not with Angular and I'm having some trouble getting the table to do the initial load with its data.
I have the following code and the code with a fromFnPromise() that never gets hit. As you'll see, I'm forced to use an existing controller, so its definition does not match that of the example, but I'm pretty sure what I have should work:
var controllerName = "gaugeDashboardController";
angular
.module('bps.gauge', ['daterangepicker', 'amChartsDirective', 'angularjs-dropdown-multiselect', 'datatables', 'datatables.bootstrap', 'datatables.buttons'])
.controller(controllerName, Controller);
Controller.$inject = ['$scope', '$location', 'hubservice', '$http', '$state', '$stateParams', '$localStorage', 'coreAppService', '$q', 'DTOptionsBuilder', 'DTColumnDefBuilder'];
function Controller($scope, $location, hubservice, $http, $state, $stateParams, $localStorage, coreAppService, $q, DTOptionsBuilder, DTDefColumnBuilder) {
var vm = this;
vm.dtOptions = DTOptionsBuilder.fromFnPromise(function () {
var defer = $q.defer();
$http.get('/master/js/custom/bps/empty.json').then(function (result) {
defer.resolve(result.data);
});
return defer.promise;
})
.withPaginationType('full_numbers')
.withButtons([
'copy',
'excel'
])
.withOption('responsive', true);
vm.dtInstance = {};
vm.dataTableColumns = [
DTDefColumnBuilder.newColumnDef('Id').withTitle('Id').notVisible(),
DTDefColumnBuilder.newColumnDef('LocationId').withTitle('LocationId').notVisible(),
DTDefColumnBuilder.newColumnDef('ClientId').withTitle('ClientId').notVisible(),
DTDefColumnBuilder.newColumnDef('RecordDate').withTitle('RecordDate'),
DTDefColumnBuilder.newColumnDef('StoreCode').withTitle('StoreCode'),
DTDefColumnBuilder.newColumnDef('LocationName').withTitle('LocationName'),
DTDefColumnBuilder.newColumnDef('SubLocality').withTitle('SubLocality'),
DTDefColumnBuilder.newColumnDef('Locality').withTitle('Locality'),
DTDefColumnBuilder.newColumnDef('Country').withTitle('Country')
];
I've also tried the following and the GET request is never fired:
DTOptionsBuilder.fromSource('/js/data/test.json')
The json file just contains a simple array of objects
HTML:
<table datatable="" dt-options="dataTableOptions" dt-columns="dataTableColumns" dt-instance="dtInstance" dt-column-defs="dtColumnDefs" class="row-border hover"></table>
The controller name is not specified in the HTML, but rather in a routes.config.js file as follows:
.state('app.gauge_dashboard', {
url: '/gauge/dashboard',
title: 'Gauge Dashboard',
controller: 'gaugeDashboardController',
controllerAs: 'gdc',
templateUrl: helper.basepath('Bps/GaugeDashboard'),
params: {
}
})
So, in my understanting of this syntax, the controller name is set programmatically to 'gaugeDashboardController' when my HTML (at url: "/guage/dashboard"). So I think the scope is correct. Initially I got the injection of the dependency wrong and I got exceptions about the validity of DTDefColumnBuilder and DTOptionsBuilder
I've made sure that my JS files are included in the correct order as specified here
I do get an exception thrown in jquery.dataTables.js "Cannot read property 'aDataSort' of undefined", but this is after the above code gets executed.
It seems to me as if I'm missing some instantiation method call, but there's nothing here that I'm leaving out.
I really want to achieve two things:
Get the table to instantiate with data
Push new data into the table at a later stage. I can't seem to do this because there is no instance of the table
I have a project where homeapp.js contains the angular.module dependencies:
var HomeApp = angular.module('HomeApp', [
'ngRoute',
'ngCookies',
'HomeControllers',
'metadataControllers',
'MyControllers',
'ScheduleControllers'
]);
HomeApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/schedules', {
templateUrl: 'pages/list_schedule.html',
controller: 'ScheduleControllers'
});
and in a ScheduleController.js, I have:
angular.module('ScheduleControllers', []).controller('PhoneListCrl', function($scope) {
$scope.phones = [
{'name': 'Nexus S',
'snippet': 'Fast just got faster with Nexus S.'},
{'name': 'Motorola XOOM with Wi-Fi',
'snippet': 'The Next, Next Generation tablet.'},
{'name': 'MOTOROLA XOOM',
'snippet': 'The Next, Next Generation tablet.'}
];
});
this is basically the code snippet from the angular tutorial.
In the index.html, I have:
<html lang="en-CA" ng-app="HomeApp">
...
<li id="id_schedule_list" class="header_list">List Schedule</li>
...
which then directs to this the schedules.html with only the follow codes:
<div>
<div ng-controller="PhoneListCrl">
<p>{{phones}}</p>
</div>
</div>
However when the html is opened from browser, it shows {{phones}} straight, without being able to show the full json object. The console says
https://docs.angularjs.org/error/ng/areq?p0=ScheduleControllers&p1=not%20a 1.#QNAN0unction%2C%20got%20undefined
Which doesn't really make sense to me, but I guess it is saying ScheduleControllers is undefined.
EDIT:
In angluar's tutorial, the app.js says:
var phonecatApp = angular.module('phonecatApp', [
'ngRoute',
'phonecatAnimations',
'phonecatControllers',
'phonecatFilters',
'phonecatServices'
]);
and then in controllers.js, it has:
var phonecatControllers = angular.module('phonecatControllers', []);
phonecatControllers.controller('PhoneListCtrl', ['$scope', 'Phone',
function($scope, Phone) {
$scope.phones = Phone.query();
$scope.orderProp = 'age';
}]);
Looks like I am almost doing exactly what the tutorial does, but why it doesn't work for me?
The problem is actually with the route. You are using the module's name for the controller instead of the actual controller name.
Where you have controller: 'ScheduleControllers', you instead need controller: 'PhoneListCtrl'. Additionally, the code you pasted has a typo in the controller definition. You need a t in PhoneListCtrl in
angular.module('ScheduleControllers', []).controller('PhoneListCtrl', function($scope) `
EDIT
In the following code, you are telling angular which controller to load when you access the /schedules route. Right now, it is pointing to 'ScheduleControllers', which is a module, not a controller. Change it to match the second block and you should be good to go.
HomeApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/schedules', {
templateUrl: 'pages/list_schedule.html',
controller: 'ScheduleControllers'
});
HomeApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/schedules', {
templateUrl: 'pages/list_schedule.html',
controller: 'PhoneListCtrl'
});
See https://docs.angularjs.org/tutorial/step_07 for reference.
You're attaching your controller to another Angular module:
// This line creates a new module named "ScheduleControllers"
// And attaches the "PhoneListCrl" to it.
angular.module('ScheduleControllers', []).controller('PhoneListCrl', function() { ... });
If you want it to be visible to your HomeApp then attach it to that module:
// You need to attach "PhoneListCrl" to your original module.
angular.module('HomeApp').controller('PhoneListCrl', function() { ... });
the controller: 'ScheduleControllers' is name of module and not controller, hence the issue
Code
var app= angular.module('myApp', ['ngRoute', 'ngResource']);
app.factory('Greeter', ['$resource',function($resource){
return $resource(
'http://123.com/processor-url.php',{
/*inputName:inputName,*/
callback: 'JSON_CALLBACK'
},{
query: {method:'GET',isArray:true}
});
}]);
app
.controller('appointmentController', ['$scope','routeParams', 'Greeter',
function($scope,$routeParams,Greeter){
/*alert("yes");*/
alert($routeParams);
var x = Greeter.query({
myvar: $routeParams
});
$scope.output = x;
}]);
app.controller('homeController', ['$scope', function($scope){
}])
/*Final Config After Loading Everything*/
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/appointments/:myvar', {templateUrl: 'appointments.html', controller: 'appointmentController'});
$routeProvider.when('/home', {templateUrl: 'home.html', controller: 'homeController'});
$routeProvider.otherwise({redirectTo: '/home'});
}]);
Data (from http://123.com/processor-url.php when myvar=1066)
[
{
"myCodeId": "1066",
"myCodeName": "session test",
"myCodeOwner": "dvg",
"myCodeBody": "",
"myCodeTimesUsedCount": "0",
"myCodeValueAsMins": "0",
"myCodeCreateDate": "2014-07-30 11:04:58",
"myCodeLastEditDate": "2014-07-30 11:05:43",
"isSnippet": "0",
"isDeleted": "0",
"isMyFavorite": "0"
}
]
I ran with this code + the data that suppose to be the result of myvar=1066.
There will be error of
TypeError: Cannot read property 'query' of undefined
at new <anonymous> (.../urlTest/:29:24)
on the line where is
var x = Greeter.query({
I wonder where the mistake is? As I did inject Greeter inside the controller itself.
==Update 1]===
I updated the code by fixing all routeParam into routeParams.
Previous error is resolved. However, now the error becomes
Error: [$injector:unpr] Unknown provider: routeParamsProvider <- routeParams
http://errors.angularjs.org/1.2.0-rc.3/$injector/unpr?p0=routeParamsProvider%20%3C-%20routeParams
I maybe using the routeParams in a wrong way? Since what I wanted to do is that I assume routeParams will be the value of 1066 as thats what after the '/' symbol. Am I wrong in understanding its functionality?
Thanks
One issue i clearly see is the parameter mismatch for DI. This
.controller('appointmentController', ['$scope', 'Greeter',
function($scope,$routeParam,Greeter){
should be
.controller('appointmentController', ['$scope','$routeParam', 'Greeter',
function($scope,$routeParams,Greeter){
Also the service name is $routeParams
I have built an test app very similar to the one from AngularJS' tutorial, with 1 major difference: It is initialized with Yeoman.
My factory code looks like this:
var deClashServices = angular.module('deClashServices', ['ngResource']);
deClashServices.factory('Session',
['$resource',
function ($resource) {
return $resource('views/sessions.json');
}]
);
Yes, angular-resource.js has been added to index.html. As well as my Controller, and Service js files.
Yes, deClashServices has been listed as a dependency on the ng-app, as seen here in my app.js:
var declashAngularApp = angular.module('declashAngularApp', [
'ngRoute',
'deClashServices',
'deClashControllers'
]);
declashAngularApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/sessions', {
templateUrl: 'views/sessions.html',
controller: 'SessionListCtrl'
})
.otherwise({
redirectTo: '/'
});
}]);
and here is my Controller:
var deClashControllers = angular.module('deClashControllers', []);
deClashControllers.controller('MainCtrl',
['$scope', 'Session',
function ($scope, Session) {
$scope.sessions = Session.query();
$scope.awesomeThings = [
'HTML5 Boilerplate',
'AngularJS',
'Karma'
];
}]
);
in main.html, which is under MainCtrl, {{awesomeThings}} produces the array of 3 strings, as expected.
But {{sessions}} produces an empty array.
To pinpoint that it is .query() that's not loading it, I tried using a factory with a simple JSON file: {"sessions":"number1"}
deClashServices.factory('Session',
['$resource',
function ($resource) {
return $resource('views/simple.json');
}]
);
And my controller is like this:
deClashControllers.controller('MainCtrl',
['$scope', 'Session',
function ($scope, Session) {
$scope.sessions = {};
Session.get(function(response) {
$scope.sessions = response.sessions;
});
$scope.awesomeThings = [
'HTML5 Boilerplate',
'AngularJS',
'Karma'
];
}]
);
This code works. Switching back to the JSON array and trying a callback with .query.$promise.then(callback-function) however, does not work.
I'm pretty lost and confused now, as the tutorial code from AngularJS with almost the exact same structure works.
I suspect that there's something wrong in the way I'm using .query(), but at the same time the same way is used by the Angular Tutorial and there isn't a problem there.
Just in case that it might be outside the few code snippets I've shown, here in the code for the entire project:
github
Angular's resource-service doesnt return promise. It returns an empty object so that when the request returns from server resource-service can populate that object with fetched data because it has a reference to that object.
So if you want to react to returning data you have to use a callback function or better yet
use $http-service, because it return promise.
Look at this plkr
I also recommend you take a look at Restangular
Hi there I was watching a couple of the angular.js videos and saw that the value() method was used to set a kind of module-wide constant. for example, one can set the Angular-UI library's config like so: (coffeescript)
angular.module('app',[])
.value "ui.config",
tinymce:
theme: 'simple'
width: '500'
height: '300'
And my app is currently looking like this:
window.app = angular.module("app", [ 'ui'])
.config(["$routeProvider", ($routeProvider) ->
$routeProvider
.when "/users",
templateUrl: "assets/templates/users/index.html"
controller: IndexUsersCtrl
.otherwise redirectTo: "/users"
])
.value 'csrf', $('meta[name="csrf-token"]').attr('content') #<---- attention here
IndexUsersCtrl = ($scope) ->
$scope.users = gon.rabl
console.log "I want to log the csrf value here" #<---- then attention
IndexUsersCtrl.$inject = ['$scope']
But I can't seem to get that value by tapping into the 'app' variable which is corresponding to the app module.
I read up here on ST and over on angularjs's google group that one way to share common code btwn controllers is through a service, will this concept apply here, too?
Thanks!
Module.value(key, value) is used to inject an editable value,
Module.constant(key, value) is used to inject a constant value
The difference between the two isn't so much that you "can't edit a constant", it's more that you can't intercept a constant with $provide and inject something else.
// define a value
app.value('myThing', 'weee');
// define a constant
app.constant('myConst', 'blah');
// use it in a service
app.factory('myService', ['myThing', 'myConst', function(myThing, myConst){
return {
whatsMyThing: function() {
return myThing; //weee
},
getMyConst: function () {
return myConst; //blah
}
};
}]);
// use it in a controller
app.controller('someController', ['$scope', 'myThing', 'myConst',
function($scope, myThing, myConst) {
$scope.foo = myThing; //weee
$scope.bar = myConst; //blah
});
I recently wanted to use this feature with Karma inside a test. As Dan Doyon points out the key is that you would inject a value just like a controller, service, etc. You can set .value to many different types - strings, arrays of objects, etc. For example:
myvalues.js a file containing value - make sure it is including in your karma conf file
var myConstantsModule = angular.module('test.models', []);
myConstantModule.value('dataitem', 'thedata');
// or something like this if needed
myConstantModule.value('theitems', [
{name: 'Item 1'},
{name: 'Item 2'},
{name: 'Item 3'}
]);
]);
test/spec/mytest.js - maybe this is a Jasmine spec file loaded by Karma
describe('my model', function() {
var theValue;
var theArray;
beforeEach(module('test.models'));
beforeEach(inject(function(dataitem,theitems) {
// note that dataitem is just available
// after calling module('test.models')
theValue = dataitem;
theArray = theitems;
});
it('should do something',function() {
// now you can use the value in your tests as needed
console.log("The value is " + theValue);
console.log("The array is " + theArray);
});
});
You need to reference csrf in your controller IndexUsersCtrl = ( $scope, csrf )
IndexUsersCtrl.$inject = [ '$scope', 'csrf' ]