AngularJS 步骤向导,禁用基于值的进度
AngularJS Step wizard, disable progress based on values
我正在使用 ui.router 创建我的视图并且我已经设置了这组状态:
.config(['$stateProvider', function ($stateProvider) {
// Set up our state(s)
$stateProvider.state('designer', {
url: '/:sport/designer',
abstract: true,
templateUrl: '/app/designer/index.tpl.html',
controller: 'DesignerController',
controllerAs: 'controller'
}).state('designer.team', {
url: '',
templateUrl: '/app/designer/team.tpl.html',
data: {
pageTitle: 'Create your team'
}
}).state('designer.kit', {
url: '/kit',
templateUrl: '/app/designer/kit.tpl.html',
data: {
pageTitle: 'Choose your garments'
}
}).state('designer.design', {
url: '/design',
templateUrl: '/app/designer/design.tpl.html',
data: {
pageTitle: 'Choose your design'
}
}).state('designer.refine', {
url: '/refine',
templateUrl: '/app/designer/refine.tpl.html',
data: {
pageTitle: 'Refine your design'
}
}).state('designer.order', {
url: '/order',
templateUrl: '/app/designer/order.tpl.html',
data: {
pageTitle: 'Order your kit'
}
}).state('designer.save', {
url: '/save',
templateUrl: '/app/designer/save.tpl.html',
data: {
pageTitle: 'Save your kit',
requireLogin: true
}
});
}])
索引模板如下所示:
<div class="container designer">
<div class="row designer-header">
<div class="col-md-6" ng-include="'/app/designer/tpls/header.tpl.html'">
</div>
<div class="col-md-6" ng-include="'/app/designer/tpls/navigation.tpl.html'">
</div>
</div>
<div class="row">
<div class="col-md-12" ng-include="'/app/designer/tpls/total.tpl.html'" ng-hide="controller.garments.loading">
</div>
</div>
<div class="row designer-body">
<ui-view></ui-view>
</div>
</div>
导航 包含如下所示:
<nav class="navbar navbar-designer">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="collapse navbar-collapse" id="designer-menu">
<ul class="nav navbar-nav navbar-right">
<li ui-sref-active="active"><a ui-sref=".team">Your team</a></li>
<li><a>|</a></li>
<li ui-sref-active="active"><a ui-sref=".kit">Kit</a></li>
<li><a>|</a></li>
<li ui-sref-active="active"><a ui-sref=".design">Design</a></li>
<li><a>|</a></li>
<li ui-sref-active="active"><a ui-sref=".refine">Refine</a></li>
<li><a>|</a></li>
<li ui-sref-active="active"><a ui-sref=".order">Order</a></li>
</ul>
</div>
</nav>
所以,我的想法是我想逐步构建它;即当页面首次加载时,我希望用户只有在填写完第一页后才能进入下一步(.kit),如下所示:
<div class="col-md-12">
<div class="alert alert-warning alert-dismissable" ng-show="controller.colours.data && controller.colours.data.length === 0">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
You must have at least one colour in the database before you can create a team / kit.
</div>
<alert-error error="controller.colours.error"></alert-error>
<form name="teamForm" novalidate ng-show="!controller.colours.loading && !controller.colours.error">
<div class="form-group">
<label class="sr-only" for="teamName">Team name</label>
<div class="input-group">
<div class="input-group-addon">1</div>
<input type="text" class="form-control" id="teamName" placeholder="Enter your team name" ng-model="controller.model.team.data.name" ng-change="controller.saveSession()" required>
</div>
</div>
<div class="form-group">
<label class="sr-only" for="colours">Colours</label>
<div class="picker colour-picker">
<div class="input-group">
<div class="input-group-addon">2</div>
<input type="text" class="form-control" id="colours" placeholder="Choose your colours" disabled>
</div>
<ul class="picker-dropdown list-inline form-control">
<li ng-repeat="colour in controller.colours.data" ng-class="{ 'active': controller.matchColour(colour) }">
<a href style="background-color: #{{ colour.hex }};" ng-click="controller.setColour(colour)"></a>
</li>
</ul>
</div>
</div>
</form>
<p><a class="btn btn-primary pull-right" ui-sref="designer.kit">Choose teamwear</a></p>
</div>
应禁用所有其他 "tabs"。然后类似地,当我前进到 kit 视图时,我希望用户只有在做出选择后才能前进,这是工具包页面:
<div class="col-md-12">
<div class="alert alert-warning alert-dismissable" ng-show="controller.garments.data && controller.garments.data.length === 0">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
It appears that your sport does not have any garments associated with it.
</div>
<alert-error error="controller.garments.error"></alert-error>
<form ng-show="!controller.garments.loading && !controller.garments.error">
<div class="form-group">
<label class="sr-only" for="clubName">Club name</label>
<div class="input-group">
<div class="input-group-addon">1</div>
<input type="text" class="form-control" id="clubName" placeholder="Choose your teamwear">
</div>
</div>
<div class="picker garment-picker">
<ul class="picker-dropdown list-inline">
<li ng-repeat="garment in controller.garments.data" ng-class="{ 'active': controller.matchGarment(garment) }"><a href ng-click="controller.setGarment(garment)">{{ garment.title }}</a></li>
</ul>
</div>
</form>
<p><a class="btn btn-primary pull-right" ui-sref="designer.design">Design teamwear</a></p>
</div>
有谁知道我该怎么做?
如果需要,我可以提供更多信息。
我已经在 resolve 的帮助下自己回答了这个问题。
这是我现在的状态:
// Set up our state(s)
$stateProvider.state('designer', {
url: '/:sport/designer',
abstract: true,
templateUrl: '/app/designer/index.tpl.html',
controller: 'DesignerController',
controllerAs: 'controller',
resolve: {
model: ['DesignerService', function (service) {
console.log('hi');
// return our model
return service.get();
}]
}
}).state('designer.team', {
url: '',
templateUrl: '/app/designer/team.tpl.html',
data: {
pageTitle: 'Create your team'
}
}).state('designer.kit', {
url: '/kit',
templateUrl: '/app/designer/kit.tpl.html',
data: {
pageTitle: 'Choose your garments'
},
resolve: {
model: ['$q', 'DesignerService', function ($q, service) {
// Defer our promise
var deferred = $q.defer();
// Get our model
var model = service.get();
// If we have selected our colours and our team name
if (model.team.data.colours.length > 0 && model.team.data.name) {
// resolve our promise
deferred.resolve(model);
} else {
// Otherwise reject our promise
deferred.reject();
}
// Return our promise
return deferred.promise;
}]
}
}).state('designer.design', {
url: '/design',
templateUrl: '/app/designer/design.tpl.html',
data: {
pageTitle: 'Choose your design'
},
resolve: {
model: ['$q', 'DesignerService', function ($q, service) {
// Defer our promise
var deferred = $q.defer();
// Get our model
var model = service.get();
// If we have selected any garments
if (model.kit.data.garments.length > 0) {
// resolve our promise
deferred.resolve(model);
} else {
// Otherwise reject our promise
deferred.reject();
}
// Return our promise
return deferred.promise;
}]
}
}).state('designer.refine', {
url: '/refine',
templateUrl: '/app/designer/refine.tpl.html',
data: {
pageTitle: 'Refine your design'
},
resolve: {
model: ['$q', 'DesignerService', function ($q, service) {
// Defer our promise
var deferred = $q.defer();
// Get our model
var model = service.get();
// If we have selected our design
if (model.kit.data.design) {
// resolve our promise
deferred.resolve(model);
} else {
// Otherwise reject our promise
deferred.reject();
}
// Return our promise
return deferred.promise;
}]
}
}).state('designer.order', {
url: '/order',
templateUrl: '/app/designer/order.tpl.html',
data: {
pageTitle: 'Order your kit'
},
resolve: {
model: ['$q', 'DesignerService', function ($q, service) {
// Defer our promise
var deferred = $q.defer();
// Get our model
var model = service.get();
// TODO: check for the applied colours
if (model.kit.data.templates.length > 50) {
// resolve our promise
deferred.resolve(model);
} else {
// Otherwise reject our promise
deferred.reject();
}
// Return our promise
return deferred.promise;
}]
}
}).state('designer.save', {
url: '/save',
templateUrl: '/app/designer/save.tpl.html',
data: {
pageTitle: 'Save your kit',
requireLogin: true
}
});
我承认分辨率很大,但我会想办法把它们变小。
在旁注中,因为我正在使用 resolve 我可以将它注入我的控制器而无需再次调用该服务,即:
.controller('DesignerController', ['$stateParams', 'model', function ($stateParams, model) {
var self = this,
slug = $stateParams.sport;
// Kit model
self.model = model;
}])
注意: model 是在所有其他依赖项之后注入的。这很重要。
我正在使用 ui.router 创建我的视图并且我已经设置了这组状态:
.config(['$stateProvider', function ($stateProvider) {
// Set up our state(s)
$stateProvider.state('designer', {
url: '/:sport/designer',
abstract: true,
templateUrl: '/app/designer/index.tpl.html',
controller: 'DesignerController',
controllerAs: 'controller'
}).state('designer.team', {
url: '',
templateUrl: '/app/designer/team.tpl.html',
data: {
pageTitle: 'Create your team'
}
}).state('designer.kit', {
url: '/kit',
templateUrl: '/app/designer/kit.tpl.html',
data: {
pageTitle: 'Choose your garments'
}
}).state('designer.design', {
url: '/design',
templateUrl: '/app/designer/design.tpl.html',
data: {
pageTitle: 'Choose your design'
}
}).state('designer.refine', {
url: '/refine',
templateUrl: '/app/designer/refine.tpl.html',
data: {
pageTitle: 'Refine your design'
}
}).state('designer.order', {
url: '/order',
templateUrl: '/app/designer/order.tpl.html',
data: {
pageTitle: 'Order your kit'
}
}).state('designer.save', {
url: '/save',
templateUrl: '/app/designer/save.tpl.html',
data: {
pageTitle: 'Save your kit',
requireLogin: true
}
});
}])
索引模板如下所示:
<div class="container designer">
<div class="row designer-header">
<div class="col-md-6" ng-include="'/app/designer/tpls/header.tpl.html'">
</div>
<div class="col-md-6" ng-include="'/app/designer/tpls/navigation.tpl.html'">
</div>
</div>
<div class="row">
<div class="col-md-12" ng-include="'/app/designer/tpls/total.tpl.html'" ng-hide="controller.garments.loading">
</div>
</div>
<div class="row designer-body">
<ui-view></ui-view>
</div>
</div>
导航 包含如下所示:
<nav class="navbar navbar-designer">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="collapse navbar-collapse" id="designer-menu">
<ul class="nav navbar-nav navbar-right">
<li ui-sref-active="active"><a ui-sref=".team">Your team</a></li>
<li><a>|</a></li>
<li ui-sref-active="active"><a ui-sref=".kit">Kit</a></li>
<li><a>|</a></li>
<li ui-sref-active="active"><a ui-sref=".design">Design</a></li>
<li><a>|</a></li>
<li ui-sref-active="active"><a ui-sref=".refine">Refine</a></li>
<li><a>|</a></li>
<li ui-sref-active="active"><a ui-sref=".order">Order</a></li>
</ul>
</div>
</nav>
所以,我的想法是我想逐步构建它;即当页面首次加载时,我希望用户只有在填写完第一页后才能进入下一步(.kit),如下所示:
<div class="col-md-12">
<div class="alert alert-warning alert-dismissable" ng-show="controller.colours.data && controller.colours.data.length === 0">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
You must have at least one colour in the database before you can create a team / kit.
</div>
<alert-error error="controller.colours.error"></alert-error>
<form name="teamForm" novalidate ng-show="!controller.colours.loading && !controller.colours.error">
<div class="form-group">
<label class="sr-only" for="teamName">Team name</label>
<div class="input-group">
<div class="input-group-addon">1</div>
<input type="text" class="form-control" id="teamName" placeholder="Enter your team name" ng-model="controller.model.team.data.name" ng-change="controller.saveSession()" required>
</div>
</div>
<div class="form-group">
<label class="sr-only" for="colours">Colours</label>
<div class="picker colour-picker">
<div class="input-group">
<div class="input-group-addon">2</div>
<input type="text" class="form-control" id="colours" placeholder="Choose your colours" disabled>
</div>
<ul class="picker-dropdown list-inline form-control">
<li ng-repeat="colour in controller.colours.data" ng-class="{ 'active': controller.matchColour(colour) }">
<a href style="background-color: #{{ colour.hex }};" ng-click="controller.setColour(colour)"></a>
</li>
</ul>
</div>
</div>
</form>
<p><a class="btn btn-primary pull-right" ui-sref="designer.kit">Choose teamwear</a></p>
</div>
应禁用所有其他 "tabs"。然后类似地,当我前进到 kit 视图时,我希望用户只有在做出选择后才能前进,这是工具包页面:
<div class="col-md-12">
<div class="alert alert-warning alert-dismissable" ng-show="controller.garments.data && controller.garments.data.length === 0">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
It appears that your sport does not have any garments associated with it.
</div>
<alert-error error="controller.garments.error"></alert-error>
<form ng-show="!controller.garments.loading && !controller.garments.error">
<div class="form-group">
<label class="sr-only" for="clubName">Club name</label>
<div class="input-group">
<div class="input-group-addon">1</div>
<input type="text" class="form-control" id="clubName" placeholder="Choose your teamwear">
</div>
</div>
<div class="picker garment-picker">
<ul class="picker-dropdown list-inline">
<li ng-repeat="garment in controller.garments.data" ng-class="{ 'active': controller.matchGarment(garment) }"><a href ng-click="controller.setGarment(garment)">{{ garment.title }}</a></li>
</ul>
</div>
</form>
<p><a class="btn btn-primary pull-right" ui-sref="designer.design">Design teamwear</a></p>
</div>
有谁知道我该怎么做? 如果需要,我可以提供更多信息。
我已经在 resolve 的帮助下自己回答了这个问题。 这是我现在的状态:
// Set up our state(s)
$stateProvider.state('designer', {
url: '/:sport/designer',
abstract: true,
templateUrl: '/app/designer/index.tpl.html',
controller: 'DesignerController',
controllerAs: 'controller',
resolve: {
model: ['DesignerService', function (service) {
console.log('hi');
// return our model
return service.get();
}]
}
}).state('designer.team', {
url: '',
templateUrl: '/app/designer/team.tpl.html',
data: {
pageTitle: 'Create your team'
}
}).state('designer.kit', {
url: '/kit',
templateUrl: '/app/designer/kit.tpl.html',
data: {
pageTitle: 'Choose your garments'
},
resolve: {
model: ['$q', 'DesignerService', function ($q, service) {
// Defer our promise
var deferred = $q.defer();
// Get our model
var model = service.get();
// If we have selected our colours and our team name
if (model.team.data.colours.length > 0 && model.team.data.name) {
// resolve our promise
deferred.resolve(model);
} else {
// Otherwise reject our promise
deferred.reject();
}
// Return our promise
return deferred.promise;
}]
}
}).state('designer.design', {
url: '/design',
templateUrl: '/app/designer/design.tpl.html',
data: {
pageTitle: 'Choose your design'
},
resolve: {
model: ['$q', 'DesignerService', function ($q, service) {
// Defer our promise
var deferred = $q.defer();
// Get our model
var model = service.get();
// If we have selected any garments
if (model.kit.data.garments.length > 0) {
// resolve our promise
deferred.resolve(model);
} else {
// Otherwise reject our promise
deferred.reject();
}
// Return our promise
return deferred.promise;
}]
}
}).state('designer.refine', {
url: '/refine',
templateUrl: '/app/designer/refine.tpl.html',
data: {
pageTitle: 'Refine your design'
},
resolve: {
model: ['$q', 'DesignerService', function ($q, service) {
// Defer our promise
var deferred = $q.defer();
// Get our model
var model = service.get();
// If we have selected our design
if (model.kit.data.design) {
// resolve our promise
deferred.resolve(model);
} else {
// Otherwise reject our promise
deferred.reject();
}
// Return our promise
return deferred.promise;
}]
}
}).state('designer.order', {
url: '/order',
templateUrl: '/app/designer/order.tpl.html',
data: {
pageTitle: 'Order your kit'
},
resolve: {
model: ['$q', 'DesignerService', function ($q, service) {
// Defer our promise
var deferred = $q.defer();
// Get our model
var model = service.get();
// TODO: check for the applied colours
if (model.kit.data.templates.length > 50) {
// resolve our promise
deferred.resolve(model);
} else {
// Otherwise reject our promise
deferred.reject();
}
// Return our promise
return deferred.promise;
}]
}
}).state('designer.save', {
url: '/save',
templateUrl: '/app/designer/save.tpl.html',
data: {
pageTitle: 'Save your kit',
requireLogin: true
}
});
我承认分辨率很大,但我会想办法把它们变小。 在旁注中,因为我正在使用 resolve 我可以将它注入我的控制器而无需再次调用该服务,即:
.controller('DesignerController', ['$stateParams', 'model', function ($stateParams, model) {
var self = this,
slug = $stateParams.sport;
// Kit model
self.model = model;
}])
注意: model 是在所有其他依赖项之后注入的。这很重要。