我有一个抽象的profile
状态,它有多个子状态(对于配置文件页面的不同选项卡),然后我希望另一个子状态的配置文件是一个模态。我已经实现了这样的事情:
$stateProvider
.state('profile', {
url: '/profile/:profileID',
templateUrl: 'profile.html',
controller: 'ProfileCtrl',
abstract:true,
resolve: {
user: ...
}
})
.state('profile.circles', {
url: '',
templateUrl: 'profilecircles.html',
controller: 'profilecirclesCtrl',
resolve: { circle: ... }
})
.state('profile.squares', {
url: '/collections',
templateUrl: 'profilesquares.html',
controller: 'profilesquaresCtrl',
resolve: { squares: ... }
})
.state('profile.editprofile', {
url: '/edit',
onEnter: ['$window','$modal', function($window, $modal) {
$modal.open({
templateUrl: 'editprofile.html',
controller: 'editProfileCtrl',
resolve: {
user: ...
}
}).result.then(function() {
$window.history.back();
},function() {
$window.history.back();
});
}]
})
这很有效,除了因为editprofile是正方形和圆形的兄弟,当该状态处于活动状态并且模态处于视图中时,正方形或圆形状态被卸载,并在模态时再次加载回来已关闭。
当profile.editprofile状态处于活动状态时,有没有办法让这些状态保持活动状态?我喜欢state..editprofile
。
答案 0 :(得分:3)
由于目前还没有理想的解决方案,我提出了一个相当优雅的解决方案。我的代码是通用的,易于理解和评论,因此它很容易适应任何项目。
请参阅代码中的注释以获取最重要的观点。
$stateProvider
// modal will open over this state from any substate
.state('foo', {
abstract: true,
url: '/:fooProp',
templateUrl: 'foo.html',
controller: 'FooController'
})
.state('foo.main', {
url: '',
templateUrl: 'foo-main.html',
controller: 'FooMainController'
})
.state('foo.bar', {
url: '/bars/:barId',
templateUrl: 'foo-bar.html',
controller: 'FooBarController'
})
// append /modal route to each `foo` substate
.state('foo.main.modal', getModalState())
.state('foo.bar.modal', getModalState())
;
function getModalState() {
return {
url: '/modal',
onEnter: [
'$modal',
'$state',
function($modal, $state) {
$modal.open({
templateUrl: 'foo-modal.html',
controller: 'FooModalController'
}).result.finally(function() {
// go to parent state - the current `foo` substate
$state.go('^');
});
}
]
}
}
$scope.goToModalState = function() {
// go to this state's `modal` state
$state.go($state.current.name+'.modal');
};
<a ng-click="goToModalState()">Open Modal</a>
答案 1 :(得分:2)
除非您想要放弃模态实现,否则我建议在profile.html
中为editprofile.html
设置2个视图,为profilecircles.html
或profilesquares.html
设置其他视图,如下所示:
// profile.html
...
<div class="" ui-view="edit" autoscroll="false"></div>
<div class="" ui-view="content" autoscroll="false"></div>
...
// state config
$stateProvider
.state('profile', {
url: '/profile/:profileID',
templateUrl: 'profile.html',
controller: 'ProfileCtrl',
abstract:true,
resolve: {
user: ...
}
})
.state('profile.circles', {
url: '',
views: {
edit@: {
templateUrl: 'editprofile.html',
controller: 'editProfileCtrl'
},
content@: {
templateUrl: 'profilecircles.html',
controller: 'profilecirclesCtrl'
}
}
resolve: { circle: ... }
})
.state('profile.squares', {
url: '/collections',
views: {
edit@: {
templateUrl: 'editprofile.html',
controller: 'editProfileCtrl'
},
content@: {
templateUrl: 'profilesquares.html',
controller: 'profilesquaresCtrl'
}
}
resolve: { squares: ... }
})
然后是实际显示/隐藏编辑个人资料视图的难点。但这可以通过一些切换按钮或在控制器中验证操作后完成。
答案 2 :(得分:1)
ui-router的意思是状态嵌套与url嵌套匹配。这意味着,如果你有:
profile.circles with a url: /profile/123
profiles.squares with a url: /profile/123/collections
profiles.edit with a url: /profile/123/edit
你不能指望profile.squares和profiles.edit同时处于活动状态,因为它们是两个完全不同的网址。但是有可能:
profiles.circles.editprofile with a url: /profile/123/edit
这会使profile.circles在你的模态中保持活动状态,因为它是父状态。 但是对于profiles.squares,如果你想要一个代表editprofile的状态,你需要这样的东西:
profiles.squares.editprofile with a url: /profile/123/collection/edit
不幸的是,如果你想把编辑作为一种状态,没有别的方法。
答案 3 :(得分:0)
您可以使用ui-router-extras指定标签状态sticky: true
。导航到兄弟时保留粘性状态,对标签特别有用。
要使用它,您必须为每个粘性状态创建一个命名视图(您可以隐藏非活动状态,但请参见下文)。
API page描述了必要的步骤:
sticky: true
views: { bar: { /* bar named-view definition */ } }
<div ui-view="bar" />
<div ui-view="bar" ng-show="$state.includes("foo.bar") />