ui-router: A route with no view template

All we need is an easy explanation of the problem, so here it is.

Is it possible to setup a route in ui-router that only has a controller? The purpose being that at a certain URL, the only thing I’d like to do is take action programatically, and not display anything in terms of a view. I’ve read through the docs, but I’m not sure if they offer a way to do this.

Yes, I have read this: https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-open-a-dialogmodal-at-a-certain-state, but that is not quite what I am looking for.

For example, let’s just say I have a basic body with view:

<body ui-view></body>

And some basic config:

// Routes
$stateProvider
  .state('myaction', {
    url: "/go/myaction",
    onEnter: function() {
      console.log('doing something');
    }
  });

When /go/myaction is visited, the view is blank. Is it possible to do this?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

I was able to solve this problem by redirecting the headless state I was taking programmatic action in, to a state WITH a view at the end of the headless state:

$stateProvider
  .state('myaction', {
    url: "/go/myaction",
    onEnter: function() {
      console.log('doing something');
    }
    controller: function($state) {
      $state.go('home');
    }
  });

Method 2

You can’t have a controller without a view but you can use onEnter instead of a controller. If you don’t want to change the current view when accessing this state you can define it as a child state:

$stateProvider

   // the parent state with a template
   .state('home', {
      url: '/home',
      templateUrl: '/home.html',
      controller: 'HomeCtrl'
   })

   // child of the 'home' state with no view
   .state('home.action', {
      url: '/action',
      onEnter: function() {
         alert('Hi');
      },
   });

Now in home.html you can do something like this:

<a href ui-sref=".action">Greet me!</a>

Method 3

From the docs:

Warning: The controller will not be instantiated if template is not defined.

Why don’t you use an empty string as a template to overcome this?

Method 4

Yes, you can do that. Use absolute view names to re-use the <ui-view> of another state.

Take a look at this example:

Users go to my app, but depending on them being authenticated or not, I want to send them to a public or private page. I use the index state purely to see if they’re logged in or not, and then redirect them to index.private or index.public.

The child states make use of absolute view names to use the <ui-view> element that corresponds to the index state. This way, I don’t need to make a second nested <ui-view>.

$stateProvider.state('index', {
  url: "/",
  controller: 'IndexCtrl'
}).state('index.private', {
  views: {
    "@": {
      templateUrl: 'private.html',
      controller: 'PrivateCtrl'
    }
  }
}).state('index.public', {
  views: {
    "@": {
      templateUrl: 'public.html',
      controller: 'PublicCtrl'
    }
  }
});

A small note on this example: I’m using the @ shortcut here. Normally you would use [email protected].

Method 5

My solution for this was just to include a template (html file) that is blank.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply