Dynamically set the value of ui-sref Angularjs

I have searched for a similar question but the ones that came up seem slightly different. I am trying to change the ui-sref='' of a link dynamically (this link points to the next section of a wizard form and the next section depends on the selection made on the dropdown list). I am simply trying to set the ui-sref attribute depending on some selection in a select box. I am able to change the ui-sref by binding to a scope attribute which is set when a selection is made. however the link does not work, is this possible at all? thanks

  <a ui-sref="form.{{url}}" >Next Section</a>

and then in my controller, I set the url parameter this way

switch (option) {
  case 'A': {
    $scope.url = 'sectionA';
  } break;
  case 'B': {
    $scope.url = 'sectionB';
  } break;
}

Alternatively, I used directives to get it to work by generating the hyperlink with the desired ui-sref attribute according to the option selected on the select box (drop down).

Hhowever this means I have to re-create the link each time a different option is selected from the selectbox which causes an undesirable flickering effect. My question is this, is it possible to change the value of the ui-sref as I tried doing above by simpling changing the value of url in my controller or do I have to re-create the entire element using a directive each time a selection is made as I have done below? (just showing this for completeness)

Select option directive (this directive generates the link directive)

define(['app/js/modules/app', 'app/js/directives/hyperLink'], function (app) {
app.directive('selectUsage', function ($compile) {

    function createLink(scope,element) {
        var newElm = angular.element('<hyper-link></hyper-link>');
        var el = $(element).find('.navLink');
        $(el).html(newElm);
        $compile(newElm)(scope);
    }

    return {

        restrict: 'E',
        templateUrl: '/Client/app/templates/directives/select.html'

        ,link: function (scope, element, attrs) {

            createLink(scope, element);

            element.on('change', function () {
                createLink(scope,element);
            })
        }
    }
})

Hyperlink directive

define(['app/js/modules/app'], function (app) {
app.directive('hyperLink', function () {

    return {
        restrict: 'E',
        templateUrl: '/Client/app/templates/directives/hyperLink.html',
        link: function (scope, element, attrs) { }
    }

})

Hyperlink template

<div>
    <button ui-sref="form.{url}}">Next Section</button>
</div>

Solution 1:

Looks like this is possible to do after all.

A breadcrumb on GitHub by one of the ui-router authors led me to try the following:

<a ng-href="{{getLinkUrl()}}">Dynamic Link</a>

Then, in your controller:

$scope.getLinkUrl = function(){
  return $state.href('state-name', {someParam: $scope.someValue});
};

Turns out, this works like a charm w/ changing scoped values and all. You can even make the 'state-name' string constant reference a scoped value and that will update the href in the view as well :-)

Solution 2:

There is a working plunker. The most easier way seems to be to use combination of:

  • $state.href() (doc here) and
  • ng-href (doc here)

These together could be used as:

<a ng-href="{{$state.href(myStateName, myParams)}}">

So, (following this plunker) having states like these:

$stateProvider
  .state('home', {
      url: "/home",
      ...
  })
  .state('parent', {
      url: "/parent?param",
      ...
  })
  .state('parent.child', { 
      url: "/child",
      ...

We can change these values to dynamically generate the href

<input ng-model="myStateName" />
<input ng-model="myParams.param" />

Check it in action here

ORIGINAL:

There is a working example how to achieve what we need. But not with dynamic ui-sref .

As we can can check here: https://github.com/angular-ui/ui-router/issues/395

Q: [A]re dynamic ui-sref attributes not supported?
A: Correct.

But we can use different feature of ui-router: [$state.go("statename")][5]

So, this could be the controller stuff:

$scope.items = [
  {label : 'first', url: 'first'},
  {label : 'second', url: 'second'},
  {label : 'third', url: 'third'},
];
$scope.selected = $scope.items[0];
$scope.gotoSelected = function(){
  $state.go("form." + $scope.selected.url);
};

And here is the HTML template:

<div>
  choose the url:
  <select
    ng-model="selected"
    ng-options="item.label for item in items"
  ></select>

  <pre>{{selected | json}}</pre>
  <br />
  go to selected
  <button ng-click="gotoSelected()">here</button>

  <hr />
  <div ui-view=""></div>
</div>

The working example

NOTE: there is more up to date link to $state.go definition, but the deprecated one is a bit more clear to me

Solution 3:

Take a look in this issue #2944.

The ui-sref doesn't watch the state expression, you can use ui-state and ui-state-params passing the variable.

  <a data-ui-state="selectedState.state" data-ui-state-params="{'myParam':aMyParam}">
       Link to page {{selectedState.name}} with myParam = {{aMyParam}}
  </a>

Also a quickly demo provided in the ticket.