web-dev-qa-db-fra.com

Définir dynamiquement la valeur de ui-sref Angularjs

J'ai cherché une question similaire, mais celles qui sont apparues semblent légèrement différentes . J'essaie de changer dynamiquement le ui-sref = '' d'un lien (ce lien pointe vers la section suivante d'un formulaire section suivante dépend de la sélection effectuée dans la liste déroulante). J'essaie simplement de définir l'attribut ui-sref en fonction d'une sélection dans une zone de sélection. Je suis capable de changer le ui-sref en me liant à un attribut de portée qui est défini quand une sélection est faite. Cependant, le lien ne fonctionne pas, est-ce possible? Merci

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

puis dans mon contrôleur, je règle le paramètre url de cette façon 

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

Alternativement, j'ai utilisé des directives pour le faire fonctionner en générant le lien hypertexte avec l'attribut ui-sref souhaité en fonction de l'option sélectionnée dans la zone de sélection (liste déroulante).

Toutefois, cela signifie que je dois recréer le lien chaque fois qu'une option différente est sélectionnée dans la zone de sélection, ce qui provoque un effet de scintillement indésirable. Ma question est la suivante: est-il possible de modifier la valeur de ui-sref comme j'ai essayé de le faire ci-dessus en simplifiant la modification de la valeur de l'url dans mon contrôleur le temps une sélection est faite comme je l'ai fait ci-dessous? (montrant juste ceci pour l'exhaustivité)

Sélectionnez la directive option (cette directive génère la directive link)

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);
            })
        }
    }
})

Directive sur les hyperliens

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) { }
    }

})

Modèle d'hyperlien

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

On dirait que c'est possible après tout.

Un fil d'Ariane sur GitHub par l'un des auteurs de ui-router m'a amené à essayer ce qui suit:

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

Ensuite, dans votre contrôleur:

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

En fin de compte, cela fonctionne comme un charme avec des valeurs changeantes, etc. Vous pouvez même faire en sorte que la constante de chaîne 'nom-d'état' fasse référence à une valeur étendue, ce qui mettra également à jour le href dans la vue :-)

65
RavenHursT

Il y a un plunker de travail . Le moyen le plus simple semble être d’utiliser une combinaison de:

  • $state.href() _ ​​(doc here ) et 
  • ng-href _ ​​(doc here )

Ces ensemble pourraient être utilisés comme:

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

Donc, (suite ce plunker ) ayant des états comme ceux-ci:

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

Nous pouvons changer ces valeurs pour générer dynamiquement le href

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

Vérifiez-le dans action ici

ORIGINAL:

Il existe un exemple de travail comment réaliser ce dont nous avons besoin. Mais pas avec ui-sref dynamique.

Comme nous pouvons le vérifier ici: https://github.com/angular-ui/ui-router/issues/395

Q: Les attributs dynamiques ui-sref non pris en charge?
A: correct.

Mais nous pouvons utiliser différentes fonctionnalités de ui-router: [$state.go("statename")][5]

Donc, cela pourrait être le truc du contrôleur:

$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);
};

Et voici le modèle HTML:

<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>

Le travail exemple

NOTE: il y a plus de mises à jour lien vers $ state.go definition, mais celui qui est obsolète est un peu plus clair pour moi

61
Radim Köhler

Jetez un coup d'oeil dans ce numéro # 2944 .

Le ui-sref ne regarde pas l'expression d'état, vous pouvez utiliser ui-state et ui-state-params en transmettant la variable.

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

Aussi un rapide démo fourni dans le billet.

21
Fabio Picheli

J'ai réussi à l'implémenter de cette façon (j'utilise cependant la variante controllerAs - pas via $ scope).

Modèle

<button ui-sref="main({ i18n: '{{ ctrlAs.locale }}' })">Home</button>

Manette

var vm = this;
vm.locale = 'en'; // or whatever dynamic value you prepare

Voir aussi la documentation sur ui-sref où vous pouvez passer des paramètres:

https://github.com/angular-ui/ui-router/wiki/Quick-Reference#ui-sref

2
codepushr

Après avoir essayé diverses solutions, j'ai trouvé le problème dans le code angular.ui.router.

Le problème provient du fait que la méthode ui.router update est déclenchée avec le ref.state, ce qui signifie qu'il n'est pas possible de mettre à jour la valeur de la href utilisée lorsque l'utilisateur clique sur l'élément.

Voici 2 solutions pour résoudre le problème:

Directive personnalisée

    module.directive('dynamicSref', function () {
    return {
        restrict: 'A',
        scope: {
            state: '@dynamicSref',
            params: '=?dynamicSrefParams'
        },
        link: function ($scope, $element) {
            var updateHref = function () {
                if ($scope.state) {
                    var href = $rootScope.$state.href($scope.state, $scope.params);
                    $element.attr('href', href);
                }
            };

            $scope.$watch('state', function (newValue, oldValue) {
                if (newValue !== oldValue) {
                    updateHref();
                }
            });

            $scope.$watch('params', function (newValue, oldValue) {
                if (newValue !== oldValue) {
                    updateHref();
                }
            });

            updateHref();
        }
    };
});

Le HTML à utiliser est assez simple: 

<a  dynamic-sref="home.mystate"
    dynamic-sref-params="{ param1 : scopeParam }">
    Link
</a>

Correction du code ui.router:

Dans angular.router.js, vous trouverez la directive $StateRefDirective (ligne 4238 pour la version 0.3).

Remplacez le code de la directive par:

function $StateRefDirective($state, $timeout) {
    return {
        restrict: 'A',
        require: ['?^uiSrefActive', '?^uiSrefActiveEq'],
        link: function (scope, element, attrs, uiSrefActive) {
            var ref = parseStateRef(attrs.uiSref, $state.current.name);
            var def = { state: ref.state, href: null, params: null };
            var type = getTypeInfo(element);
            var active = uiSrefActive[1] || uiSrefActive[0];
            var unlinkInfoFn = null;
            var hookFn;

            def.options = extend(defaultOpts(element, $state), attrs.uiSrefOpts ? scope.$eval(attrs.uiSrefOpts) : {});

            var update = function (val) {
                if (val) def.params = angular.copy(val);
                def.href = $state.href(ref.state, def.params, def.options);

                if (unlinkInfoFn) unlinkInfoFn();
                if (active) unlinkInfoFn = active.$$addStateInfo(ref.state, def.params);
                if (def.href !== null) attrs.$set(type.attr, def.href);
            };

            if (ref.paramExpr) {
                scope.$watch(ref.paramExpr, function (val) { if (val !== def.params) update(val); }, true);
                def.params = angular.copy(scope.$eval(ref.paramExpr));
            }

            // START CUSTOM CODE : Ability to have a 2 way binding on ui-sref directive
            if (typeof attrs.uiSrefDynamic !== "undefined") {
                attrs.$observe('uiSref', function (val) {
                    update(val);

                    if (val) {
                        var state = val.split('(')[0];
                        def.state = state;

                        $(element).attr('href', $state.href(def.state, def.params, def.options));
                    }
                });
            }
            // END OF CUSTOM CODE

            update();

            if (!type.clickable) return;
            hookFn = clickHook(element, $state, $timeout, type, function () { return def; });
            element.bind("click", hookFn);
            scope.$on('$destroy', function () {
                element.unbind("click", hookFn);
            });
        }
    };
}
2
Linvi

La meilleure approche consiste à utiliser la fonction uiRouter's $state.go('stateName', {params}) sur la directive ng-click du bouton. Et désactivez le bouton si aucune option n'est sélectionnée.

HTML

<select ng-model="selected" ng-options="option as option.text for option in options"></select>
<button ng-disabled="!selected" type="button" ng-click="ctrl.next()">Next</button>

Manette

function Controller($scope, $state){
    this.options = [{
        text: 'Option One',
        state: 'app.one',
        params: {
            param1: 'a',
            param2: 'b'
        }
    },{
        text: 'Option Two',
        state: 'app.two',
        params: {
            param1: 'c',
            param2: 'd'
        }
    },{
        text: 'Option Three',
        state: 'app.three',
        params: {
            param1: 'e',
            param2: 'f'
        }
    }];

    this.next = function(){
        if(scope.selected){
            $state.go($scope.selected.state, $scope.selected.params || {});
        }
    };
}

Etat

$stateProvider.state('wizard', {
    url: '/wizard/:param1/:param2', // or '/wizard?param1&param2'
    templateUrl: 'wizard.html',
    controller: 'Controller as ctrl'
});
1
rynangeles

Entré pour répondre à ça pour de bon :)

Heureusement, vous n'avez pas besoin d'utiliser un bouton pour ng-click , ou d'utiliser une fonction dans un ng-href pour obtenir ce que vous recherchez. Au lieu;

Vous pouvez créer une variable $scope dans votre contrôleur, y affecter la chaîne ui-sref et l'utiliser dans votre vue en tant qu'attribut ui-sref.

Comme ça:

// Controller.js

// if you have nasted states, change the index [0] as needed.
// I'm getting the first level state after the root by index [0].
// You can get the child by index [1], and grandchild by [2]
// (if the current state is a child or grandchild, of course).
var page = $state.current.name.split('.')[0];
$scope.goToAddState = page + ".add";


// View.html
<a ui-sref="{{goToAddState}}">Add Button</a>

Cela fonctionne parfaitement pour moi.

1
ilter

cela fonctionne juste pour moi

dans le contrôleur

$scope.createState = 'stateName';

en vue

ui-sref="{{ createState }}"
0
Abou-Emish
<ul class="dropdown-menu">
  <li ng-repeat="myPair in vm.Pairs track by $index">
     <a ui-sref="buy({myPairIndex:$index})"> 
          <span class="hidden-sm">{{myPair.pair}}</span>
     </a>
  </li>
</ul>

Si quelqu'un ne veut que définir dynamiquement le $ stateParams de ui-sref dans Angularjs . $ index sera récupéré dans cet état.

0
Ryan Augustine

Pour gérer plusieurs paramètres dynamiques en utilisant ui-sref, voici ma solution:

Html: ('MyPage.html')

<button type="button" ui-sref="myState(configParams())">

Contrôleur: ('MyCtrl')

.controller('MyCtrl', function ($scope) {
  $scope.params = {};
  $scope.configParams = function() {
    $scope.params.param1 = 'something';
    $scope.params.param2 = 'oh again?';
    $scope.params.param3 = 'yes more and more!';
    //etc ...

    return $scope.params;
  };
}

stateProvider: ('myState')

 $stateProvider
          .state('myState', {
            url: '/name/subname?param1&param2&param3',
            templateUrl: 'MyPage.html',
            controller: 'MyCtrl'
          });

Prendre plaisir !

0
Emidomh
<a ng-click="{{getLinkUrl({someParam: someValue})}}">Dynamic Link</a>

$scope.getLinkUrl = function(value){
  $state.go('My.State',{someParam:value});

}

Il retourne un objet

0
bklups