【问题标题】:Dynamically set the value of ui-sref Angularjs动态设置 ui-sref Angularjs 的值
【发布时间】:2014-08-12 12:53:56
【问题描述】:

我搜索了一个类似的问题,但出现的问题似乎略有不同。 我正在尝试动态更改链接的 ui-sref='' (此链接指向向导表单的下一部分,下一部分取决于下拉列表中的选择)。我只是想根据选择框中的某些选择来设置 ui-sref 属性。我可以通过绑定到在进行选择时设置的范围属性来更改 ui-sref。但是链接不起作用,这可能吗?谢谢

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

然后在我的控制器中,我以这种方式设置 url 参数

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

或者,我使用指令通过根据选择框(下拉)上选择的选项生成具有所需 ui-sref 属性的超链接来使其工作。

但是,这意味着每次从选择框中选择不同的选项时,我都必须重新创建链接,这会导致不希望的闪烁效果。 我的问题是,是否可以像我上面尝试的那样通过简单地更改控制器中 url 的值来更改 ui-sref 的值,还是每次选择时我都必须使用指令重新创建整个元素是按照我在下面所做的那样制作的吗? (只是为了完整起见)

选择选项指令(该指令生成链接指令)

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

超链接指令

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

})

超链接模板

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

【问题讨论】:

标签: angularjs angular-ui angular-ui-router


【解决方案1】:

看来这毕竟是可能的。

一位 ui-router 作者在GitHub 上的面包屑引导我尝试以下操作:

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

然后,在您的控制器中:

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

事实证明,这就像一个带有改变作用域值和所有内容的魅力。您甚至可以使“状态名称”字符串常量引用一个作用域值,这也将更新视图中的 href :-)

【讨论】:

  • 最干净的解决方案 - 值得一提的是,“独立于路由器库”。
  • 这迫使 getLinkUrl() 在每个摘要周期都被处理,这是非常频繁的。在 getLinkUrl() 中粘贴一个 console.log,然后在页面上移动鼠标,然后看着你的日志爆炸。不是说这个方法不行,就是乱七八糟。
  • 这是 3 年前用 Angular 1.4 编写的解决方案。在当时,使用那个版本的 Angular,这是实现所需功能的唯一可行选择。只是批评和否决答案,甚至懒得给出替代解决方案(如果有的话),对任何人都没有帮助。
  • 绝对确实有帮助。它向未来的观众暗示这可能不是最好的解决方案,他们应该寻找其他地方。该评论没有任何“不具建设性”的地方。如果有任何不具建设性的地方,那就是您的回应,猛烈抨击用户的有效批评(并假设事实没有证据,例如反对票与评论相关联)。
  • @FabioPicheli 的回答确实提供了更新的原生解决方案,请务必查看。
【解决方案2】:

a working plunker。最简单的方法似乎是使用以下组合:

  • $state.href() (doc here)
  • ng-href (文档here

这些一起可以用作:

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

所以,(在 this plunker 之后) 具有如下状态:

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

我们可以改变这些值来动态生成href

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

查看action here

原文:

有一个工作示例how to 实现了我们所需要的。但不是动态的ui-sref

我们可以在这里查看:https://github.com/angular-ui/ui-router/issues/395

问:[A]不支持动态 ui-sref 属性?
答:正确。

但是我们可以使用ui-router的不同特性:[$state.go("statename")][5]

所以,这可能是控制器的东西:

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

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

工作的example

注意:有更多最新链接到$state.go 定义,但不推荐使用的链接对我来说更清楚

【讨论】:

  • 恕我直言,这并不能完全实现所需的行为。 ui-sref 实际上在 ui-sref 指令初始化时设置了锚标记的 href 属性。我通常为动态控制的锚标记做的事情如下:&lt;a ui-sref="{{scopedStateName}}( { 'some-state-param': '{{scopedParamValue}}' })"&gt;My Dynamic Link&lt;/a&gt; 显然,这种方法的唯一问题是 ui-sref 不会监视作用域变量的变化,因此 href 不会改变随后的价值变化。 AFAIK,ui-sref 不支持这个。
  • 经过更多研究,我想我找到了一种方法来完成动态生成的href属性引用状态w/状态参数。请在下面查看我的答案。
  • 在使用 ng-href 时如何避免硬页面刷新?我目前在使用此解决方案时遇到问题,因为 ng-href 不使用 ui-routers $state.go() 方法。
【解决方案3】:

看看这个问题#2944

ui-sref 不监视状态表达式,您可以使用ui-stateui-state-params 传递变量。

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

票中还提供了一个快速demo

【讨论】:

  • 太棒了。它不需要额外的逻辑,也支持 ui-sref-active
【解决方案4】:

我设法以这种方式实现它(虽然我使用的是 controllerAs 变体 - 不是通过 $scope)。

模板

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

控制器

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

另请参阅ui-sref 的文档,您可以在其中传递参数:

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

【讨论】:

  • 不,button 的行为方式与a 相同,该指令实际上在编译时在按钮上创建了一个href 属性,但从未更新此属性。并且单击按钮将始终进入 href 值的状态,但不是更新后的 ui-sref
【解决方案5】:

在尝试了各种解决方案后,我在angular.ui.router 代码中发现了问题。

问题在于 ui.router update 方法是用ref.state 触发的,这意味着无法更新单击元素时使用的href 的值。

这里有两种解决方案:

自定义指令

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

使用它的 HTML 非常简单:

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

修复ui.router代码:

在 angular.router.js 中,您将找到指令 $StateRefDirective(0.3 版的第 4238 行)。

将指令代码更改为:

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

【讨论】:

  • 除非你创建自己的 angular-ui-router 分支,否则我建议不要这样做。你的同事可能会尝试更新它并b​​oom,没有人知道错误来自哪里。
【解决方案6】:

来回答这个问题:)

幸运的是,您不需要为 ng-click 使用按钮,或使用 ng-href 内的函数来实现您所寻求的。而是;

您可以在您的控制器中创建一个$scope 变量并在其中分配ui-sref 字符串并在您的视图中使用它,作为ui-sref 属性。

像这样:

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

这对我来说非常有效。

【讨论】:

  • 我已经尝试过你的方法,我可以看到ui-sref 但没有生成href。任何建议
  • 我的回答中没有提到“href”。这有什么关系?
  • ui-sref 是一个指令,如果提供的状态具有 url(但在这种情况下显然没有),则在元素上设置 href 属性。
  • @ilter 这是第一次工作,但没有任何双向绑定 - 范围更改时链接不会更新。
  • 我只能为自己说话,但就我而言,这是因为答案不适用于该问题。当下拉列表更改时,您将不再拥有有效的链接。
【解决方案7】:

最好的方法是在按钮的ng-click 指令上使用uiRouter's $state.go('stateName', {params})。如果未选择任何选项,则禁用该按钮。

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>

控制器

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

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

【讨论】:

  • 这不适用于 ui-sref-active 或 ui-sref-active-eq
【解决方案8】:
<a ng-click="{{getLinkUrl({someParam: someValue})}}">Dynamic Link</a>

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

}

它返回一个对象

【讨论】:

    【解决方案9】:

    这对我有用

    在控制器中

    $scope.createState = 'stateName';
    

    在视图中

    ui-sref="{{ createState }}"
    

    【讨论】:

    • 正如@ben 在其他答案中所指出的:这是第一次工作,但没有任何双向绑定 - 范围更改时链接不会更新
    【解决方案10】:

    对于使用 ui-sref 管理 多个动态参数,这里是我的解决方案:

    Html : ('MyPage.html')

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

    控制器: ('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'
              });
    

    享受吧!

    【讨论】:

    • 它给了我一个错误,指出无法从当前状态导航到 myState
    • @Mani 你在使用ui-router 吗?可以看到你的代码吗?
    • 是的,我正在使用 ui-router。 {{ item.title }}
    • 试试ui-sref="item.state"
    • 它只适用于花括号。对不起。还有一些地方我犯了错误。对不起。
    【解决方案11】:
    <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>
    

    如果有人只想在Angularjs中动态设置ui-sref$stateParams。 注意:在检查元素中,它仍会显示为“buy({myPairIndex:$index})”,但会在该状态下获取 $index。

    【讨论】:

      【解决方案12】:

      我发现这个解决方案最合适:

      .state('history', {
          url: 'home',
          controller: 'homeCtrl',
          templateUrl: "home.html"
        })
        .state('settings', {
          url: "/settings",
          controller: 'settingsCtrl',
          templateUrl: 'settings.html'
        })
      
      <button ui-sref="{{$ctrl.newProductLink()}}"</button>
      
      ctrl.newProductLink = () => a > b ? 'home' : 'settings';
      

      【讨论】:

        【解决方案13】:

        或者只是这样:

        <a ui-sref="{{ condition ? 'stateA' : 'stateB'}}">
          Link
        </a>
        

        【讨论】:

        • 正如@ben 在其他答案中所指出的:这是第一次工作,但没有任何双向绑定 - 范围更改时链接不会更新
        • 我正在尝试这种方法,但无法提出任何建议或
        猜你喜欢
        • 2019-09-06
        • 2015-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-01
        • 2014-08-22
        • 2015-03-19
        • 2019-03-22
        相关资源
        最近更新 更多