Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 419 Vote(s) - 3.5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
AngularJS dynamic routing

#1
I currently have an AngularJS application with routing built in.
It works and everything is ok.

My app.js file looks like this:

angular.module('myapp', ['myapp.filters', 'myapp.services', 'myapp.directives']).
config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/', { templateUrl: '/pages/home.html', controller: HomeController });
$routeProvider.when('/about', { templateUrl: '/pages/about.html', controller: AboutController });
$routeProvider.when('/privacy', { templateUrl: '/pages/privacy.html', controller: AboutController });
$routeProvider.when('/terms', { templateUrl: '/pages/terms.html', controller: AboutController });
$routeProvider.otherwise({ redirectTo: '/' });
}]);

My app has a CMS built in where you can copy and add new html files within the **/pages** directory.

I would like to still go through the routing provider though even for the new dynamically added files.

In an ideal world the routing pattern would be:

$routeProvider.when('/**pagename**', { templateUrl: '/pages/**pagename**.html', controller: CMSController });

So if my new page name was "contact.html" I would like angular to pick up "/contact" and redirect to "/pages/contact.html".

Is this even possible?! and if so how?!

**Update**

I now have this in my routing config:

$routeProvider.when('/page/:name', { templateUrl: '/pages/home.html', controller: CMSController })

and in my CMSController:

function CMSController($scope, $route, $routeParams) {
$route.current.templateUrl = '/pages/' + $routeParams.name + ".html";
alert($route.current.templateUrl);
}
CMSController.$inject = ['$scope', '$route', '$routeParams'];

This sets the current templateUrl to the right value.

*However* I would now like to change the *ng-view* with the new templateUrl value. How is this accomplished?
Reply

#2
In the $routeProvider URI patters, you can specify variable parameters, like so: `$routeProvider.when('/page/:pageNumber' ...` , and access it in your controller via $routeParams.

There is a good example at the end of the $route page: [

[To see links please register here]

.$route][1]

**EDIT (for the edited question):**

The routing system is unfortunately very limited - there is a lot of discussion on this topic, and some solutions have been proposed, namely via creating multiple named views, etc.. But right now, the ngView directive serves only ONE view per route, on a one-to-one basis. You can go about this in multiple ways - the simpler one would be to use the view's template as a loader, with a `<ng-include src="myTemplateUrl"></ng-include>` tag in it ($scope.myTemplateUrl would be created in the controller).

I use a more complex (but cleaner, for larger and more complicated problems) solution, basically skipping the $route service altogether, that is detailed here:

[

[To see links please register here]

][2]


[1]:

[To see links please register here]

.$route
[2]:

[To see links please register here]

Reply

#3
I think the easiest way to do such thing is to resolve the routes later, you could ask the routes via json, for example. Check out that I make a factory out of the $routeProvider during config phase, via $provide, so I can keep using the $routeProvider object in the run phase, and even in controllers.

'use strict';

angular.module('myapp', []).config(function($provide, $routeProvider) {
$provide.factory('$routeProvider', function () {
return $routeProvider;
});
}).run(function($routeProvider, $http) {
$routeProvider.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
}).otherwise({
redirectTo: '/'
});

$http.get('/dynamic-routes.json').success(function(data) {
$routeProvider.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
});
// you might need to call $route.reload() if the route changed
$route.reload();
});
});
Reply

#4
Not sure why this works but dynamic (or wildcard if you prefer) routes are possible in angular 1.2.0-rc.2...

[To see links please register here]

[To see links please register here]


angular.module('yadda', [
'ngRoute'
]).

config(function ($routeProvider, $locationProvider) {
$routeProvider.
when('/:a', {
template: '<div ng-include="templateUrl">Loading...</div>',
controller: 'DynamicController'
}).


controller('DynamicController', function ($scope, $routeParams) {
console.log($routeParams);
$scope.templateUrl = 'partials/' + $routeParams.a;
}).

example.com/foo -> loads "foo" partial

example.com/bar-> loads "bar" partial

No need for any adjustments in the ng-view. The '/:a' case is the only variable I have found that will acheive this.. '/:foo' does not work unless your partials are all foo1, foo2, etc... '/:a' works with any partial name.


All values fire the dynamic controller - so there is no "otherwise" but, I think it is what you're looking for in a dynamic or wildcard routing scenario..
Reply

#5
Ok solved it.

**Added the solution to GitHub** -

[To see links please register here]


In my app.js routing config:

$routeProvider.when('/pages/:name', {
templateUrl: '/pages/home.html',
controller: CMSController
});

Then in my CMS controller:

function CMSController($scope, $route, $routeParams) {

$route.current.templateUrl = '/pages/' + $routeParams.name + ".html";

$.get($route.current.templateUrl, function (data) {
$scope.$apply(function () {
$('#views').html($compile(data)($scope));
});
});
...
}
CMSController.$inject = ['$scope', '$route', '$routeParams'];

With #views being my `<div id="views" ng-view></div>`

**So now it works with standard routing and dynamic routing.**

To test it I copied about.html called it portfolio.html, changed some of it's contents and entered `/#/pages/portfolio` into my browser and hey presto portfolio.html was displayed....

***Updated***
*Added $apply and $compile to the html so that dynamic content can be injected.*
Reply

#6
angular.module('myapp', ['myapp.filters', 'myapp.services', 'myapp.directives']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/page/:name*', {
templateUrl: function(urlattr){
return '/pages/' + urlattr.name + '.html';
},
controller: 'CMSController'
});
}
]);

- Adding * let you work with ***multiple levels of directories*** dynamically.
Example: ***/page/cars/selling/list*** will be catch on this provider

From the docs (1.3.0):

> "If templateUrl is a function, it will be called with the following
> parameters:
>
> {Array.<Object>} - route parameters extracted from the current
> $location.path() by applying the current route"

Also
> when(path, route) : Method
>
> - path can contain named groups starting with a colon and ending with a star: e.g.:name*. All characters are eagerly stored in $routeParams under the given name when the route matches.
Reply

#7
Here is another solution that works good.

(function() {
'use strict';

angular.module('cms').config(route);
route.$inject = ['$routeProvider'];

function route($routeProvider) {

$routeProvider
.when('/:section', {
templateUrl: buildPath
})
.when('/:section/:page', {
templateUrl: buildPath
})
.when('/:section/:page/:task', {
templateUrl: buildPath
});



}

function buildPath(path) {

var layout = 'layout';

angular.forEach(path, function(value) {

value = value.charAt(0).toUpperCase() + value.substring(1);
layout += value;

});

layout += '.tpl';

return 'client/app/layouts/' + layout;

}

})();

Reply

#8
As of AngularJS 1.1.3, you can now do exactly what you want using the new catch-all parameter.

[To see links please register here]


From the commit:
> This allows routeProvider to accept parameters that matches
substrings even when they contain slashes if they are prefixed
with an asterisk instead of a colon.
For example, routes like `edit/color/:color/largecode/*largecode`
will match with something like this
`http://appdomain.com/edit/color/brown/largecode/code/with/slashs`.

I have tested it out myself (using 1.1.5) and it works great. Just keep in mind that each new URL will reload your controller, so to keep any kind of state, you may need to use a custom service.
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through