5

Is there a way to have an optional attribute at the beginning of the url in ui-router? If so, how?

I want to achieve sth like this:

.state('events',{
    url: '(/city:)?/events/:id'
    ...
})

So "city" would be optional.

Thank you for any input whatsoever.

3 Answers 3

7

It's probably bad practice to have two separate routes point to the same state, but nothing is keeping you from creating two different states that use the same resolutions/controller/template.

$stateProvider
.state('state1', {
  url: "/:city/events/:id",
  templateUrl: "partials/events.html",
  controller: eventsCtrl
})
.state('state2', {
  url: "/events/:id",
  templateUrl: "partials/events.html",
  controller: eventsCtrl
});

function eventsCtrl($scope){
  // shared controller
}

Again, this is probably bad practice but I can't think of a better solution

Sign up to request clarification or add additional context in comments.

1 Comment

Yeah that is why I am asking this question, cause I want to avoid this... But yeah fair point. If no one knows better solution I guess this is the way to go.
7
+50

I tried to answer the similar (if not same) here:

Angular js - route-ui add default parmeter

There is a working plunker, solving the issue for a language instead of for a city (but the concept is the same)

so, we would/should introduce some super state 'root'.

In our case, we can even use some regex to limit allowed values - because it would be hard to guess what is city and what is events

.state('root', {
    url: '/{city:(?:Prague|Bristol|Denver)}',
    abstract: true,
    template: '<div ui-view=""></div>',
    params: {lang : { squash : true, value: 'Prague' }}
})

What is important here is the setting params : {}. It says, that the default value is 'Prague' - so that would be the city if none is selected. What is also important - it should be squashed, skipped if there is a match with 'Prague' param value:

params: {lang : { squash : true, value: 'Prague' }}

Now, we can introduce some nested state(s) which would declare 'root' as their parent:

.state('events',{
    parent: 'root',
    url: '/events/:id'
    ...
})

Check the working example (with a language instead of city) here. For more details see the original Q & A

Comments

3

I see no reason why you wan't do it in a standard ui-router state setup.

DEMO

JAVASCRIPT

angular.module('app', ['ui.router'])

  .config(function($stateProvider, $urlRouterProvider) {

    $stateProvider

      .state('state1', {
        url: ':city/events/:id',
        templateUrl: 'partials/events.html',
        controller: 'EventsController'
      })

      .state('state2', {
        url: ':abc/cities/:x/:y',
        templateUrl: 'partials/cities.html',
        controller: 'CitiesController'
      });

  })

  .controller('EventsController', function($scope, $stateParams) {

    angular.extend($scope, $stateParams);

  })

  .controller('CitiesController', function($scope, $stateParams) {

    angular.extend($scope, $stateParams);

  });

2 Comments

Does it support www.xyz.com/abc/cities/y/z and also www.xyz.com/cities/y/z?. I don't think it does...
Of course it does, check the demo again, I added a new state definition.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.