angularjs directive definition using angular.module - javascript

Please can anyone explain why the following throws an "Argument 'MainCtrl' is not a function, got undefined" error which seems to be tied into the use of module dependency injection with directives(?!).
angular.module('app', [])
.controller('MainCtrl', [function() {
var self = this;
self.name = "will this work";
self.items = [
{
name: "name 1",
test: "test 1"
},
{
name: "name 2",
test: "test 2"
}
];
}]);
angular.module('app',[])
.directive('typeahead', [function() {
return {
templateUrl: 'type-ahead.html',
restrict: 'AEC',
scope: {
items: '=',
prompt: '#',
title: '#',
subtitle: '#',
model: '=',
onSelect: '&'
}, <...more code>
Yet it will work perfectly fine when I remove the
[ ]
module dependency braces from the directive to read
angular.module('app').directive('typeahead', ...)
It also works perfectly fine if I define the directive as a cascade following the controller definition i.e.
angular.module('app', [])
.controller('MainCtrl', [function() {
var self = this;
self.name = "will this work";
self.items = [
{
name: "name 1",
test: "test 1"
},
{
name: "name 2",
test: "test 2"
}
];
}])
.directive('typeahead', [function() {
return {
Thanks in advance!

You are running into Angular's Creation versus Retrieval Problem:
Beware that using angular.module('myModule', []) will create the module myModule and overwrite any existing module named myModule. Use angular.module('myModule') to retrieve an existing module.
The first time you run angular.module('app',[]), Angular will create a module called app. Next time, you only need to run angular.module('app'), Angular will try to load the existing module app.
Since you call angular.module('app',[]) once again, module app has been re-initialized. That's why MainCtrl is undefined now.

Related

Wrapping window global variable in AngularJS

I'm wrapping a global variable in a factory so that it can be injectable. It looks something like this:
angular.module('Analytics').factory('woopra', [
'$window',
function ($window) {
return $window.woopra;
}
]);
Because of how this tool works, at some point in the future after running initialisation, the variable woopra on the window gets replaced with a new value.
I need the injectable factory woopra to reference this new woopra variable that is on the window. What's a nice way to do this? At the moment I'm just referencing it as $window.woopra so I can mock $window.
factory
angular.module('Analytics').factory('woopra', [function () {
return {
'injectableVar': 'test Value'
}
}]);
Ctrl2
angular.module('Analytics').controller('Ctrl1', ['$scope', 'woopra', function ($scope, woopra) {
woopra.injectableVar = 'Value from Ctrl1';
}]);
Ctrl2
angular.module('Analytics').controller('Ctrl2', ['$scope', 'woopra', function ($scope, woopra) {
$scope.Ctrl2Var = woopra.injectableVar;
}]);
This sample show enjectableVar share between 2 controller
Why use factories? So much typing, I use the angular value and constant properties. Use the constant one if you don't want it editable. And then just inject it into the controller you want to you:
app.constant("woopra", "test 1234");
// OR the value property, can also be an array
app.value("proptypes", [
{
Description: "Duplex"
}, {
Description: "Simplex"
}, {
Description: "Duet"
}, {
Description: "Cluster"
}, {
Description: "House"
}, {
Description: "Townhouse"
}]);

Angular error: [$injector:unpr] Unknown provider: lineChartProvider <- lineChart <- MainController

Not Sure why but my controller wont recognize the service. I have checked enerything what am I missing here. I have included the services file in HTML. It recognizes other services but not just this one
(function() {
'use strict';
angular
.module('pollyvotes')
.service('lineChart', lineChart);
/** #ngInject */
function lineChart($scope, $http){
var promise = null;
return function(){
if (promise){
return promise
} else {
promise = $http.jsonp('')
.success(function(data){
$scope.predictions = data;
})
.error( function(data){
$scope.data = "Request failed";
})
return promise;
}
}
Controller
(function() {
'use strict';
angular
.module('pollyvotes')
.controller('MainController', MainController);
/** #ngInject */
function MainController($scope, $timeout, lineChart) {
$scope.photos = [ {id: 'chart-1', name: 'something here',src: "assets/images/300x600.png", href: "https://www.google.de/?gws_rd=ssl", discription: "say something about the chart here"},
{id: 'chart-2', name: 'another picture', src: "assets/images/300x600.png", href: "https://www.google.de/?gws_rd=ssl", discription: "say something about the chart here"},
{id: 'chart-3', name: 'another picture', src: "assets/images/300x600.png", href: "https://www.google.de/?gws_rd=ssl", discription: "say something about the chart here"},
{id: 'chart-4', name: 'another picture', src: "assets/images/300x600.png", href: "https://www.google.de/?gws_rd=ssl", discription: "say something about the chart here"}
];
}
})();
and declaring module
(function() {
'use strict';
angular
.module('pollyvotes', ['ngAnimate', 'ngCookies', 'ngTouch', 'ngSanitize',
'ngMessages', 'ngAria', 'ngResource', 'ui.router',
'ui.bootstrap', 'akoenig.deckgrid', 'smoothScroll',
'ngToast', 'picardy.fontawesome']);
})();
You are injecting $scope to your service.
That's what the documentation says about this error:
https://docs.angularjs.org/error/$injector/unpr
Attempting to inject a scope object into anything that's not a controller or
a directive, for example a service, will also throw an
Unknown provider: $scopeProvider <- $scope error.
There is a good answer how to avoid this here:
Injecting $scope into an angular service function()

Angular Directive isn't running and templateUrl isn't showing

Can't find why this directive isn't runnning.
No errors of any type, link function not being called and template is not being rendered.
Original code is on TypeScript but I have reproduced exactly the same behavior in a plnkr trying to make the problem come up, but still.
Plnkr version: http://plnkr.co/edit/vBARsB9PhZ4txjlmolMM?p=preview
JS
angular.module('DirectivesApp', [])
.controller('MainCtrl', ['$scope', function($scope) {
$scope.text = 'find this, also this';
$scope.Items = [{
Key: 'find this',
Value: 'FOUND 1'
}, {
Key: 'also this',
Value: 'FOUND 2'
}];
}]).directive('multiSelect', function() {
return {
templateUrl: 'multipleSelect-template.html',
$scope: {
text: '#text',
Items: '&Items'
},
restrict: 'A',
link: function($scope, element, attrs) {
$scope.text = attrs.text;
}
};
});
HTML
<div ng-app="DirectivesApp">
<div ng-controller="MainCtrl">
<multi-select text="{{text}}" Items="{{Items}}"></multi-select>
</div>
</div>
Template
<input type="text" disabled value="{{text}}" />
<input type="checkbox" ng-repeat="item in Items" value="{{item.Key}}"/><label>{{item.Value}}</label>
PS: trying to make a custom multiselect control.
To summarise all the comments above, this should be all you need
return {
templateUrl: 'multipleSelect-template.html',
scope: {
text: '#',
Items: '='
}
};
The default restrict is "EA" anyway and you don't need to bind attrs.text to the $scope as it's already bound in the isolate scope.

Angular JS, Error: [$injector:nomod] Module 'blogger.posts.controllers' is not available

I am following the Book Angular.js - Novice to Ninja
This is how I have set up the project:
app/js/app.js:
angular.module('blogger', ['blogger.posts', 'ui.router']);
app/modules/posts/postModule.js:
angular.module('blogger.posts', ['blogger.posts.controllers', 'blogger.posts.services']);
angular.module('blogger.posts').config(['$stateProvider', '$urlRouterProvider', '$locationProvider', function($stateProvider, $urlRouterProvider, $locationProvider){
$urlRouterProvider.otherwise('/posts');
$stateProvider.state('allPosts', {
url:'/posts',
templateUrl:'modules/posts/views/posts.html',
controller:'PostsController'
});
}]);
app/modules/posts/js/controllers.js:
angular.module('blogger.posts.controllers')
.controller('PostController', ['$scope', 'postService', function($scope, postService){
$scope.getAllPosts=function(){
return postService.getAll();
};
$scope.posts=$scope.getAllPosts();
}]);
app/modules/posts/js/services.js:
angular.module('blogger.posts.services').factory('postService',
function(){
return {
posts:[{
id:1,
title:'Sample title 1',
content:'Sample content 1',
permalink:'sample-title1',
author:'Sandy',
datePublished:'2015-21-01'
}],
getAll:function(){
return this.posts;
}
}
});
But if I run the code it is giving me this error:
Error: [$injector:nomod] Module 'blogger.posts.controllers' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument
/**
* Create blogger.posts which dependes on sub modules
* 'blogger.posts.controllers', 'blogger.posts.services'
* Ex . angular.module('moduleName', []) syntax for module setter.
* This is requried before registering on module
*/
angular.module('blogger.posts', ['blogger.posts.controllers',
'blogger.posts.services']);
/**
* Module setters
*/
angular.module('blogger.posts.controllers', []);
angular.module('blogger.posts.services', []);
/**
* Now you can register controllers , service, directive etc
*/
angular.module('blogger.posts.services').factory('postService',
function () {
return {
posts: [{
id: 1,
title: 'Sample title 1',
content: 'Sample content 1',
permalink: 'sample-title1',
author: 'Sandy',
datePublished: '2015-21-01'
}],
getAll: function () {
return this.posts;
}
}
});
angular.module('blogger.posts.controllers')
.controller('PostController', ['$scope', 'postService',
function ($scope, postService) {
$scope.getAllPosts = function () {
return postService.getAll();
};
$scope.posts = $scope.getAllPosts();
}]);
I just fixed this (i was doing the same tutorial :P). in the file app/js/app.js you need to have:
angular.module('blogger', [
'ui.router',
'blogger',
'blogger.posts'
]).run(['$state', function($state){
$state.go('allPosts');
}]);
and that should fix it :)

Using non-angular external js functions inside angularjs controller

I'm still new to angularJs.
I need to access Enumerable class from linqjs inside an angularjs controller.
My ngController looks similar to this:
var app1= angular.module("app1");
app1.controller("peopleController", ['$scope', 'Restangular',
function($scope, Restangular) {
$scope.people = Restangular.all('people').getList()
$scope.selectedItem = Enumerable.From(people).FirstOrDefault(); // ERROR
}]);
The error I'm getting is:
ReferenceError: Enumerable is not defined
any help?
I think it should be:
var app1 = angular.module("app1");
app1.controller("peopleController", ['$scope', 'Restangular', function ($scope, Restangular) {
$scope.people = Restangular.all('people').getList();
$scope.selectedItem = Enumerable.From(people).FirstOrDefault(); // ERROR
}]);
So without the 'peopleController' name of the function.
Edit
The problem is that Enumerable ( which is defined in linqjs ) is not available at the moment that it is called. Therefore the injector is looking for it and for the Enumerableprovider, but it doesn't exist nor is it injected.
You want to make sure you load the linqjs sources before your application is run. If Enumerable is defined in the global scope, you should be fine to use it from your controller. I created a JsFiddle that loads angular and linqjs from a CDN and shows you that it will 'just work' from your controller: http://jsfiddle.net/ngn3Lprx/2/
var app = angular.module('myapp', []);
app.controller('myctrl', ['$scope', function ($scope) {
// Example from: http://linqjs.codeplex.com/
var jsonArray = [
{ "user": { "id": 100, "screen_name": "d_linq" }, "text": "to objects" },
{ "user": { "id": 130, "screen_name": "c_bill" }, "text": "g" },
{ "user": { "id": 155, "screen_name": "b_mskk" }, "text": "kabushiki kaisha" },
{ "user": { "id": 301, "screen_name": "a_xbox" }, "text": "halo reach" }
]
// ["b_mskk:kabushiki kaisha", "c_bill:g", "d_linq:to objects"]
$scope.queryResult = Enumerable.From(jsonArray)
.Where(function (x) { return x.user.id < 200 })
.OrderBy(function (x) { return x.user.screen_name })
.Select(function (x) { return x.user.screen_name + ':' + x.text })
.ToArray();
}]);
With view:
<div ng-app="myapp">
<div ng-controller="myctrl">
<pre>
{{ queryResult | json }}
</pre>
</div>
</div>
Gives:
[
"b_mskk:kabushiki kaisha",
"c_bill:g",
"d_linq:to objects"
]
As expected.
p.s. Dont' forget the semi-colon after .getList();

Categories