AngularJS: Adding new routes dynamically - angularjs

As we use, $routeProvider in config method, as of my knowledge $route is a provider.
So, I tried adding new routes to $route in my controller:
After configuring and bootstrapping the application, somewhere in my controller, I tried this:
app.controller('MyCtrl',function($scope,$route) {
$route.routes['/newRoute'] = { template : 'hey, this is dynamically added route' };
});
But this doesn't seem to work. why?
Any Ideas?

you can only configure the routes via your ngapp config function only, so you can't just add routes dynamically in runtime.
also $route is a service.

Related

Why getting provider error when trying to inject resolved property in controller using ui-router?

I am unable to inject resolve property of ui-routing in controller.
It is giving
Error: $injector:unpr
Unknown Provider
When I'm using controller property in state definition object as following
.state('widget', {
url: '/widgets',
template: '<h1>{{name}}</h1>',
controller: function(widget, $scope) {
$scope.name = widget.name;
},
resolve: {
// standard resolve value promise definition
widget: function() {
return {
name: 'myWidget'
};
},
// resolve promise injects sibling promise
features: function(widget) {
return ['featureA', 'featureB'].map(function(feature) {
return widget.name+':'+feature;
});
}
}
});
Then it is working fine and I'm able to get the widget in controller and able to use in html.
Please see the fiddle for code.
http://jsfiddle.net/sunilmadaan07/ugsx6c1w/8/
Might be I'm making a silly mistake.
Before posting this question I have tried returning with simple object, promise object to the property.
Thanks In Advance.
You can not get resolved data in the directive with the code you did. Basically, you are trying to implement component based structure with an older version of angular 1.3.x.
You have two options to achieve this.
Create route controller then you can access resolve to the controller as local dependency then use that dependency as binding to the directive.
Here is example - http://plnkr.co/edit/TOPMLUXc7GhXTeYL0IFj?p=preview
Upgrade angular version to 1.5.x and use "ui-router-route-to-components": "^0.1.0"
Here working example of your code - http://jsfiddle.net/ugsx6c1w/25/
In order for the controller to be able to use resolvers, it should be route component (only in UI Router 1.x) or route controller.
widget and features are local dependencies, they aren't registered in the injector and aren't available anywhere in the application except route controller/component.
As explained here, resolvers can be passed to nested components in UI Router 0.3.x and injected directly to route components in 1.x.

Automatically instantiate AngularJS controller nested in templateUrl

I'm just learning Angular and have a very basic app set up. When rendering some data via the templateUrl property of a route, what would be the best way to include a sub-controller in the returned template? For example, including a "createOrEditItem" template at the bottom of a "viewItem" template so that the "createOrEditItem" can be reused on its own later?
I've tried putting a div in the template with its ng-controller attribute set to a controller name that I've defined at the app level, but it's not being activated. Should this be done with a directive instead to make it instantiate when the master controller has its contents set, or am I missing something more fundamental?
yes, as mentioned in the later part of the question, you should be using a directive. Or, if using AngularJS >= v1.5, component should be the choice because they are pluggable and works well with nesting too.
Note that for the route also, you can directly use a component like this:
var myMod = angular.module('myMod', ['ngRoute']);
myMod.component('home', {
template: '<h1>Home</h1><p>Hello, {{ $ctrl.user.name }} !</p>',
// ^^^^ other components can be used here
controller: function() {
this.user = {name: 'world'};
}
});
myMod.config(function($routeProvider) {
$routeProvider.when('/', {
template: '<home></home>'
});
});
Now, as the comment suggests, you can freely use other components in the template of home component.
Hope this helps a bit!
A directive can be used.
Another option is to use a seperate view/route. So when you add a ui-view tag, you could define your view and route.
This is explained here:
https://scotch.io/tutorials/angular-routing-using-ui-router

$transition$ not working when injected in a controller / ui-router 1.0.0-beta.3

in the official doc :
https://ui-router.github.io/docs/latest/modules/ng1.html , in the example :
MyController.$inject = ['$transition$'];
function MyController($transition$) {
var username = $transition$.params().username;
// .. do something with username
}
$transition$ is injected in the controller, but when I do the same with angular 1.6.1 and ui-router 1.0.0-beta.3 I have the follwing error, using a component architecture:
Error: [$injector:unpr] Unknown provider: $transition$Provider
I am able to inject $transition$ only in a resolve.
From the ui-router Route to Component guide:
When routing to a legacy style template/controller (not routing to
components), the transition could be injected as $transition$.
...
To access the Transition on a routed component, you should bind to
$transition$ in your component.
As you noted, therefore this can only be accessed via the resolve when routing to components. This is because the $transition$ service is a locally scoped injectable which is not available for components. More information can be found in issue ui-router#3110
You are trying to inject the '$transition$' object where you should be injecting the '$transitions' service into your controller. See the distinction in the documentation on this page:
https://ui-router.github.io/ng1/docs/latest/modules/injectables.html#transition
$transition$ isn't a global service, it's a locally scoped injectable.
https://github.com/angular-ui/ui-router/issues/3110
You can use component input bindings to address this:
.component('adminApplicants',{
bindings: { $transition$: '<' },
templateUrl:'admin.applicants.html',
controller:function($http,$transition$){
}
})

Dynamically load controller without templateURL and ngView

I don't want to use templateUrl, due to the way the app is currently structured.
I want to be able to dynamically load a controller into my ng-controller template.
I would think there would be a way to pass variable to ng-controller as you can see
I'm passing controller to ng-controller ignorantly hoping the name controller is assigned
to index_projects.
Routing
config = (http,route) ->
http.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content');
http.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest"
route_to = (path,controller)->
route.when path, {controller: controller}
route_to '/projects', 'index_projects'
Template
.projects_wrap{ ng:{controller:'controller'} }
%h2
%span All Projects
.light_button{ ng:{click: 'pop.new()'} }
%span.light_plus
Add Project
Look at this:
http://www.bennadel.com/blog/2441-Nested-Views-Routing-And-Deep-Linking-With-AngularJS.htm
I am successfully freed of using ngView with this article.

How to load language-specific templates in AngularJS?

I have a route defined as
$routeProvider.when('/:culture/:gameKey/:gameId/closed', { templateUrl: '/templates/tradingclosed', controller: TradingClosedCtrl });
I would like angular to include the "culture" parameter when requesting the template somehow, so I can serve a translated template.
Is this possible?
If I'm reading this correctly you'd like to somehow use the culture parameter from the url route to determine which location to retrieve your template.
There may be a better way but this post describes retrieving the $routeParams inside a centralized controller with ng-include to dynamically load a view.
Something similar to this:
angular.module('myApp', []).
config(function ($routeProvider) {
$routeProvider.when('/:culture/:gameKey/:gameId/closed', {
templateUrl: '/templates/nav/urlRouter.html',
controller: 'RouteController'
});
});
function RouteController($scope, $routeParams) {
$scope.templateUrl = 'templates/tradingclosed/' + $routeParams.culture + '_template.html';
}
With this as your urlRouter.html:
<div ng-include src="templateUrl"></div>
You can define the controller you want to load in your views using ng-controller and access the $routeParams for the additional route parameters:
<div ng-controller="TradingClosedCtrl">
</div>
I've posted similar question with working Plnkr example of solution like #Gloopy suggested.
The reason why you can't implement that without ng-include is that routing is done in 'configuration' block, where you can't inject any values (you can read about these blocks in Modules documentation, section Module Loading & Dependencies
If you want not to introduce new scope, you can replace ng-include with my stripped version of ng-include directive, that do absolutely same that ng-include does, but do not create new scope: source of rawInclude directive
Hope that solution will satisfy your use case.

Resources