Now in my records :
14.3, 14.2 and 14.1 belongs to part with Id =30.
I am trying to achieve below:
1) By default first 2 ids will be selected.Now if user try to select id = 71 which belongs to part 30 then user should not be allowed to select id=71 because higher version of part 30 is already selected i.e id=76.
2) Now if user uncheck id = 77(33) then user should be allowed to check id=71 because now there is no different part selected so user should be allow to check all part with id = 30 but as soon as user select different part then lower part should be uncheck.
Problem with my code :
1) When I uncheck 16.1 and try to check 14.2 then I am not allowed to check it. I should allow to check 14.2 as now there is no different parts here.
2) 16.1 and 14.3 are check by default. Now when I check 15.1 and then again check 14.1 then 14.3 gets uncheck which is wrong as 14.3 is highest among part id=30 so I should not be able to check 14.1.
var app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope) {
$scope.myArray = [
{
"id": 77,
"selected": true,
"part": 33,
"name": "16.1",
},
{
"id": 76,
"part": 30,
"selected": true,
"name": "14.3",
},
{
"id": 71,
"part": 30,
"selected": false,
"name": "14.2",
},
{
"id": 70,
"part": 31,
"selected": false,
"name": "15.1",
},
{
"id": 69,
"part": 30,
"selected": false,
"name": "14.1",
},
{
"id": 68,
"part": 29,
"selected": false,
"name": "13.1",
},
{
"id": 55,
"part": 26,
"selected": false,
"name": "12.1",
}
,
{
"id": 54,
"part": 25,
"selected": false,
"name": "11.2",
}
,
{
"id": 53,
"part": 25,
"selected": false,
"name": "11.1",
}
];
$scope.checkItem = function (item) {
if (item.selected) {
var index = $scope.myArray.map(m=>m.id).indexOf(item.id);
var previousPart = {};
for (var i = index - 1; i >= 0; i--) {
if ($scope.myArray[i].selected) {
previousPart = $scope.myArray[i];
break;
}
}
if (item.part != previousPart.part) {
for (var i = 0; i < $scope.myArray.length; i++) {
if (($scope.myArray[i].part == item.part && $scope.myArray[i].part != item.part)
&& $scope.myArray[i].selected) {
$scope.myArray[i].selected = false;
break;
}
}
}
else
item.selected = false;
}
};
});
<!DOCTYPE html>
<html ng-app="myApp" ng-controller="myCtrl">
<head>
<title></title>
<meta charset="utf-8" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
</head>
<body>
<div ng-repeat="item in myArray">
<input ng-model="item.selected" ng-click="checkItem(item)" type="checkbox" />{{ item.name }}
</div>
</body>
</html>
To update an object's property in an array of objects, use the map() method to iterate over the array. On each iteration, check if the current object is the one to be updated. If it is, modify the object and return the result, otherwise return the object as is.
Our function should search the first array for objects with the same "id" property that is present in the second array. Then our function should replace the "name" property of those objects with the corresponding "name" property of the second array's objects.
A nested data structure is an array or object which refers to other arrays or objects, i.e. its values are arrays or objects. Such structures can be accessed by consecutively applying dot or bracket notation. Here is an example: const data = { code: 42, items: [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }] };
To change the value of all elements in an array:Use the forEach() method to iterate over the array. The method takes a function that gets invoked with the array element, its index and the array itself. Use the index of the current iteration to change the corresponding array element.
I would take a different approach. Separating some of the logic into a service helps me keep the code cleaner. It will be easier to maintain, debug and test. fiddle
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, myCollection) {
$scope.myArray = myCollection.items;
// Call function every time an item was checked
$scope.checkItem = function(item) {
// Remap collection items before and after
myCollection.mapCheckedItems();
// Do something with the user's interaction only if there are
// different selected parts by definition
if (item.selected && myCollection.selectedPartsOnly.length > 1) {
// Iterate through the selected parts
myCollection.selectedPartsOnly.map(part => {
// Get the array of items belonging to the exact part number
var map = myCollection.selectedPartsMap[part];
for (var j = map.length - 1; j > 0; j--) {
// By definition deselect all but the highest version.
// Happens if different part numbers selected simultaneously
map[j].selected = false;
}
})
}
// Recalculate collection map to keep it up to date with the
// items' array
myCollection.mapCheckedItems();
};
});
app.service('myCollection', function() {
// Init the collection object
var self = {};
// Function to calculate and map items' dependencies
self.mapCheckedItems = mapCheckedItems;
// This holds a list of the selected unique part numbers
// Used to determine needed action easier. By definition if only
// one part number is selected and used to iterate through the map
self.selectedPartsOnly = [];
// This is the important dictionary where the part numbers is mapped
// to its child items. Easy access to items grouped by a part number
self.selectedPartsMap = {};
// The actual array definition
self.items = [{
"id": 77,
"selected": true,
"part": 33,
"name": "16.1",
}, {
"id": 76,
"part": 30,
"selected": true,
"name": "14.3",
}, {
"id": 71,
"part": 30,
"selected": false,
"name": "14.2",
}, {
"id": 70,
"part": 31,
"selected": false,
"name": "15.1",
}, {
"id": 69,
"part": 30,
"selected": false,
"name": "14.1",
}, {
"id": 68,
"part": 29,
"selected": false,
"name": "13.1",
}, {
"id": 55,
"part": 26,
"selected": false,
"name": "12.1",
}, {
"id": 54,
"part": 25,
"selected": false,
"name": "11.2",
}, {
"id": 53,
"part": 25,
"selected": false,
"name": "11.1",
}];
// Init the helpers once on start. This will be executed only once
mapCheckedItems();
// Return the service object to be accessed from the controller
return self;
// This function will create and update the objects mapping
function mapCheckedItems() {
// Reset the helpers
self.selectedPartsOnly = [];
self.selectedPartsMap = {};
// Now we iterate through the selected items.
self.items
.filter(item => item.selected)
.map(item => {
// Map every selected item directly to one part number
mapSelectedParts(item);
// Determine what part numbers are in use.
mapSelectedPartsOnly(item.part);
})
}
function mapSelectedPartsOnly(part) {
if (self.selectedPartsOnly.indexOf(part) == -1)
self.selectedPartsOnly.push(part);
}
function mapSelectedParts(item) {
if (!self.selectedPartsMap[item.part])
self.selectedPartsMap[item.part] = [];
self.selectedPartsMap[item.part].push(item);
}
})
<!DOCTYPE html>
<html ng-app="myApp" ng-controller="myCtrl">
<head>
<title></title>
<meta charset="utf-8" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
</head>
<body>
<div ng-repeat="item in myArray">
<input ng-model="item.selected" ng-click="checkItem(item)" type="checkbox" />{{ item.name }}
</div>
</body>
</html>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With