Defining controllers using ui-router - angularjs

I am creating web application using Angular js in ES6. I just started learning angular. I have following questions which I couldn't understand much from resources in internet.
1) I am using ui-router for routing based on states. I have following code in my controller
myApp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home);
$stateProvider
.state('contact', {
url: '/contact',
templateUrl: 'contact.html',
controller: myContactController
});
};
Contact.html:
<div ng-controller=”myContactController”>
….
</div>
Question:
a) I have specified the controller in my state in js. Should I need to specify the controller using ng-controller in my view also? What is the difference and why its necessary ?
2) I have a base module for my app.
Base module - Index.js :
import subapp1 from ‘./subApp1/index’;
angular.module(“myapp”,[subapp1]);
subApp1/index.js
Export default function(){
Angular. module(“subApp1”,[]);
};
Question:
a) Is this the right way of injecting sub module dependency in to base module?If not which is the best way to inject module dependency in to base module?
b) I would appreciate if I can get best links to understand dependency injection and different scopes in angular js in basic way.

I have specified the controller in my state in js. Should I need to specify the controller using ng-controller in my view also? What is the difference and why its necessary ?
You don't need to use ngController in HTML. Router will fetch HTML template and compile it with specified controller.
I have a base module for my app...
You specify dependent module by its name, so your setup could look like this (note, how you export name property of the Angular module):
export default angular.module('subApp1', [])
.factory('someService', semeService) // For example, attach some module service
.directive('someDirective', someDirective) // ... or some components
.name;
and then
import subapp1 from './subApp1/index';
import subapp2 from './subApp2/index';
angular.module('myapp', [
subapp1,
subapp2
]);

1.a) no, you shouldn't. If you do, you'll have two instances of the controller
2.a) no. First you don't "inject" a module into another module: a module depends on another one, that's all. That has nothing to do with dependency injection. And the syntax for that is
angular.module('myapp', ['subApp1']);
I.e. the elements of the array must be names of module you depend on. And of course, these modules must themselves be defined (before or after, it doesn't matter), using
angular.module('subApp1', []);
2.b) https://docs.angularjs.org/guide

Related

What is the best way to import a component from another module, in AngularJS?

I have 2 sub-modules in my AngularJS (v1.7) app, let's call them A and B. I'm trying to import a component (with html template and controller) from module B (componentB), to be used inside the template of a component in module A (componentA).
After reading Reuse AngularJS Component in another Module (Dependency Injection), I first tried to do this by specifying componentB as a dependency of componentA and then using it inside componentA's template.
componentA.js
angular.module('A', ['componentB']).component('componentA', {...});
componentA.html
<div>
<componentB></componentB>
</div>
Unfortunately this did not work, even though componentB is correctly defined and being successfully used in module B. I also tried to specify module B as a dependency of module A, by modifying app.js as shown below:
angular.module('A', ['B'])
.config(...
In both cases, I'm getting an
Uncaught Error: [$injector:modulerr]
I'm having a hard time finding similar questions/articles that relate to AngularJS as opposed to the newer Angular. I'm also pretty rusty with AngularJS so any help would be appreciated, thanks in advance.
It is pretty straight forward:
angular.module("moduleB",[])
.component("componentB", {
template: "<div>This is Component B from Module B</div>"
});
angular.module("moduleA",["moduleB"])
<div ng-app="moduleA">
<component-b></component-b>
</div>
The moduleA imports components from moduleB by declaring moduleB as a dependency.
Module Creation vs Retrieval
Only the first module declaration should have dependencies specified.
ERRONEOUS
angular.module('moduleA', [])
.controller('ctrl', /* ... */)
angular.module('moduleA', ['moduleB'])
.service('serviceA', /* ... */)
Declaring dependencies again will cause the controller to be unregistered.
Better
angular.module('moduleA', ['moduleB'])
angular.module('moduleA')
.controller('ctrl', /* ... */)
angular.module('moduleA')
.service('serviceA', /* ... */)
For more information, see
AngularJS Developer Guide - Module Creation vs Retrieval
AngularJS angular.module API Reference

how do i add angular-moment filter here?

Am new to angularjs and given a codebase to add angular-moment (moments.js) to a module.
The module is defined is as follows:
angular.module("xyz", ["ngRoute",
"ui.bootstrap",
"infinite-scroll",
"uiGmapgoogle-maps",
"googlechart"],
function($interpolateProvider) {
$interpolateProvider.startSymbol("[[");
$interpolateProvider.endSymbol("]]");
})
.factory("principal", principal)
.factory("authorization", authorization)
.factory("pingService", abc)
When i add angularMoment just after "googlechart" i get a "unpr" angular error. I did include both moments.js and angular-moments.js in my html.
I need to use javascript moments lib in my angular code.
Please help.
thanks
You haven't included 'angularMoment' in your module as dependency.
Do like following :
angular.module("xyz", ["ngRoute",
"ui.bootstrap",
"infinite-scroll",
"uiGmapgoogle-maps",
"googlechart","angularMoment"],
function($interpolateProvider) {
$interpolateProvider.startSymbol("[[");
$interpolateProvider.endSymbol("]]");
})
.factory("principal", principal)
.factory("authorization", authorization)
.factory("pingService", abc)
And make sure , you have included the angular-moment.js file in your index.html
I hope this helps. Do let me know in case of any query
You don't need to add any directive to use momentjs in your project, reference it just like any other script in your SPA main page an use it on any controler.
The only benefit of loading it via a directive is having it declared as a dependence, and the possibility of mocking it for tests, if you don't care about this, just use it as you would do without Angular.

Resolve objects not available in $injector

I have a route definition as follows:
.state('user_login', {
url: '/user/login',
templateUrl: 'login.tpl.html',
controller: 'AuthenticationCtrl',
resolve: {
practice: ['$q', function($q) {
return $q.when({});
}]
}
})
Things work as expected when I inject "practice" into the controller. When I use the $injector, service however:
$injector.get('practice')
I get an unknown provider exception. Are resolve objects not available to the $injector? How I can expose them in the controller without explicitly injecting them in the controller definition?
Note: I am using Angular 1.2.x
No, you cannot get them separately via $injector. And you cannot even inject them separately as well in other places, say the same controller (AuthenticationCtrl) instantiated by ng-controller directive.
Resolve objects are not any service or any other entity which can be injected separately. It is a special dependency injected by the router when the controller AuthenticationCtrl is bound via the router. You cannot get the instances separately. Only router knows about the resolve properties and while the router instantiates the controller (once all the resolve dependencies are resolved) it looks for resolve properties in the annotation (of the dependency list specified via explicit/implicit dependency annotation in the definision of AuthenticationCtrl) of the route-bound controller and injects them as required.
This kind of special implementation can be found in other components as well like, angular-ui-modal, ui-state-router, angular-router's routeprovider etc..

registerModule with dependencies

I'm building an app with MEAN.JS and I'm trying to use a controller from another module. I've found that I can do this with dependency injection:
angular.module(‘MyModule’, [‘Dependency’]);
But the way modules are created in MEAN.JS is:
ApplicationConfiguration.registerModule('MyModule');
And I can't just pass a second parameter to registerModule. So, how should I do this? Do I have to use both methods? Am I doing it wrong?
Example
I want to add a new model: Campaign. Campaigns are created by admins only, but can be seen by the "campaign owner" (another User). The create campaign form should list available Users, so the admin can select the one that's going to be the "owner" of that Campaign.
The problem is, the create campaign form is controlled by CampaignsController, how can I list Users? I've used another controller (UsersController) and thats the problem, it is undefined because we are in the Campaign module.
EDIT:
The problem was grunt autorestarting the app incorrectly:
I moved the controller from one module (folder) to another, but grunt was still trying to load it from the old path, and thus failing: Controller not found. I thought the problem was dependency injection, but you only have to close grunt (Ctrl+C) and run it again. Problem solved.
Anyways, thanks for the answer #gilBirman cause it is correct: there is no need to inject anything with MEANJS.
MEAN.js makes all the modules registered via registerModule available to all other modules in your app by adding it as a dependency to the main app called mean. Here's the part of the MEAN.js source code that does this:
var applicationModuleName = 'mean';
....
// Add a new vertical module
var registerModule = function(moduleName) {
// Create angular module
angular.module(moduleName, []);
// Add the module to the AngularJS configuration file
angular.module(applicationModuleName).requires.push(moduleName);
};
So you're on the right track, however it sounds like you are trying to inject a controller. However, in angular, controllers are not injectable. You can inject services, factories, values, and constants.
First create your own module for example:
angular.module('app.controllers', []) - angular module with controllers.
then add controller to that module:
angular.module('app.controllers', [])
.controller('dashboard.admin.account.controller', ['$scope', ($scope) { .... }]);
then create global module which will bind to your markup:
angular.module('app', [
'app.controllers'
'ui.router',
'ngAnimate'
]);
then bootstrap your global module to markup:
domReady(function () {
angular.bootstrap(document, ['app']);
});
Now you can use your controller.

How to create a directive to be used in any module?

How can I create a directive without linking it to a specific module which can be used in any module, such as the build-in directives.
A directive or service has to belong to a module. What you can do is create separate modules for your directives and then inject them into your main application module. Here's my set up:
window.app = angular.module('app', ['ngRoute', 'app.system', 'app.animations', 'app.cart']);
angular.module('app.system', []);
angular.module('app.animations', []);
angular.module('app.cart', []);
Now your Service can be in its own module and called from within the app module. This is essentially what Ajay said.
angular.module('app.cart').factory("Cart", ['$resource', function($resource) {}]);
Short answer: no, it is not possible. All directives must be part of a module.
The Angular docs say
Much like controllers, directives are registered on modules. To register a directive, you use the module.directive API. module.directive
There isn't a way to define a directive outside of a module.
The Angular built-in directives themseves are defined on a module called ng - see the source code.
This module is created using the Angular internal method setUpModuleLoader (see AngularPublic.js and loader.js).
This function is not part of the Angular public API, so you can't access it yourself. You need to define your directives in your own module. Any app module which depends on this module will be able to use your directives.
It's a very Angular way of looking at things - avoid public objects, but make things injectable wherever possible.
I think I understand what the OP means. Similar to libraries like Angular UI for Bootstrap. The OP would like to create directives, etc. that can be used in other apps without having to know the main app name.
You can do this like so:
angular.module("hello.world", [])
.directive('hello', function() {
return {
template: '<p>Hello, world!</p>',
restrict: 'E',
link: function (scope, element, attrs) {}
};
});
Saved as 'hello-world.js' for example.
Make sure you include that JS in your page. Then inside your main Angular app:
var app = angular.module("myApp", ['hello.world']);
Then anywhere in your HTML under the app scope, you can insert:
<hello></hello>
And that directive will take over rendering a paragraph tag with the words "Hello, world!" within.
My understanding is that you can do this with all Angular objects - services, factories, providers, etc.
If I m not mistaken even the built-in directives belong to a module (ng module). It just that you don't have to explicitly declare a dependency on it as it is done by the framework for you. That's why you will always have to declare a module, add directive(s) to this module and depend of this module in other modules. Something like that :
// Reusable module with directive(s)
angular.module('directives', [])
.directive('rating', function () {
...
}
// other module that rely on teh first one
angular.module('MyApp', [
'directives',
...
]);
//Module 2
angular.module('MyModuleWithDependency', [
'directives'
]);

Resources