I'm attempting to understand how factories work and have hit a road block. I'm following along with this guide on page 88 or so.
Running my code results in these console errors.
TypeError: Cannot read property 'getData' of undefined
<div ng-app="timeEntry">
<div ng-controller="timeEntryController">
<p class="lead">Factory Test</p>
<p>**** {{testing}}</p>
<p>******** {{testing2}}</p>
</div>
</div>
var timeEntry = angular.module('timeEntry', []);
timeEntry.controller('timeEntryController', ['$scope', function ($scope, loadData) {
$scope.testing = 'test';
$scope.testing2 = loadData.getData();
}]);
timeEntry.factory('loadData', function ($http) {
var test = 'test data';
var factory = {};
factory.getData = function () {
return test;
};
return factory;
});
JS Fiddle http://jsfiddle.net/dgdavidson/QPc3j/2/
I'm sure that the error will be frightfully obvious, but I don't know what it is.
You need to add the string 'loadData' to your declaration:
So change this:
timeEntry.controller('timeEntryController', ['$scope', function ($scope, loadData) {
to:
timeEntry.controller('timeEntryController', ['$scope', 'loadData', function ($scope, loadData) {
(updated fiddle)
The error you're seeing is because Angular is passing undefined into loadData. And, of course, undefined has no property getData.
This is such an easy/common mistake that some people skip manually declaring the strings and use ngMin to do it for them (for instance adding it to your grunt file). This allows you to then use the following style of declaration where you don't have to ensure strings match parameters:
timeEntry.controller('timeEntryController', function ($scope, loadData) {
Related
I've looked at a half dozen examples, but none of them seems to work for me - maybe because of the peculiar var myController = [] format of the code I inherited.
.cshtml:
<div id="ng-app" ng-app="cmorApp">
<div
data-ng-controller="myCtrl"
data-ng-init="referralId = #Model.ReferralId">
...
This works, inasmuch as my page correctly renders the value I seek:
data-ng-init="referralId = 12345"
Now I'm just trying to capture it in my controller.
Controller:
var myCtrl = ['$scope', '$http', 'FileUploader',
function ($scope, $http, FileUploader, referralId) {
console.log(referralId);
//$scope.init = function (referralId) {
// console.log(referralId);
//}
//$scope.init();
It outputs undefined.
What am I missing?
.
UPDATE:
This sort of works:
ng-init="init(#Model.ReferralId)
.
$scope.init = function (referralId) {
$scope.referralId = referralId;
}
The problem is, the value is not there when I need it. It only there if I let the page do some processing.
I can't do this, or I'm back to undefined:
$scope.init = function (referralId) {
$scope.referralId = referralId;
}
console.log($scope.referralId);
I am creating a controller in AngularJS, and it works fine when i define it like this:
aluPlanetApp.controller('KontaktController', function($scope) {
$scope.title= 'Kontakt';
$scope.id = '10';
$scope.users =[{"MIGX_id":"1","image":"upload/bridge.png"}];
});
However, when I define it like this I get an error:
(function () {
'use strict';
aluPlanetApp.controller('KontaktController', KontaktController);
KontaktController.$inject = ['$scope'];
function KontaktController($scope) {
$scope.title= 'Kontakt';
$scope.id = '10';
$scope.users =[{"MIGX_id":"1","image":"upload/bridge.png"}];
activate();
function activate() { }
}
})();
This is the error I get:
TypeError: aluPlanetApp.config(...) is not a function
aluPlanetApp.config(function($routeProvider) {
The entire JavaScript file is here.
Just get rid of aluPlanetApp variable completely and always use the getter version of angular.module()
angular.module('aluPlanetApp').controller(...
angular.module('aluPlanetApp').service(...
angular.module('aluPlanetApp').directive(...
See John Papa Angular Style Guide
You need to get the module first after 'use strict',
var aluPlanetApp = angular.module("aluPlanetApp");
I have a controller that ive added a function to but cant get the function to be called from ng-click on an anchor. Ive looked at similar posts but cant really see what I could be missing. Its as though the controller function cant be seen?
The module and controller:
var commonModule = angular.module('common', ['ngRoute', 'ng.ckeditor']);
var mainModule = angular.module('main', ['common']);
//mainModule.config(function ($routeProvider, $locationProvider) {
// $locationProvider.html5Mode(true);
//});
commonModule.factory('viewModelHelper', function ($http, $q, $window, $location) {
return MyApp.viewModelHelper($http, $q, $window, $location);
});
commonModule.factory('validator', function () {
return valJs.validator();
});
mainModule.controller("rootViewModel",
function ($scope, $http, $q, $routeParams, $window, $location, viewModelHelper, $rootElement) {
//test
console.log("creating controller");
var self = this;
viewModelHelper.apiGet('api/PageContent/1', null,
function (result) {
$scope.htmlEditor = result.data;
});
$scope.ToggleEditor2 = function () {
//test
console.log("hello");
if ($scope.editorVisible == true) {
$scope.editorVisible = false;
}
else {
$scope.editorVisible = true;
}
}
});
The controller is referenced at the root level of the page:
Which in this case since im using ASP.Net MVC, is in my _layout.cshtml
<body data-ng-app="main" data-ng-controller="rootViewModel">
In a (mvc) view that gets loaded, I have a button with ng-click that calls the ToggleEditor2 function, but its never called. Cant get a breakpoint to hit in the chrome dev console and I dont see anything written to the log either.
<input type="button" ng-click="ToggleEditor2()" value="test me" />
Update:
If I wrap that anchor with a div and specify the "rootviewModel" controller there, the log message gets written. Hmmm - something tells me its related to scope?
<div data-ng-controller="rootViewModel">
<input type="button" ng-click="ToggleEditor2()" value="test me" />
</div>
Problem
A common problem with $scope is that when using any sort of nested controllers or modules, your $scope's can step on each other and cause issues like you have experienced.
Solution
Using Angular's "Controller As" syntax is the recommended solution for this problem. It allows you to create multiple instances of the same controller, while defining and maintaining a unique scope for each instance.
This Article is a great resource I used to understand and implement this new syntax.
this is how I implemented it
var ngModule = angular.module('appunit',['ui.bootstrap','bootstrapLightbox']);
ngModule.controller('ImageController', ['$scope', 'CallApi', function ($scope, CallApi, Lightbox)
{
$scope.openLightboxModal = function (index)
{
Lightbox.openModal($scope.listImages ,index);
};
}]);
by calling the openLightboxModal(index) in the HTML dom lead to this error
Cannot read property 'openModal' of undefined"
I tried something like this
['$scope', 'CallApi','Lightbox', function ($scope, CallApi, Lightbox)
but still no luck.
Any ideas ??
If you have code like that:
var ngModule = angular.module('appunit',['ui.bootstrap','bootstrapLightbox']);
ngModule.controller('ImageController', ['$scope', 'CallApi', 'Lightbox', function ($scope, CallApi, Lightbox)
{
$scope.openLightboxModal = function (index)
{
Lightbox.openModal($scope.listImages ,index);
};
}]);
then the assumption must be wrong as it's clearly undefined, maybe if you can post the way you include modules it would draw a bit of light on it
---edit---
ater exchaning comments with OP I got to Lightbox source, it appears that it requires version v.0.14.x of ui-bootstrap as up from this version Lightbox can use the modal
I'm running into a problem trying to setup a fairly simple call using a factory and controller in angularjs. I've been attempting to follow the style guides of John Papa and Todd Motto in setting this up.
First I'm using 2 modules
(function(){
'use strict';
angular.module('app',[
'app.core',
'app.property'
]);
})();
In 'app.core' I define the factory
(function(){
'use strict';
angular.module('app.core')
.factory('dataservice',dataservice);
dataservice.$inject = ['$http','$q'];
function dataservice($http,$q) {
var service = {
getListing: getListing
};
return service;
function getListing() {
var def = $q.defer;
$http.get("http://acme.com/property/1?format=json")
.success(function(data){
service.getListing = data;
def.resolve(data);
});
return def.promise;
}
}
})();
and in 'app.property' I defined the controller
(function(){
'use strict';
angular.module('app.property')
.controller('PropertyCtrl',PropertyCtrl);
PropertyCtrl.$inject = ['dataservice'];
function PropertyCtrl(dataservice) {
var vm = this;
vm.listings = [];
activate();
function activate() {
return getListing().then(function(){});
}
function getListing(){
return dataservice.getListing().then(function(data){
vm.listings = data;
console.log("data is");
console.log(data);
return vm.listings;
});
}
}
})();
the error I get in the console output is
Error: dataservice.getListing(...) is undefined except when I inspect dataservice in chrome I can see
Further on I receive
TypeError: Cannot read property 'then' of undefined
TypeError: def.resolve is not a function
Despite these errors the remote call returns json fine.
Hoping someone with angular chops has an idea on where I went wrong.
You're very close. It should be $q.defer() but you've $q.defer
function getListing() {
var def = $q.defer();
$http.get("http://acme.com/property/1?format=json")
.success(function(data){
service.getListing = data;
def.resolve(data);
});
return def.promise;
}
You have to actually create the modules you are building on:
Put this above your app.property module's objects:
angular.module('app.property', []);
Put this above your app.core module's objects:
angular.module('app.core', []);
You are basically attaching a factory and a controller to modules that don't exist. You are trying to inject modules that don't exist into your primary module.
Here is a plunker showing the issues you were having resolved. Your code has some other issues, but at least it's finding the modules now, which was your original problem.
It should also be noted that mohamedrias is also correct - you had an error in syntax by not putting () on your defer call.
I updated my plunker to include his correction as well.