why can't omit module dependency in angular.module when define component - javascript

The main moduleapp.js:
angular.module("myApp",["phoneList"]);
and I follow the tutorial to make a sperate component module named phoneList
angular.module("phoneList")
//^ omit the empty bracket here, cause no dependency needed
.component('phoneList', {
templateUrl: 'template/phone-list.html',
controller: function (){
this.phones = [
{name: "iphone", snippet: "designed by apple"},
{name: "nexus", snippet: "phone that could explode"}
]}
});
but it will complain that:
angular.min.js:6 Uncaught Error: [$injector:nomod] http://errors.angularjs.org/1.6.1/$injector/nomod?p0=phoneList
at angular.min.js:6
at angular.min.js:25
at b (angular.min.js:24)
at Object.module (angular.min.js:25)
at phone-list.js:5
When I add an empty [] back:
angular.module("phoneList",[])
.component(//balabla)
things will work just fine. I checked the API Reference, it demonstrate that the dependency is optional thus could be omitted.
So what cause the problem?

According to the documentation,
angular.module(name, [requires], [configFn]);
If specified then new module is being created. If unspecified then the
module is being retrieved for further configuration.
It means you need to pass an empty array []. To make it work without any dependency module, you can use it as
angular.module("phoneList",[])
Update
if the module is already declared you do not have to pass the dependencies again. So you can use your component/controller/service/factory as
angular.module('phoneList').controller(...)...

Once you have the module defined you can refer to it without the second argument. The first time you do.
So...
angular.module('app',[ dependencies... ]);
angular.module('app').controller(...)...
would be correct.

This is because passing an array in the second argument tells angular to create a new instance of the module with all the dependencies mentioned. If you do not have any dependencies you have to pass a empty array in order to create a new module.
By omitting this parameter you ask angular to retrieve the existing module. And, in your code you do not have a module previously named phoneList. That is why it is giving you the error.

Related

Angular Underscore Cannot read property 'find' of undefined

I'm trying to return the object with a specific "ID" from the json service. I can see the objects in my console log but any attempt to iterate or use underscore _find gives me "undefined"
var metaresult = _.find($scope.results.results, function(rw){ return rw.id == $scope.answer1 });
gives me this error:
TypeError: Cannot read property 'find' of undefined
at k.$scope.metaResult (https://evening-taiga-2443.herokuapp.com/js/controllers/MainController.js:173:21)
Here is my factory:
app.factory('results', ['$http', function($http) {
return $http.get('js/services/results.json')
.success(function(data) {
return data;
})
.error(function(err) {
return err;
});
}]);
any my json structure:
{
"results": [
{
"id": "a"
},
.... and so on
EDIT: So the issue seems to be dependency. I tried using ng-underscore instead and I'm loading as follows:
<script src="js/ng-underscore.min.js"></script>
then the app.js
var app = angular.module("quizApp", ['720kb.socialshare', 'ngUnderscore']);
Then in my controller
app.controller('MainController', ['$scope', 'quiz', 'results', function($scope, quiz, results, underscore)
typing "underscore" into console gives me:
Uncaught ReferenceError: underscore is not defined
EDIT: Figured it out just need to use lodash
var metaresult = _.find( ...
TypeError: Cannot read property 'find' of undefined
This error means that javascript didn't know what is _. _ is undefined and when you do _.find then error is generated. It seems you're not loading libraries properly. Kindly make sure you have added the underscore js module. Once underscore is loaded, _ will reference to the js module and you will be able to use all the methods.
Once get the libs to load correctly, it should be:
var metaresult = _.findWhere($scope.results.results, { id: $scope.answer1.id });
http://underscorejs.org/#findWhere
_ would be referring to either lodash or underscore which are both javascript utility libraries. I would suggest that you take a look at bower which is a package manager for front end libraries and make sure that you both have the necessary files in your project and also that they are being referenced in your HTML.
I would personally recommend that you use lodash instead of underscore as it is essentially a drop in replacement and offers performance benefits. That being said, there is absolutely no reason to use an angular module wrapper in based on the code that you've shown here. Simply downloading lodash and including it in your HTML will make it available for use inside your controller without having to worry about any module dependencies or controller injection.

'ShouldWorkController' is not a function. Got undefined

When I try to bind a controller to a template using the angular-ui-router $stateProvider, I run into the following error:
'ShouldWorkController' is not a function. Got undefined.
However, when I declare the controller inside the template using ng-controller, everything works fine. What could be wrong here?
app.ts
module App {
var dependencies = [
MyControllers
]
function configuration($stateProvider: ng.ui.IStateProvider) {
$stateProvider
.state("shouldWork", {
url: "/shouldWork",
templateUrl: "app/shouldWork.html"
controller: "ShouldWorkController" // does not work
});
}
}
shouldWorkController.ts
module App.MyControllers {
interface IShouldWorkViewModel {
}
class ShouldWorkController implements IShouldWorkViewModel {}
}
ShouldWork.html
<div ng-controller="ShouldWorkController as viewModel" us-spinner spinner-key="spinner-1">
^ --- this works nicely
That message means, that such controller "ShouldWorkController" is not loaded int he main angular module. Be sure that you do call register at the end:
module App.MyControllers {
...
class ShouldWorkController implements IShouldWorkViewModel {}
}
// we have to register this controller into some module (MyControllers)
// which is also referenced in the main app module
angular.module('MyControllers')
.controller('ShouldWorkController', App.MyControllers.ShouldWorkController );
I realise this is old, but I came here via Google with the same issue, not for the firs time. Things to check include:
Export statement for your controller class. From the code you posted I see that you are missing an export statement for your ShouldWorkController class. This may not be the issue in your case, but it is something you should check. I can reproduce this error by removing the export statement from my controller classes.
Check your HTML template exists (if using UI-Router). As described in the UI-Router documentation: "The controller will not be instantiated if template is not defined."
Register your controllers in the same file as the controller. Some tutorials do demonstrate controllers being registered in the module file. While this does work, I personally have found it more error prone than directly registering the controller within the controller file.
Check your typescript references. Make sure that you add typescript references (e.g. ///<reference path="../app/services/shouldWorkService.ts">) to typescript files that contain any types that you reference
Check the name of your controller matches that declared in your $stateProvider configuration.

Override dependency object prototype in angularjs

I have a set of angular $resource defined in a module called 'App.API' in a single file which I cannot touch because it is generated. (With loopback-angular, a tool to generate angular $resource from server side model definitions)
Let's take the Product dependency as en example, later in the app, I want to override its prototype, like this :
module('App.NewModule', ['App.API']).run(['Product', function(Product) {
Product.prototype.getTitle = function() {
return 'Product name is ' + this.name;
};
// From now on I can use p.getTitle() on every Product $resource
});
It works.
The thing is, I have many different files, each containing modules, and I am experiencing a dependency injection issue : I can access the getTitle function inside NewModule, but not inside other modules.
Question : How can I override a dependency object prototype and make it available to other modules ?
I tried to define the prototype functions in this way instead, thinking that Product prototype would be modified. Maybe not early enough :
module('App.API').run(['Product', function(Product) {
Product.prototype.getTitle = function() {
return 'Product name is ' + this.name;
};
});
It does not work : using getTitle in another module (using App.API/Product as a dependency) on a Product instance still throws a undefined is not a function error, even while Product object is correctly injected.
Actually, I just messed up the dependency definitions / orders.
I have three files :
app.js for module App (dependant on module App.API)
api.js for module App.API
product.js containing Product prototype
As stated in the question, I was doing :
// in product.js
module('App.API').run(['Product', function(Product) { ... }]);
// in app.js
var appModule = module('App', ['App.API']);
But the App.API module was defined in another file, which is a bit messed up because you never know for sure which one will load first, unless dealing with in in the js loader and loosing parallel downloads.
So I explicitly specified the modules and dependencies, at the expense of adding more dependency to declare in my app (but it works and is more stable) :
// in product.js
module('ApiProduct', ['App.API']).run(['Product', function(Product) { ... }]);
// in app.js
var appModule = module('App', ['App.API', 'ApiProduct']);
Note : In my first attempt, I defined the prototype in a new module in a .config() block, but it was not working, maybe because App.API services were not loaded yet. With .run() it works and my getTitle prototype is available everywhere I need Product provider.

AMD: what does 'dependencies' mean when its an object, not an array?

I have inherited some code with an AMD module looks like:
define('shared/modulename', {
load: function(name, parentRequire, callback, config) {...}
})
This doesn't resemble the normal AMD syntax of an array of dependencies as documented here. The code isn't commented, and there is no explanation of why the change in syntax is needed for this module.
What does this invocation of define() actually do?
Looking at the arguments given to the load() function, they seem to be AMD internals.
This is one of the simple forms of defining AMD modules. http://requirejs.org/docs/api.html#define
In RequireJS you can define name-value pairs in this simple format:
define({foo: 'yay'})
And you can specify the module name in define too, which you are required to when you combine your modules. So that makes our example to:
define('aloha', {foo: 'yay'})
Now back to your code. The meaning is shallow. It defines a module called shared/modulename.
The exports of that module is an Object, which contains a method called load.
You can use this module like this:
require('shared/modulename').load(name, parentRequire, callback, config)

Undefined object being passed via Requirejs

I'm using Requirejs to load the JavaScript in our web app. The issues is that I'm getting an undefined object being passed to a module which, when used in other modules, is instantiated perfectly fine.
OK, here's the setup. My main.js file which requirejs runs on startup:
require.config({
baseUrl: "/scripts",
paths: {
demographics: "Demographics/demographics",
complaints: "Complaints/complaints",
}
});
require(["templates", "demographics", "complaints", "crossDomain"], function (templates, demographics, complaints) {
"use strict";
console.log("0");
console.log(demographics === undefined);
demographics.View.display();
});
A lot of the config has been stripped to just the core files in this problem.
Here's Demographics.js:
define(["ko", "templates", "complaints", "globals", "underscore"], function (ko, templates, complaints, globals) {
// Stuff removed.
return {
View: view
};
});
and Complaints.js
define([
"demographics",
"ko",
"templates",
"complaints",
"visualeffects",
"globals",
"webservice",
"underscore",
"typewatcher",
"imagesloaded"],
function (demographics, ko, templates, complaints, visualeffects, globals, webservice) {
"use strict";
console.log("1");
console.log(demographics === undefined);
return {
View: view
};
});
The problem is this - in Complaints.js the demographics parameter passed via the define config is undefined. The console log out tells me that "demographics === undefined" is true.
However, when the main.js file executes, the demographics parameter passed to it is not undefined, it is, as expected, an instantiated object.
Now I'm stuck since I can't see why in complaints.js that demographics variable is undefined. Can anyone spot what I'm missing please?
You have a circular dependency. The demographics module depends on complaints and complaints depends on demographics. As per the documentation:
If you define a circular dependency (a needs b and b needs a), then in this case when b's module function is called, it will get an undefined value for a.
The solution, if you can't remove the circular dependency, is to asynchronously require one of the two modules within the other on demand (say when the view is instantiated instead of when the module that defines the view is executed). Again, the docs cover this topic fairly well.
Another case is when you accidentally type require instead of define when defining a module, took me some time to notice this.
I had a similar problem. In my case, when defining a module, I'd written:
define('some_dependency', ...
instead of
define(['some_dependency'], ...
Another possible reason is implementing the module's interface (AMD, CommonJS), but forgetting to return anything. I just did that.
I just encountered another reason:
define(function () {
return {};
}()); // <-- notice the '()' typo.
This "typo" causes no JS errors for this one and can make it confusing to figure out especially in a complicated application with many potential circular dependancies.
The reason, of course, is the "typo" is valid JS that simply calls the function you define thereby passing its result to define() rather then the function as intended.
One other possible reason that may look obvious in hindsight is an error in your module's code. In my case, I was trying to get an attribute from an undefined variable. The error is logged in the console, but for some reason I was not seeing it/mistaking it for the undefined module error.

Categories