在AngularJS UI-Router中动态更改View

时间:2015-03-01 17:29:25

标签: javascript angularjs angular-ui-router

我在我的应用程序中有一个演练,其中包含4页。我决定将Walkthrough设置为具有多个视图的单个状态,以表示4个页面中的每一个。

在我的html中,我将div定义为指向当前视图的ui视图,然后我的控制器会根据需要进行更改。

问题是,当我将$ scope.currentView更新为' general'它不会改变屏幕上实际看到的内容!如果我手动将其更改为' general'在我的_init函数中,它确实显示了常规页面,但我无法根据按钮单击进行更改。

HTML:

<div ui-view="{{currentView}}@walkthrough"></div>

控制器:

var _init = function () {
    $scope.currentView = 'welcome';
};
_init();

$scope.setView = function (view) {
    $scope.currentView = view;
};

我的州定义:

.state('walkthrough', {
    url: '/walkthrough',
    views: {
        '': {
            templateUrl: 'app/walkthrough/walkthrough.html',
            controller: 'walkthroughController'
        },
        'welcome@walkthrough': {
            templateUrl: 'app/walkthrough/welcome.html'
        },
        'general@walkthrough': {
            template: 'general'
        }
    }
})

更新视图的按钮:

<img class="start-button center-block" ng-click="setView('general')" />

更新1

我已尝试以下方法解决,但没有一个有效:

  1. 将currentView更改为getter函数getCurrentView(),它返回currentView。同样的行为。
  2. 将currentView setter包装在$ scope。$ apply中。获取$ apply in progress错误
  3. 在$ timeout中包装currentView setter。相同的行为
  4. 更新2

    我添加了<pre>部分,该部分调用与ui-view {{currentView}}@walkthrough中相同的代码。它显示正确的视图,即使页面本身没有更新显示新视图。

    更新3

    我已尝试过如何以编程方式设置视图的所有组合,但我尝试过的任何工作都没有。我是否使用服务器来获取视图,函数,直接$ scope变量,什么都没有。变量本身是正确的,但是当我更改变量时,视图才会改变。

    奇怪的是,当我在init()函数中设置currentView的值时,它有效。如果我将值更改为代码本身的下一个视图之一($ scope.currentView =&#39; general&#39;&lt; - 显示常规页面),但是如果我单击按钮更改则不行currentView to&#39; general&#39;。

    我已经尝试过各种各样的$ scope。$ applys,$ digests和$ timeouts。我所做的一切都不会让视图本身更新。剩下的唯一的事情就是把它变成一堆带有ng-show / hide的div,这真的很丑陋,管理起来很痛苦,而且我之所以想要首先使用视图。

    更新4

    仍然没有进展,无论我尝试什么......我认为在$ timeout中包装变量更改的一些奇怪的组合可能证明是有用的但是唉,没有。我最后的想法是将所有这些改变为他们自己的独立状态,但随后我会得到一堆重复的代码,这显然是不好的。我在我的应用程序的其他部分使用几乎相同类型的更改(虽然改变状态,而不是视图),并且它完美地工作。我无法弄清楚为什么我无法动态更改视图。任何帮助将不胜感激。

    更新5

    在下面的用户评论后有一些回家,但它没有领先优势。我试图调用各种$ state更改来刷新视图,但没有任何工作。我尝试了以下所有内容,但没有一个对页面产生任何影响:

    $state.reload();
    $state.go($state.current, {}, { reload: true });
    $state.transitionTo($state.current, $stateParams, {
        reload: true,
        inherit: false,
        notify: true
    });
    

2 个答案:

答案 0 :(得分:2)

虽然ui-view指令将为视图名称采用插值({{ something }}),但它实际上并不会对此进行更改。相反,查看更新仅由$stateChangeSuccess$viewContentLoading事件触发。这就是为什么你可以在第一次和第一次看到它工作的原因。

您可以通过查看ui-router源代码中$ViewDirective的链接功能来验证这一点:https://github.com/angular-ui/ui-router/blob/master/src/viewDirective.js

这意味着您的setView函数需要调用$state.go来触发状态更改,而不是仅仅在范围上设置属性。作为通常的状态更改过程,这最终会导致广播$stateChangeSuccess事件。

答案 1 :(得分:0)

所以我解决了这个问题,只需让每个演练页面都从父级演练中获得自己的继承状态,每个演练都有一个单独的视图。可能不是最好的方法,但我不想浪费更多时间。

我仍然喜欢使用嵌套视图并以这种方式导航的方法,因为使用该方法将来更容易添加更多,而不会使我的stateProvider膨胀。

        .state('walkthrough', {
            url: '/walkthrough',
            views: {
                '': {
                    templateUrl: 'app/walkthrough/walkthrough.html',
                    controller: 'walkthroughController'
                }
            }
        })
        .state('walkthrough.welcome', {
            url: '/welcome',
            views: {
                'walkthrough.welcome@walkthrough': {
                    templateUrl: 'app/walkthrough/welcome.html'
                }
            }
        })
        .state('walkthrough.general', {
            url: '/general',
            views: {
                'walkthrough.general@walkthrough': {
                    templateUrl: 'app/walkthrough/general.html'
                }
            }
        })
        .state('walkthrough.business', {
            url: '/business',
            views: {
                'walkthrough.business@walkthrough': {
                    templateUrl: 'app/walkthrough/business.html'
                }
            }
        })
        .state('walkthrough.friends', {
            url: '/friends',
            views: {
                'walkthrough.friends@walkthrough': {
                    templateUrl: 'app/walkthrough/friends.html'
                }
            }
        })

现在我可以使用

轻松导航
<img ui-sref="walkthrough.general" />