这是一款angularJs应用程序,可以帮助您为类似bookmyshow的电影节预订座位。
用户可以做什么(用户案例)?
选择并取消选择相对于selectedVal的座位,即如果 selectedVal = 4然后用户总共只能选择4个席位。
如果SelectedVal小于1,则用户不应该 除非用户取消选择任何一个,否则选择座位 之前选择的座位并再次选择。
预订座位案例:如果座位的检查值为真,那么 用户不应该选择或取消选择该座位(a.blocked 为此目的添加了CSS规则),因为它已被选中 另一个用户(让我们假设)。
如GIF所示
如果有4个席位。
问题:
我可以使用angular.forEach()
实现自动选择过程,但不能正确使用所有逻辑。
$scope.execute = function(i, j, itemVal, itemLetter) {
angular.forEach($scope.obj, function(v, k) {
if (v[i].val == itemVal && v[i].letter == itemLetter) {
if (v[i].seat == true || ($scope.isDisabled && v[i].check == false)) {
return;
}
v[i].check = !v[i].check;
if (v[i].check)
$scope.selectedVal -= 1;
else
$scope.selectedVal += 1;
//seatSelection
var m = i;
for (var l = 0; l < $scope.selectedVal; l++)
v[m++].check = true;
//seatSelectionEnd
console.log(itemVal + " " + itemLetter);
if ($scope.selectedVal < 1) {
$scope.isDisabled = true;
} else {
$scope.isDisabled = false;
}
}
});
};
}])
答案 0 :(得分:1)
你的循环逻辑有点难以理解,但更关键的是,不必要。它不是循环遍历整个集合的click函数,而是直接与绑定到被单击元素的对象进行交互。
将锚元素绑定更改为:ng-click="clickSeat(item)"
,并使用控制器上的函数,如下所示:
$scope.clickSeat = function(seat) {
if (!seat.seat && !$scope.isDisabled) {
if (seat.check) {
seat.check = false;
$scope.selectedSeatCount--;
} else if ($scope.selectedSeatCount < $scope.selectedVal) {
seat.check = true;
$scope.selectedSeatCount++;
}
}
}
这是一个更新的小提琴:https://jsfiddle.net/5vqxgtq3/12/
我不知道这是否会捕获所有您正在寻找的功能,但希望有效地证明逻辑在不再适用时更容易推理依赖于循环,你可以从那里扩展它。
答案 1 :(得分:1)
我已使用以下几点更改了代码以实现逻辑:
seats = [ [Obj0, Obj1, Obj2], [Obj3, Obj4, Obj5] ]
rang
属性以创建不同行组的部分。我想我已经实现了所有用例。
请查看下面的演示或fiddle。
我的代码也非常复杂,但我认为由于其他选择的更新,循环是必需的。
angular.module('bookYourSeatApp', [])
.factory('seats', SeatsFactory)
.controller('mainCtrl', MainCtrl);
function SeatsFactory($rootScope, $timeout) {
var seatProps = {
id: 0,
caption: 0,
checked: false,
booked: false
};
var seats = {
'firstRang': {
// col0 1 2 3 4 5
// row 0 seat 0 1 2 3 4 5
// row 1 seat 6 7 8 9 10 11
seats: createSeats(2, 6) // rows, cols
},
'secondRang': {
seats: createSeats(3, 6)
}
};
function createSeats(rows, cols) {
var arr = [[]];
var seatIndex = 0;
for (var row = 0; row < rows; row++) {
arr[row] = [];
for(var col=0; col < cols; col++) {
var seat = angular.extend({}, seatProps, {
id: seatIndex,
caption: seatIndex,
booked: seatIndex < 5 // 0 to 5 booked
});
arr[row][col] = seat;
seatIndex++;
}
}
return arr;
}
function checkSelected(newCount) {
// selected fewer or more than persons in select.
// --> uncheck all
var checkedCount=0, keys = Object.keys(seats);
for (var rang=0; rang < keys.length; rang++) {
var key = keys[rang];
var curSeats = seats[key].seats;
for (var row=0; row < curSeats.length; row++) {
for (var col=0; col < curSeats[row].length; col++) {
if ( curSeats[row][col].checked ) {
checkedCount++;
}
}
}
//console.log('new count', newCount, checkedCount);
// we can have more or less selections after selection change
// --> more inc availCount
if (checkedCount === 0) {
// nothing selected
factory.availCount = angular.copy(newCount);
}
else if (newCount.val > checkedCount) {
//console.log('add delta', newCount, checkedCount)
factory.availCount.val = (newCount.val - checkedCount);
} else {
removeAllCheck();
}
}
}
function removeCheck(rang) {
// later pass user to this function (for now remove all checked)
/*var curSeats = seats[rang].seats
for (var row=0; row < curSeats.length; row++) {
for (var col=0; col < curSeats[row].length; col++) {
curSeats[row][col].checked = false;
}
}*/
keys = Object.keys(seats);
for (var rang=0; rang < keys.length; rang++) {
var key = keys[rang];
var curSeats = seats[key].seats;
for (var row=0; row < curSeats.length; row++) {
for (var col=0; col < curSeats[row].length; col++) {
curSeats[row][col].checked = false;
}
}
}
}
function removeAllCheck() {
keys = Object.keys(seats);
for (var rang=0; rang < keys.length; rang++) {
var key = keys[rang];
var curSeats = seats[key].seats;
for (var row=0; row < curSeats.length; row++) {
for (var col=0; col < curSeats[row].length; col++) {
curSeats[row][col].checked = false;
}
}
}
}
function selectSeats(selection, count) {
// todo:
// check distance to border, keep the rest as clickable
// selection = {rang, row, seat}
console.log(selection);
var row = selection.row,
seat = selection.seat;
if ( !seat.booked ) {
//console.log('availCount', factory.availCount);
if ( factory.availCount.val == 0 ) {
//console.log('new selection');
factory.availCount = angular.copy(count);
removeCheck(); //selection.rang);
}
var borderDistance = row.length - row.indexOf(seat),
rest = borderDistance > count.val ? 0: count.val - borderDistance;
if ( factory.availCount.val === count.val) {
// first click
var lastIndex = rest > 0 ? row.length: row.indexOf(seat) + count.val;
for ( var seatIndex = row.indexOf(seat); seatIndex < lastIndex; seatIndex++) {
row[seatIndex].checked = true;
}
factory.availCount.val = rest; // update available seats
}
else {
// second click dec. availCounter
// single change of seats
/*if ( factory.availCount.val < 0 ) {
row[row.indexOf(seat)].checked = false; // remove check
factory.availCount.val++;
}
else {*/
if ( !row[row.indexOf(seat)].checked ) {
// only if not already checked
row[row.indexOf(seat)].checked = true;
if ( factory.availCount.val > 0 ) {
factory.availCount.val--;
}
}
//}
}
}
}
var factory = {
map: seats,
select: selectSeats,
availCount: {},
setAvailCount: function(count) {
console.log('avail', count);
checkSelected(count);
}
};
return factory
}
function MainCtrl(seats) {
var vm = this;
angular.extend(vm, {
seats: seats,
selectionCount: [//[0,1,2,3,4],[
{id: 0, val: 0}, // object for two-way binding
{id: 1, val: 1},
{id: 2, val: 2},
{id: 3, val: 3},
{id: 4, val: 4},
],
selectedCount: 0
});
vm.selectedCount = vm.selectionCount[2];
seats.setAvailCount(vm.selectedCount);
}
table {
border: 1px solid black;
padding: 0.5em;
}
td {
padding: 1em;
border: 2px solid gray;
}
td:hover {
cursor: default;
background-color: gray;
}
.active {
border: 2px solid lightgreen;
border-radius: 5px;
}
.booked {
background-color: lightgray;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="bookYourSeatApp" ng-controller="mainCtrl as ctrl">
<label>Persons <select ng-model="ctrl.selectedCount" ng-change="ctrl.seats.setAvailCount(ctrl.selectedCount)" ng-options="count as count.val for count in ctrl.selectionCount"></select></label>
Seats left: {{ctrl.seats.availCount.val}}<br/>
<table ng-repeat="(key, rang) in ctrl.seats.map">
<tr ng-repeat="row in rang.seats">
<td ng-repeat="seat in row" ng-class="{'active': seat.checked, 'booked': seat.booked}" ng-click="ctrl.seats.select({rang:key, row:row, seat: seat}, ctrl.selectedCount)">
{{seat.caption}}
</td>
</tr>
</table>
<pre>{{ctrl.seats.map | json : 2}}</pre>
</div>