使用 Ui-Router 在 AngularJS 中设置动态 URL 状态

Set dynamic URL on state in AngularJS with Ui-Router

我的页面上有一个 ng-include 呈现部分,但由于 ng-include 的性质,我不需要状态来加载部分。我希望 URL 在 ng-include 更新其视图时更新,以便我的分析将其跟踪为页面更改。我想知道最好的方法。

我也在使用 angular-ui-router,这使得 ng-include 由于嵌套状态而变得无关紧要;直到有人遇到我的情况:我有大量的部分加载到 ng-include 中,这很可爱,因为我需要提供的只是部分的路径,而不是我的 $stateProvider 文件的大量不同状态;但是没有自定义url。因此,我想知道的是:

Ng-include 是否可以在加载局部视图时更新页面 url 而没有为该局部视图定义状态

可以完全解决我的问题的东西: 有没有办法添加具有 url 的状态,可以动态更新?喜欢:

.state( 'test',  {
        url: function( stateId ){
    // where stateId is somehow passed into the $stateParams of the new state
},
    templateUrl: "templates/views/test.html"
})

这是我的 ng-include 到目前为止的设置,如果您对如何在 ng-include 呈现不同部分时更改 url 有任何想法,我会非常高兴。


::JS::

// states
 // self executing function
(function() {

var app = angular.module( 'app', [ 'ui.router', 'ngAnimate' ] );

app.config( function( $stateProvider, $urlRouterProvider ) {

  // if url not defined redirect to login
  $urlRouterProvider.when( '', "/home" );
  // if nonexistant url defined redirect to sign-in
  $urlRouterProvider.otherwise( "/home" );

  // Now set up the states
  $stateProvider
    .state('home', {
      url: "/home",
      templateUrl: "templates/views/home.html"
    });
}()); // self executing function end

// factory
//self executing container function
(function() {
var listFactory = function( ) {
  // declare factory for return at end of function
  var factory = {};

  var list = 
    { 
        list1 : [
            { 
                name: 'first',
                url: 'templates/views/partials/view1.html',
                id: '1'
            },
            {
                name: 'second',
                url: 'templates/views/partials/view2.html',
                id: '2'
            },
            {
                name: 'third',
                url: 'templates/views/partials/view3.html',
                id: '3'
            },
            {
                name: 'fourth',
                url: 'templates/views/partials/view4.html',
                id: '4'
            }
        ]
    };

    factory.getList = function(){
      return list;
    };

    // return factory object to access data
    return factory;
};

  angular.module( 'app' ).factory( 'listFactory', listFactory );

}());

// controller
//self executing container function
(function() {

    var listController = function ( $scope, listFactory ) {

        $scope.listFactory = listFactory.getList();
        // set a default list state
        $scope.currentList = 'templates/views/partials/default.html';

        // function sets list url on click to new scope item for rendering partial view
        $scope.setCurrentList = function( url ) {
            $scope.currentList = url;
        };
    };

    listController.$inject = [ '$scope', 'listFactory' ];

    angular.module('app')
      .controller('listController', listController);

}());

::HTML::

<!-- this is loaded in the home state.  -->

<div>
    <div id="{{ list.id }}" ng-repeat="list in list.list1" ng-click="setCurrentList( list.url )">
        <p>{{ list.name }}</p>
    </div>
</div>
<div id="list-view-container">
    <div class="rotateViewAnimate" ng-include src="currentList"></div>
</div>

::相当不相关 CSS::

/* Have to set height explicity on ui-view-container
to prevent collapsing during animation*/
#list-view-container {
    position: relative;
    min-height: 500px;
    overflow: hidden;
}    

/* rotate in / out animation transition */
.rotateViewAnimate.ng-enter, .rotateViewAnimate.ng-leave {
  /* settings so animations display together */
  position: absolute!important;
  left: 0!important;
  right: 0!important;
  -webkit-transition: 0.5s ease-in-out all;
  -moz-transition: 0.5s ease-in-out all;
  -o-transition: 0.5s ease-in-out all;
  transition: 0.5s ease-in-out all;
  transform-style: preserve-3d;
}

.rotateViewAnimate.ng-enter {
    transform: rotateY(90deg);
    opacity: 0;
}

.rotateViewAnimate.ng-enter-active {
    transform: rotateY(0deg);
    opacity:1;
}

.rotateViewAnimate.ng-leave {
    transform: rotateY(0deg);
    opacity:1;
}

.rotateViewAnimate.ng-leave-active {
    transform: rotateY(90deg);
    opacity:0;
}





好的,所以对于使用 Ui-Router 的部分,您需要包含一个

<ui-view>
    <i>Some content will load here!</i>
</ui-view>

您希望部分加载的位置。

看起来你的家庭状态工作正常,但如果你想嵌套视图你必须做这样的事情

.state('home.view1', {
  url: '/notes',
  templateUrl: 'pages/view1.html',
  controller: 'mainController'
})

执行此嵌套路由的完整 Url 将是 */#/home/notes 欲了解更多信息: https://github.com/angular-ui/ui-router/wiki


已解决


ui-router 文档中详细介绍了我要解决的问题;在这里找到:

https://github.com/angular-ui/ui-router/wiki

我使用了下面的方法来达到这里所说的效果:

"Set a Dynamic URL on a state using ui-router and angularJS"

查看问题中显示的代码,我将根据我的解决方案对其进行相应调整。

// states
// self executing function
(function() {

var app = angular.module( 'app', [ 'ui.router', 'ngAnimate' ] );

app.config( function( $stateProvider, $urlRouterProvider ) {

  // if url not defined redirect to login
  $urlRouterProvider.when( '', "/home" );
  // if nonexistant url defined redirect to sign-in
  $urlRouterProvider.otherwise( "/home" );

  // Now set up the states
  $stateProvider
    .state('home', {
      url: "/home",
      templateUrl: "templates/views/home.html"
    })
    .state( 'home.urlChanger', {
        url: '/urlChanger/name=:name&url=:url',
        params: {
            'spareParam' : 'whateverString'
        },
        views: {
            'viewName@home': {
                templateUrl: function ( $stateParams ){
                    return $stateParams.url;
                },
                controller: "mainController"
            }
        }
    });
}()); // self executing function end

在上面的状态声明中,状态 "home.urlChanger" 有一个带有特殊字符的 url,这些字符的值来自传递给 $stateProvider 变量的信息。这里有一个非常重要的注意事项是,如果想要访问存储在 $stateParams 中的项目,则必须将其传递到 URL 中。因此,在我的控制器中,我使用以下函数通过 $state.go(); 传递我希望在状态下可用的信息;方法如下:

$scope.setParams = function( location ) {
        var urlname = object.stored.in.factory.NAME,
            url = object.from.factory.URL, // path to html file passed to be used in termplateurl from state
            // set stateParams.name to be used in URL
            $stateParams.name = urlName;

            // set params to be passed into URL when $state.go(); is called, they will be available for use then and update the URL with the state setup from above.
            $state.go( location, { name: $stateParams.name, url: url } );
        }; 

从上面的示例可以看出,我尝试将其存储到 $stateparams.name 中以查看它是否会在状态参数中可用,但正如预期的那样 state.go();被称为一个新的状态被加载并且之前的 $stateparams 对象不再可用。因此,为什么必须在 $state.go 期间传递信息,以便将其存储到新转换的状态 $stateParams 对象中。

所以导致这种情况发生的 html 可能是对调用 setparams( location ) 函数的任何元素的 ng-click,这将通过将变量传递给 URL 并使它们在您所在的州可用,即:由州本身设置的动态 URL。

希望有人发现这有点帮助,我花了一些时间来完成自己的工作。

案例是在 http 创建请求 (201) 之后更改页面 URL 这是一个例子:

StudentsService.create($stateParams.sudId,studentInfo).then(r => {
                 $scope.newStudentId=r.data.id;
     console.log(r.data, $scope.newStudentId);
     $state.go("stateName", {sudId:$stateParams.sudId, id:$scope.newStudentId});

所以,创建后会发给新生url。