Learning Angular. Working with 1.6.6.
Trying to use ui.router, running into an issue with injecting components.
I've been using the following as resources to structure my project:
AngularJS: Understanding design pattern
https://github.com/angular-app/angular-app
Both these resources suggest using module as a container for the code underneath them. For example from my own project:
angular.
module('randomTownGenerator.module', [
'randomTown.service',
'randomTown.controller'
]);
Each of those dependancies is defined in its own file. When I specify the above module as the component for the the route:
var randomTownGenerator = {
name: 'randomTownGenerator',
url: '/random-town',
component: 'randomTownGenerator.module'
}
I get:
Error: [$injector:unpr] Unknown provider: randomTownGenerator.moduleDirectiveProvider <- randomTownGenerator.moduleDirective
How can I pass the randomTownGenerator.module, which is just a wrapper around the service, template, and controller, to ui.router?
You have provided a module where it is expecting an angular component.
component: 'randomTownGenerator.module'
Here angular-ui-router is expecting a angular component to generate as the view for the state 'randomTownGenerator'. Please refer the angularjs documentation on how to create a component.
https://code.angularjs.org/1.6.6/docs/guide/component
You are trying to mixup the angularjs earlier version of injecting a module and new way of injecting module.
You should provide a component as a view with the later version so that will be loaded when it is required.
var States = {
"app": {
path: "",
routing: null,
definition: {
name: "app",
url: "",
onEnter: function () {
console.info("App state entered.");
},
params: {
//
},
resolve: {
//
},
views: {
"app#": {
component: "appComponent"
}
},
abstract: true
}
}
};
where component should be a component not a module. Here is a complete example of how to create states with ui-router and angularjs 1.6 version
Related
I've successfully replicated my issue with a fork of the "Hello Galaxy!" plunk embedded within the UI-Router tutorial page.
My plunk: https://plnkr.co/edit/2GqCtEJ4mhBIdJOFHy9c?p=preview
On the existing "Helo Galaxy!" plunk, I added the following module and route config:
// file: hello.js
// existing "Hello Galaxy!" hello module code above this ↑↑↑
// then my new module below...
angular.module('hello.product-management', ['ui.router']).config(function($stateProvider) {
// An array of state definitions
var states = [
{
name: 'product-management-template',
url: '/product-management-template',
// Using component: instead of template:
template: '<h1>Product Management</h1>'
},
{
name: 'product-management-component',
url: '/product-management-component',
// Using component: instead of template:
component: 'product-management'
},
]
// Loop over the state definitions and register them
states.forEach(function(state) {
$stateProvider.state(state);
});
});
The issue: You can click on the Product Management - Template tab to see the Product Management template, like so:
But you can't view the component template, using the Product Management - Component tab. It just shows an empty view:
I left the original "Hello Galaxy!" plunk's components and routes alone, and they still work fine:
In the state definition, use camelCase for the component name:
{
name: 'product-management-component',
url: '/product-management-component',
// Using component: instead of template:
̶c̶o̶m̶p̶o̶n̶e̶n̶t̶:̶ ̶'̶p̶r̶o̶d̶u̶c̶t̶-̶m̶a̶n̶a̶g̶e̶m̶e̶n̶t̶'̶
component: 'productManagement'
},
And define the component with camelCase:
̶a̶p̶p̶.̶c̶o̶m̶p̶o̶n̶e̶n̶t̶(̶'̶p̶r̶o̶d̶u̶c̶t̶-̶m̶a̶n̶a̶g̶e̶m̶e̶n̶t̶'̶,̶ ̶{̶
app.component('productManagement', {
template: '<h1>Product Management</h1>',
controller: function () {
console.log("product management component");
}
});
For more information, see AngularJS Developer Guide - Directive Normalization
I have an AngularJS 1.6 app that loads a list of app modules fetched from the server. Every app has a different list of modules, so it would mean a lot of overhead code to create one unique route per module.
We are using ui-router, and it provides a really cool route config method called componentProvider which allows us to dynamically load a component pages on (in our case) the $routeParams.
Here is the working Angular 1.6 code:
//...
.state('applications.apps.modules', {
url: '/:moduleSlug',
data: {
addToSideMenu: false,
},
// create a dynamic component
componentProvider: ($stateParams: StateParams) => {
// This outputs "application-<name of module>"
return `application${capitalizeFirstLetter(snakeToCamel($stateParams.moduleSlug))}`;
},
resolve: {
application: (applications, $stateParams: StateParams) => {
return applications.filter(app => app.slug === $stateParams.appSlug)[0];
},
},
})
//...
This code will return a string application-<name of module>, and it allows us to load that module dynamically.
We're trying to find a way to do the same thing in that app but in Angular 4.
Any idea?
Im using the angular.js 1.5.8 framework along with "oc.lazyload" library for lazy loading applications.
Now, i'm trying to load a "child" component from parent component (ie. lazy load the component "navigation" into the "main") but it doest work.
Main component:
angular.module('app', [
'ngRoute', 'oc.lazyLoad'
]).component('main', {
template: '<navigation></navigation>',
controller: function($ocLazyLoad: any) {
return $ocLazyLoad.load('ui/navigation.js');
}
})
)
Navigation.js:
angular.module('app').component('navigation', {
templateUrl: './ui/navigation.html'
});
When i look into the developer console it shows me that only the navigation.js file is loaded and not the template (navigation.html)
It does work when i'm using it with ngRouter resolve property however. Is there anything similar i could use for components?
Hello fellow stackoverflowers,
I've been trying for some time now without success to implement
lazy loading of angular components with the new component router (ngComponentRouter).
This is the code I used for the configuration of the main component:
//define main app component
app.value("$routerRootComponent","simpleTrackerApp");
//main app component config
var lazyLoaderMod = null;
var httpService = null;
app.component("simpleTrackerApp", {
/*#ngInject*/
controller:function ($ocLazyLoad,$http) {
lazyLoaderMod = $ocLazyLoad;
httpService = $http;
},
templateUrl: CONFIG_APP_SHARED_URL + 'mainComponent/simpleTrackerApp.html',
$routeConfig: [
{
useAsDefault:true,
path:"/bugs",
name:"Bugs",
loader: function () {
return lazyLoaderMod.load(CONFIG_APP_COMPONENTS_URL + 'bug/bugs/bugsCtrl.js');
}
},
{path:'/**',redirectTo:['Bugs']}
]
});
My first problem was I could'nt get it to work with ocLazyLoad injected in loader propety so I loaded it in the main controller and referenced it in the loader property.
After that when I finally got it working inside loader propety
I couldn't seem to get it to actually load the component I kept getting this error:
lib.js:2 TypeError: Cannot read property 'then' of undefined
at e._loader (http://simpletracker.co.il/client/production/app/lib.js:9:10670)
at e.resolveComponentType (http://simpletracker.co.il/client/production/app/lib.js:9:21463)
at e.recognize (http://simpletracker.co.il/client/production/app/lib.js:9:23535)
at http://simpletracker.co.il/client/production/app/lib.js:9:25949
at Array.forEach (native)
at e.recognize (http://simpletracker.co.il/client/production/app/lib.js:9:25921)
at e._recognize (http://simpletracker.co.il/client/production/app/lib.js:10:4834)
at e.recognize (http://simpletracker.co.il/client/production/app/lib.js:10:4605)
at t.e.recognize (http://simpletracker.co.il/client/production/app/lib.js:10:13656)
at http://simpletracker.co.il/client/production/app/lib.js:10:10757
Now I understand I'm obviously doing something wrong in the loader
and that I need to somehow register the component. but I couldn't find
any docs on angular for the loader and nobody else lazyloading components with the new router so I really couldn't figure how this could be achieved.
I'd really appreciate some help on this but I'm also wondering in general
if maybe it is premature to use angular component router
with its lack of documentation and support.
So I'd really like to hear from other expierenced angular programmers
their opinion on the matter.
Edit:Anyone have any insight on the matter?..
You could use $router instead of the http-service. Applied on your code:
app.component("simpleTrackerApp", {
templateUrl: 'mainComponent/simpleTrackerApp.html',
controller: ['$router', '$ocLazyLoad', function ($ocLazyLoad, $http) {
$router.config([
{
path: '/bugs/',
name: "Bugs",
loader: function () {
return $ocLazyLoad.load('/bugsFolder/bugs.component.js') //no url, set the path to your component
.then(function () {
return 'bugs' //name of your component
})
}
}
])
}],
});
And don't forget to inject your dependencies in the app.module.
I'm using angular 1.5 beta 2 and the new router from Angular 2 alpha 45.
I couldn't find examples of usage for the latest router with Angular 1.
I can find examples of the usage of the router for Angular 2, using #RouteConfig.
Can someone explain how I would configure an angular 1 controller? And, if possible, a full working example?
Update They have stopped working on this version of the Router and started a version 3 with different APIs. As of June 20, 2016 there was no recommended way for using the router v3 with Angular 1. I'm not sure if this has changed since. This question and answer below relates to Router v2 (aka ComponentRouter).
Obsolete API
A few sites indicate that a component in Angular 1 (for the purpose of the new router) is a controller registered as [name]Controller and a template picked up from component/[name]/[name].html. This is now obsolete.
New API
This discussion contains recent information, explaining how to get the latest Angular 1 new router version.
The component used in the configuration is mapped to a directive registered with the component name. See this sample.
angular.module('app.home', [])
.directive('home', function() {
return {
template: 'Hello {{ home.text }}',
controller: function HomeController() {
this.text = 'World';
},
controllerAs: 'home'
}
});
With Angular 1.5 there is a new syntax for registering components, see here. I've used it with this syntax:
angular.module('app.home', [])
.component('home', {
restrict: "EA",
template: 'Hello {{ home.text }}',
controller: function HomeController() {
this.text = 'World';
}
// to configure a child route
//,$routeConfig: [
// { aux: "/son", component: "son", as: "Left" },
// { aux: "/daughter", component: "daughter", as: "Left" }]
});
Although it is pretty new at this point you can also use a root component with the new angular router. This component could take additional components as children.
I followed Pete Bacon Darwin's example to get a version going.
https://github.com/petebacondarwin/ng1-component-router-demo
Notice in his version The main component has $router.config passed in the run block and identifies children with 3 dots.
.run(function($router) {
$router.config([
{ path: '/...', name: 'App', component: 'app', useAsDefault: true }
]);
I am using angular 1.5.0 to follow his github. I ran into issues playing with release some of the release candidates.