Angular ui-路由器之争
Angular ui-router struggle
好吧,我有这个项目,ui-router 让我很难过。我做了一个 quick Plunker 演示:http://plnkr.co/edit/imEErAtOdEfaMMjMXQfD?p=preview
所以基本上我有一个主视图,index.html
,其他顶级视图被注入其中,像这样 operations.index.html
。当顶层视图中有多个命名视图时,我的大脑开始疼痛,operations.detail.html
和 operations.list.html
被注入 operations.index.html
,后者又被注入 index.html
.
基本上,我要实现的是以下行为:
- 当用户单击导航栏中的
Operations
项时,将显示一个包含空(新)操作的页面。 URL 是 /operations
.
- 当他们 select 列表中的一个项目时,字段会更新一些数据(数据是通过服务请求的,但为简单起见,我们假设它就在控制器中)。 URL 是
/operations/:id
.
- 如果他们决定要创建一个新项目,同时编辑当前项目,他们单击列表顶部的
New operation
按钮,URL 将从 /operations/:id
变为至 /operations
.
- 无论新项目还是旧项目,导航栏中的项目
Operations
都保持活动状态。
- 如果用户正在编辑一个项目,它应该在列表中突出显示为活动,如果他们创建一个新项目 —
New operation
按钮应该相应地突出显示。
现在,检查一下奇怪的行为:转到 Operations
,然后再次单击 Operations
导航栏项。一切都消失了。如果我做 Operations
-> select Operation 1
-> select New operation
.
也会发生同样的情况
此外,请查看我尝试获取 id
参数的部分:
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
if (toParams) {
if (toParams.id) {
for (var i = 0; i < vm.operations.length; i++) {
if (vm.operations[i].id == toParams.id) {
vm.operation = vm.operations[i];
break;
}
}
}
}
});
我不是专家,但看起来太长太复杂了,尤其是对于获取请求参数这样简单的任务。如果我尝试检查状态更改 $stateParams
,则对象为空,因此采用此解决方法。如果我尝试篡改 app.js
中的状态,情况会略有不同,但总会出现 Operations
导航栏项目失去其活动状态或其他奇怪的东西之类的错误。
我知道问这样笼统的问题在 SO 中并不常见,但我真的无法理解 ui-router 的概念,我能感觉到我在这里做错了,并且如果能为我指明如何正确使用 ui-router 的正确方向,我将不胜感激。干杯。
我刚刚使用了这个问答中的技术:
我添加了 redirectTo
设置 (可以是任何状态)
.state('operations', {
url: '/operations',
templateUrl: 'operations.index.html',
controller: 'operationsController as op',
// here is redirect
redirectTo: 'operations.new',
})
并添加了这个 redirector
:
app.run(['$rootScope', '$state', function($rootScope, $state) {
$rootScope.$on('$stateChangeStart', function(evt, to, params) {
if (to.redirectTo) {
evt.preventDefault();
$state.go(to.redirectTo, params)
}
});
}]);
此外,我删除了当前位于 operationsController.js
:
中的重定向
angular.module('uiRouterApp')
.controller('operationsController', function($state, $stateParams, $rootScope) {
var vm = this;
//if ($state.current.name === 'operations') $state.go('operations.new');
以上只是为了保持新状态 - 没有 url。因为解决方案会变得更容易,如果我们只引入 url: '/new'
:
.state('operations', {
url: '/operations',
..
})
.state('operations.new', {
//url: '',
url: '/new',
因此,我们通过这种方式为路由赋予了生命。现在是让细节发挥作用的时候了。为了实现它,我们需要更多 - there is another updated plunker
首先,我们将全新controller
两个子状态视图:
.state('operations.new', {
url: '',
views: {
'detail': {
templateUrl: 'operations.detail.html',
controller: 'detailCtrl as dc', // here new controller
...
})
.state('operations.detail', {
url: '/:id',
views: {
'detail': {
templateUrl: 'operations.detail.html',
controller: 'detailCtrl as dc', // here new controller
...
两者可能是同一个控制器,因为我们将根据 $stateParams.id
的内容保留新的或现有的决定。这将是它的实现:
.controller('detailCtrl', function($scope, $state, $stateParams) {
var op = $scope.op;
op.operation = {id:op.operations.length + 1};
if ($stateParams.id) {
for (var i = 0; i < op.operations.length; i++) {
if (op.operations[i].id == $stateParams.id) {
op.operation = op.operations[i];
break;
}
}
}
})
我们保持原来的方法,并在选择$stateParams.id
时设置op.operation。如果不是,我们创建新项目,id
适当递增。
现在我们只是调整父控制器,不保存现有的,只保存新的:
.controller('operationsController', function($state, $stateParams, $rootScope) {
var vm = this;
//if ($state.current.name === 'operations') $state.go('operations.new');
vm.operation = {};
/*$rootScope.$on('$stateChangeStart',
function(event, toState, toParams, fromState, fromParams) {
if (toParams) {
if (toParams.id) {
for (var i = 0; i < vm.operations.length; i++) {
if (vm.operations[i].id == toParams.id) {
vm.operation = vm.operations[i];
break;
}
}
}
}
});*/
vm.save = function() {
if(vm.operations.indexOf(vm.operation) >= 0){
return;
}
if (vm.operation.name
&& vm.operation.description
&& vm.operation.quantity) {
vm.operations.push(vm.operation);
vm.operation = {id: vm.operations.length + 1};
}
};
好吧,我有这个项目,ui-router 让我很难过。我做了一个 quick Plunker 演示:http://plnkr.co/edit/imEErAtOdEfaMMjMXQfD?p=preview
所以基本上我有一个主视图,index.html
,其他顶级视图被注入其中,像这样 operations.index.html
。当顶层视图中有多个命名视图时,我的大脑开始疼痛,operations.detail.html
和 operations.list.html
被注入 operations.index.html
,后者又被注入 index.html
.
基本上,我要实现的是以下行为:
- 当用户单击导航栏中的
Operations
项时,将显示一个包含空(新)操作的页面。 URL 是/operations
. - 当他们 select 列表中的一个项目时,字段会更新一些数据(数据是通过服务请求的,但为简单起见,我们假设它就在控制器中)。 URL 是
/operations/:id
. - 如果他们决定要创建一个新项目,同时编辑当前项目,他们单击列表顶部的
New operation
按钮,URL 将从/operations/:id
变为至/operations
. - 无论新项目还是旧项目,导航栏中的项目
Operations
都保持活动状态。 - 如果用户正在编辑一个项目,它应该在列表中突出显示为活动,如果他们创建一个新项目 —
New operation
按钮应该相应地突出显示。
现在,检查一下奇怪的行为:转到 Operations
,然后再次单击 Operations
导航栏项。一切都消失了。如果我做 Operations
-> select Operation 1
-> select New operation
.
此外,请查看我尝试获取 id
参数的部分:
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
if (toParams) {
if (toParams.id) {
for (var i = 0; i < vm.operations.length; i++) {
if (vm.operations[i].id == toParams.id) {
vm.operation = vm.operations[i];
break;
}
}
}
}
});
我不是专家,但看起来太长太复杂了,尤其是对于获取请求参数这样简单的任务。如果我尝试检查状态更改 $stateParams
,则对象为空,因此采用此解决方法。如果我尝试篡改 app.js
中的状态,情况会略有不同,但总会出现 Operations
导航栏项目失去其活动状态或其他奇怪的东西之类的错误。
我知道问这样笼统的问题在 SO 中并不常见,但我真的无法理解 ui-router 的概念,我能感觉到我在这里做错了,并且如果能为我指明如何正确使用 ui-router 的正确方向,我将不胜感激。干杯。
我刚刚使用了这个问答中的技术:
我添加了 redirectTo
设置 (可以是任何状态)
.state('operations', {
url: '/operations',
templateUrl: 'operations.index.html',
controller: 'operationsController as op',
// here is redirect
redirectTo: 'operations.new',
})
并添加了这个 redirector
:
app.run(['$rootScope', '$state', function($rootScope, $state) {
$rootScope.$on('$stateChangeStart', function(evt, to, params) {
if (to.redirectTo) {
evt.preventDefault();
$state.go(to.redirectTo, params)
}
});
}]);
此外,我删除了当前位于 operationsController.js
:
angular.module('uiRouterApp')
.controller('operationsController', function($state, $stateParams, $rootScope) {
var vm = this;
//if ($state.current.name === 'operations') $state.go('operations.new');
以上只是为了保持新状态 - 没有 url。因为解决方案会变得更容易,如果我们只引入 url: '/new'
:
.state('operations', {
url: '/operations',
..
})
.state('operations.new', {
//url: '',
url: '/new',
因此,我们通过这种方式为路由赋予了生命。现在是让细节发挥作用的时候了。为了实现它,我们需要更多 - there is another updated plunker
首先,我们将全新controller
两个子状态视图:
.state('operations.new', {
url: '',
views: {
'detail': {
templateUrl: 'operations.detail.html',
controller: 'detailCtrl as dc', // here new controller
...
})
.state('operations.detail', {
url: '/:id',
views: {
'detail': {
templateUrl: 'operations.detail.html',
controller: 'detailCtrl as dc', // here new controller
...
两者可能是同一个控制器,因为我们将根据 $stateParams.id
的内容保留新的或现有的决定。这将是它的实现:
.controller('detailCtrl', function($scope, $state, $stateParams) {
var op = $scope.op;
op.operation = {id:op.operations.length + 1};
if ($stateParams.id) {
for (var i = 0; i < op.operations.length; i++) {
if (op.operations[i].id == $stateParams.id) {
op.operation = op.operations[i];
break;
}
}
}
})
我们保持原来的方法,并在选择$stateParams.id
时设置op.operation。如果不是,我们创建新项目,id
适当递增。
现在我们只是调整父控制器,不保存现有的,只保存新的:
.controller('operationsController', function($state, $stateParams, $rootScope) {
var vm = this;
//if ($state.current.name === 'operations') $state.go('operations.new');
vm.operation = {};
/*$rootScope.$on('$stateChangeStart',
function(event, toState, toParams, fromState, fromParams) {
if (toParams) {
if (toParams.id) {
for (var i = 0; i < vm.operations.length; i++) {
if (vm.operations[i].id == toParams.id) {
vm.operation = vm.operations[i];
break;
}
}
}
}
});*/
vm.save = function() {
if(vm.operations.indexOf(vm.operation) >= 0){
return;
}
if (vm.operation.name
&& vm.operation.description
&& vm.operation.quantity) {
vm.operations.push(vm.operation);
vm.operation = {id: vm.operations.length + 1};
}
};