I would like to get the results like the following manner,
Expected work flow chart,
Here the default view,
Scenario 1: When click on the number "1" all the left to right and children need to highlight like the below,
Scenario 2: Considering the scenario 1 results, click on the number "3" all the left to right and children need to remove highlight like the below since 3 we consider as parent/root,
Scenario 3: Considering the default view, By default there is no selection When click on the number "18" all the parent values need to highlight like the below,
Scenario 4: Considering the Scenario 3 results , When click on the number "18" only for 18 the highlight need to be removed and like the below, Right to left parent level deselection not required for any value.
Note: While clicking on any value Right to left parent level deselection not required. In this case only clicked value need to remove highlight.
Here is the code: JSFiddle
$scope.setActiveSelectedItem = function() {
return $scope.groupOfCheckboxes[i].RowValues[j].isActive = !$scope.groupOfCheckboxes[i].RowValues[j].isActive;
}
$scope.setActivePrevNext = function(arr, id) {
let keys = Object.keys(arr);
let nextIndex = keys.indexOf(id) +1;
let nextItem = keys[nextIndex];
return $scope.groupOfCheckboxes[i].RowValues[nextIndex].isActive = !$scope.groupOfCheckboxes[i].RowValues[nextIndex].isActive;
}
$scope.setBinary = function (id) {
for(i=0; i<$scope.groupOfCheckboxes.length; i++) {
for(j=0; j<$scope.groupOfCheckboxes[i].RowValues.length; j++) {
if($scope.groupOfCheckboxes[i].RowValues[j].td == id) {
$scope.setActiveSelectedItem();
$scope.setActivePrevNext($scope.groupOfCheckboxes, id);
}
}
}
}
});
Html
<table>
<tr ng-repeat="checkbox in groupOfCheckboxes track by $index" ng-init="rowId = $index">
<td ng-repeat="data in checkbox.RowValues track by $index" ng-init="vId = $index">
<span ng-if="data.show" ng-click="setBinary(rowId,vId,data)"
ng-class="data.isActive ? 'active' : ''">{{data.td}}</span>
</td>
</tr>
</table>
Controller
$scope.groupOfCheckboxes = [
{
Row: "1",
RowValues: [
{ td: "1", show: true },
{ td: "2", show: true },
{ td: "3", show: true },
{ td: "4", show: true },
{ td: "5", show: true }
]
},
{
Row: "2",
RowValues: [
{ td: "6", show: false },
{ td: "7", show: false },
{ td: "8", show: false },
{ td: "9", show: true },
{ td: "10", show: false }
]
},
{
Row: "3",
RowValues: [
{ td: "11", show: false },
{ td: "12", show: false },
{ td: "13", show: true },
{ td: "14", show: true }
]
},
{
Row: "4",
RowValues: [
{ td: "15", show: false },
{ td: "16", show: false },
{ td: "17", show: false },
{ td: "18", show: true }
]
}
];
// Setting Parents
for (let rowIndex = $scope.groupOfCheckboxes.length - 1; rowIndex >= 0; rowIndex--) {
for (let valIndex = $scope.groupOfCheckboxes[rowIndex].RowValues.length - 1; valIndex >= 0; valIndex--) {
$scope.groupOfCheckboxes[rowIndex].RowValues[valIndex].isActive = false;
if ($scope.groupOfCheckboxes[rowIndex].RowValues[valIndex].show == true) {
loop4:
for (let rx = rowIndex; rx >= 0; rx--) {
for (let vx = valIndex - 1; vx >= 0; vx--) {
if ($scope.groupOfCheckboxes[rx].RowValues[vx].show == true) {
$scope.groupOfCheckboxes[rowIndex].RowValues[valIndex].pri = rx;
$scope.groupOfCheckboxes[rowIndex].RowValues[valIndex].pvi = vx;
break loop4;
};
}
}
};
}
}
$scope.setBinary = function (rowId, vId, data) {
data.isActive = !data.isActive
bool = data.isActive;
loopx:
for (let row = rowId; row < $scope.groupOfCheckboxes.length; row++) {
loop1:
for (let v = vId; v < $scope.groupOfCheckboxes[row].RowValues.length; v++) {
if (row == rowId) {
if ($scope.groupOfCheckboxes[row].RowValues[v].show == true) {
$scope.groupOfCheckboxes[row].RowValues[v].isActive = bool;
} else {
break;
};
} else {
if (v == vId) {
if ($scope.groupOfCheckboxes[row].RowValues[v].show == true) {
break loopx;
}
} else {
if ($scope.groupOfCheckboxes[row].RowValues[v].show == true) {
$scope.groupOfCheckboxes[row].RowValues[v].isActive = bool;
}
}
}
}
}
function rec(pri, pvi) {
if ($scope.groupOfCheckboxes[pri]) {
$scope.groupOfCheckboxes[pri].RowValues[pvi].isActive = true;
x = $scope.groupOfCheckboxes[pri].RowValues[pvi]
rec(x.pri, x.pvi)
}
}
rec(data.pri, data.pvi)
}
Related
I have Items data which I am attempting to display array values sorted by cost field in costtable array when roomname is Double and type is 2.Here is my code:
Json:
{
"index": 1,
"id": "5e3961face022d16a03b1de9_1023632_1004876",
"costtable": [
{
"roomname": "Single",
"room_id": "1023632_479490,1004876_385485",
"family": [
{
"title": "adult 1",
"cost": 3.7568000,
"unit": "10",
"type": "2"
}
]
}
]
},
{
"index": 2,
"id": "5e3961face022d16a03b1de9_1088496_1005362",
"costtable": [
{
"roomname": "Double",
"room_id": "1088496_447339,1005362_415279",
"family": [
{
"title": "adult 1",
"cost": 5.6868000,
"unit": "10",
"type": "2"
}
]
}
]
},
{
"index": 3,
"id": "5e3961face022d16a03b1de9_1141859_1005529",
"costtable": [
{
"roomname": "Single",
"room_id": "1141859_74888,1005529_870689",
"family": [
{
"title": "adult 1",
"cost": 5.9586000,
"unit": "10",
"type": "2"
}
]
}
]
}
]
Code:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
Items: [],
library: null,
perPage: 20,
currentPage: 1,
maxPage: null,
}
}
componentDidMount() {
fetch('/json', {
method: 'GET',
})
.then(response => response.text())
.then(text => {
let Maindata = JSON.parse(text.replace(/\'/g, '"'))
let CostSort = Maindata.map(a => {
return this.renderSort(a)
})
Maindata.sort((a, b) => a.CostSort - b.CostSort);
this.setState(state => ({
...state,
Items: Maindata
}), () => {
this.reorganiseLibrary()
})
}).catch(error => console.error(error))
}
reorganiseLibrary = () => {
const { perPage, Items } = this.state;
let library = Items;
library = _.chunk(library, perPage);
this.setState({
library,
currentPage: 1,
maxPage: library.length === 0 ? 1 : library.length
});
};
renderSort(element) {
let indents = []
let lenFamilies = element.costtable.length
for (let i = 0; i < lenFamilies; i++) {
if (element.costtable[i].roomname.indexOf('Double') > -1) {
for (let j = 0; j < element.costtable[i].family.length; j++) {
if (element.costtable[i].family[j].type == 2) {
indents.push(element.costtable[i].family[j].cost)
break;
}
}
break;
}
}
return (indents)
}
// Previous Page
previousPage = event => {
this.setState({
currentPage: this.state.currentPage - 1
});
};
// Next Page
nextPage = event => {
this.setState({
currentPage: this.state.currentPage + 1
});
};
// handle per page
handlePerPage = (evt) =>
this.setState({
perPage: evt.target.value
}, () => this.reorganiseLibrary());
// handle render of library
renderLibrary = () => {
const { library, currentPage } = this.state;
if (!library || (library && library.length === 0)) {
return '';
}
return library[currentPage - 1].map((item, i) => (
<div className="item-list">
{item.index}
</div>
));
};
render() {
const { library, currentPage, perPage, maxPage } = this.state;
return (
<div>
<div className="wrapper-data">
{this.renderLibrary()}
</div>
<div class="clr"></div>
<ul id="page-numbers">
<li className="nexprevPage">
{currentPage !== 1 && (
<button onClick={this.previousPage}><span className="fa-backward"></span></button>
)}
</li>
<li className="controlsPage active">{this.state.currentPage}</li>
<li className="restControls">...</li>
<li className="controlsPage">{this.state.maxPage}</li>
<li className="nexprevPage">
{(currentPage < maxPage) && (<button onClick={this.nextPage}><span className="fa-forward"></span></button>
)}
</li>
</ul>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('Content'));
This code does not give me any errors but displays the values in an unsorted format. How can I sort it?
New Code
Maindata.sort((a, b) => {
let lenFamilies = a.costtable.length
for (let i = 0; i < lenFamilies; i++) {
if( a.costtable[i].roomname.indexOf('Double') > -1){
for (let j = 0; j < a.costtable[i].family.length; j++) {
if( a.costtable[i].family[j].type == 2){
a.costtable[i].family[j].cost- b.costtable[i].family[j].cost
}
}
}
}
}
I do not understand the exact formula that you are using to sort, but what you are doing before the sort is wrong.
In your componentDidMount
let CostSort = Maindata.map(a => { return this.renderSort(a) })
This returns an array into a variable called CostSort and does not affect MainData in any way.
However, later on you do this.
Maindata.sort((a, b) => a.CostSort - b.CostSort);
For first iteration, this will compare Maindata[0] and Maindata[1]. Note that there is no CostSort in either of the objects and hence you are performing operation of undefined - undefined which is NaN. Therefore no sorting happens.
I would suggest you use only the sort function and do your comparison between two values there.
Maindata.sort((a, b) => {
// Do your calculation here
if(a should be before b) {
return -1;
} else {
return 1;
}
}
P.S The convention for variable in js is camelCase and not PascalCase. So, Maindata should he mainData.
EDIT:
Here is a simple sort implementation which works for the above case, you can expand on it according to your full use case.
Maindata.sort((a, b) => {
let lenFamilies = a.costtable.length;
for (let i = 0; i < lenFamilies; i++) {
if (
a.costtable[i].roomname.includes("Double") &&
!b.costtable[i].roomname.includes("Double")
) {
return -1;
}
if (
!a.costtable[i].roomname.includes("Double") &&
b.costtable[i].roomname.includes("Double")
) {
return 1;
}
if (a.costtable[i].roomname.indexOf("Double") > -1) {
for (let j = 0; j < a.costtable[i].family.length; j++) {
if (a.costtable[i].family[j].type == 2) {
a.costtable[i].family[j].cost - b.costtable[i].family[j].cost;
}
}
}
}
});
Omitting the algorithms (bubble, quicksort, by inserting ...). There is possible of sorting in UI context.
Your json have:
title | cost | unit | type
What type of sort You need? (title is string (can eg. sort alphabetically), then cost, unit & type are number (ascending + descending)
It's will be helpfull - when in future You provide only neccessary piece of code.
Here it's ellegant minimalistic function responsible for asc/desc sorting.
Firstly it's need to pass the props(which You wan't to sort) to values state.
function App() {
const [ascValue, setAscValue] = useState(true);
const [values, setValues] = useState([10, 5, 12, 1, 2, 900, 602]);
function sortValues() {
const compare = ascValue ? (a, b) => a - b : (a, b) => b - a;
setValues([...values].sort(compare));
}
useEffect(() => {
sortValues();
}, [ascValue]);
return (
<div>
<h3>{ascValue.toString()}</h3>
<button onClick={() => setAscValue(!ascValue)}>Toggle Asc</button>
{values.map(v => (
<p key={v}>{v}</p>
))}
</div>
);
}
Here is sorting by cost for your object:
let text = [{
"index": 1,
"id": "5e3961face022d16a03b1de9_1023632_1004876",
"costtable": [
{
"roomname": "Single",
"room_id": "1023632_479490,1004876_385485",
"family": [
{
"title": "adult 1",
"cost": 3.7568000,
"unit": "10",
"type": "2"
}
]
}
]
},
{
"index": 2,
"id": "5e3961face022d16a03b1de9_1088496_1005362",
"costtable": [
{
"roomname": "Double",
"room_id": "1088496_447339,1005362_415279",
"family": [
{
"title": "adult 1",
"cost": 5.6868000,
"unit": "10",
"type": "2"
}
]
}
]
},
{
"index": 3,
"id": "5e3961face022d16a03b1de9_1141859_1005529",
"costtable": [
{
"roomname": "Single",
"room_id": "1141859_74888,1005529_870689",
"family": [
{
"title": "adult 1",
"cost": 5.9586000,
"unit": "10",
"type": "2"
}
]
}
]
}
]
const App = () =>{
const usersWithName = Object.keys(text).map(function(key) {
var user = text[key];
return user.costtable[0].family[0].cost;
});
let costArray = usersWithName
const [ascValue, setAscValue] = useState(true);
const [values, setValues] = useState(costArray);
function sortValues() {
const compare = ascValue ? (a, b) => a - b : (a, b) => b - a;
setValues([...values].sort(compare));
}
useEffect(() => {
sortValues();
}, [ascValue]);
return (
<div>
<h3>{ascValue.toString()}</h3>
<button onClick={() => setAscValue(!ascValue)}>Toggle Asc</button>
{values.map(v => (
<p key={v}>{v}</p>
))}
</div>
);
}
export default App;
I don't have idea of performance in this case + if in your json are more costtable & family it should iterate by [i] iterator.
json Structure:
{
"id" : "1",
"Data" : [
{
"name" : "abc",
},
{
"name" : "option1",
"position" : [
{
"name" : "option1",
"status" : [
{
"code" : "0",
"value" : "OFF"
},
{
"code" : "1",
"value" : "ON"
}
]
}]
} ]
}
Here,I want to get the data from above complex Json structure.How to do that,
Have tried below code but giving error like;
error: uncaughtException: Cannot read property 'status' of undefined
function myfunc(req,res){
var collectionname = db.collection("col1");
collectionname.find({}).each(function(err, doc) {
if(doc != null)
{
var fdata = [];
for(var i =0;i<doc.Data.length;i++){
fdata.push(doc.Data[i].position.status);
}
console.log("fdata............",fdata);
}
});
}
Please help with the same.
You can use foreach for prevent length undefined.
function myfunc(req,res)
{
let collectionname = db.collection("col1");
collectionname.find({}).each(function(err, doc)
{
if(doc != null)
{
let fdata = [];
for(let i in doc.Data)
{
for(let j in doc.Data[i].position)
{
fdata.push(doc.Data[i].position[j].status);
}
}
console.log("fdata............", fdata);
}
});
}
#MikaelLennholm have right, for(let i in doc.Data) works but not recommanded, be careful not to use it in prototyped or object-built arrays.
EDIT:
function myfunc(req,res)
{
db.collection('col1').find({}).each(function(err, doc)
{
if(err)
{
console.log('[INFOS] Request fail, more details:\n', err);
}
else if(doc)
{
let fdata = [];
if(doc.Data && doc.Data.length)
{
for(let i = doc.Data.length-1; i >= 0; i--)
{
if(doc.Data[i].position && doc.Data[i].position.length)
{
for(let j = doc.Data[i].position.length-1; j >= 0; j--)
{
if(doc.Data[i].position[j].status)
{
fdata = fdata.concat(doc.Data[i].position[j].status);
}
}
}
}
}
console.log("[INFOS] Datas:\n", fdata);
}
});
}
im a newbie at nodejs, hope this's correctly
//I assume this is a object or you can convert from string to object
var data = {
"id": "1",
"Data": [
{
"name": "option1",
"position": [
{
"name": "option1",
"status": [
{
"code": "0",
"value": "OFF"
},
{
"code": "1",
"value": "ON"
}
]
}]
}]
}
var statusArr = data.Data[0].position[0].status;
console.log(...statusArr);
Result: { code: '0', value: 'OFF' } { code: '1', value: 'ON' }
Parse through position array as well
function myfunc(req,res){
var collectionname = db.collection("col1");
collectionname.find({}).each(function(err, doc) {
if(doc != null)
{
var fdata = [];
for(var i =0;i<doc.Data.length;i++){
for(var j =0;j<doc.Data[i].position.length;j++){
fdata.push(doc.Data[i].position[j].status);
}
}
console.log("fdata............",fdata);
}
});
}
I have one array that contain all the office list. another array is user selected list. so now I want to display all officelist and if the value in selected list is the same with office list then the checkbox will be checked. This is how I did it. Code
<div *ngFor="let item of officeLIST">
<div *ngFor="let officeDATA of allOffice.office">
<div *ngIf="item.office_id == officeDATA.office_id">
<input #officeArray type="checkbox" id="officeArray" name="officeArray" class="form-control" value="{{item.officename}}"
checked> {{(item.officename == "" ? "--No data--" : item.officename)}}
</div>
<div *ngIf="item.office_id != officeDATA.office_id">
<input #officeArray type="checkbox" id="officeArray" name="officeArray" class="form-control" value="{{item.officename}}"> {{(item.officename == "" ? "--No data--" : item.officename)}}
</div>
</div>
</div>
and the result is
My officeLIST
this.officeLIST = [
{ "office_id": "1", "officename": "Sun Dept" },
{ "office_id": "2", "officename": "Moon" },
{ "office_id": "3", "officename": "Stars" }
]
allOffice.office array
"office": [
{
"office_id": "1",
"officename": "Sun Dept"
},
{
"office_id": "2",
"officename": "Moon Dept"
}
]
use this solution.this works fine for me. I have done all the things in constructor .if you want this in a method simply use the code block inside the constructor.
this is my ts file:
officeLIST: Array<any> = [
{ "office_id": "1", "officename": "Sun Dept" },
{ "office_id": "2", "officename": "Moon" },
{ "office_id": "3", "officename": "Stars" }
];
office: Array<any> = [
{
"office_id": "1",
"officename": "Sun Dept"
},
{
"office_id": "2",
"officename": "Moon Dept"
}
];
newArray: Array<any> = [];
constructor() {
for (var i = 0; i < this.officeLIST.length; i++) {
var ismatch = false; // we haven't found it yet
for (var j = 0; j < this.office.length; j++) {
if (this.officeLIST[i].office_id == this.office[j].office_id) {
// we have found this.officeLIST[i]] in this.office, so we can stop searching
ismatch = true;
this.officeLIST[i].checked = true;// checkbox status true
this.newArray.push(this.officeLIST[i]);
break;
}//End if
// if we never find this.officeLIST[i].office_id in this.office, the for loop will simply end,
// and ismatch will remain false
}
// add this.officeLIST[i] to newArray only if we didn't find a match.
if (!ismatch) {
this.officeLIST[i].checked = false;// checkbox status false
this.newArray.push(this.officeLIST[i]);
} //End if
}
console.log(this.newArray);
}
this is my html:
<div *ngFor="let item of newArray">
<input type="checkbox" [checked]="item.checked"> {{item.officename}}
</div>
Your user selected array will have ids of selected checkboxes.
Suppose he had selected Sun Dept and Moon, then
this.userSelectedArray = ["1","2"];
<div *ngFor="let item of officeLIST">
<input type="checkbox" [attr.checked]="userSelectedArray.indexOf(item.office_id) !== -1 ? true : false">
</div>
I need to create a JSON structure like this:
"combinationsData":[
{
"combinationName":"2_2",
"dataGroups": [
{
"tableType":"2",//This value comes from HTML
"twoAxisData":[{
"vAxis":18,//This value also comes from HTML
"dataValue":[
{//Need to iterate the hAxis. I need to add a loop to iterate this value
"hAxis":"03",
"dataValue":"0.7750"
},{
"hAxis":"04",
"dataValue":"1.48"
},{
"hAxis":"05",
"dataValue":"1.48"
},{
.
.
.
"hAxis":"08",
"dataValue":"0.06833"
}
]
},
{
"vAxis":20,
"dataValue":[
{
"hAxis":"01",
"dataValue":"1.48"
},{
"hAxis":"02",
"dataValue":"1.48"
},{
"hAxis":"03",
"dataValue":"1.48"
},{
"hAxis":"04",
"dataValue":"1.48"
},{
"hAxis":"05",
"dataValue":"1.48"
},{
"hAxis":"06",
"dataValue":"1.48"
},{
"hAxis":"07",
"dataValue":"1.48"
}
]
}]
},
{
"tableType":"1",
"oneAxisData":[
{
"vAxis":"18",
"dataValue":"1.48"
},
{
"vAxis":"19",
"dataValue":"1.48"
},
{ "vAxis":"19",
"dataValue":"1.48"
}
]
}
]
},
]
}
This is my controller code, in which I am getting some values from HTML and based on the values I need to iterate a loop in JSON. I am not getting how to add a loop inside JSON as it is an object.
mapData = function() {
"combinationData": {
"combinationName": "2_2",
"dataGroups": {
"tableType": "2",
"twoAxisData": {
for (var i = 0; i < 5; i++) { //Need to add a loop like this to iterate till its value
"vAxis": $scope.vAxis,
"dataValue": {
"hAxis": "2",
"dataValue": $scope.hrows
},
}
}
}
Please suggest how to create a JSON structure using a iterative loop
mapData = function() {
var jsonData = {
"combinationData": {
"combinationName": "2_2",
"dataGroups": {
"tableType": "2",
"twoAxisData": []
}
}
}
for (var i = 0; i < 5; i++) {
jsonData["combinationData"]["dataGroups"]["twoAxisData"]
.push({
"vAxis": $scope.vAxis,
"dataValue": {
"hAxis": "2",
"dataValue": $scope.hrows
}
})
}
}
I already have this foreach that sets the selected value for the state in statesList correctly for a _searchParam[key] that == the state.id.
However, if the _searchParam[key] contains more than one value in this format" "NH,TX" then the if statement fails and the match never occurs so all items get selected set to false.
var _states = [];
angular.forEach($scope.statesList, function (state, key2) {
if(_searchParams[key].indexOf(state.id) > -1)
if(state.id == _searchParams[key]) {
state.selected = true;
} else {
state.selected = false;
}
this.push(state);
if(state.selected)
$scope.states.push(state);
}, _states);
So, I tried to split the _searchParams[key] value and loop through them but it is not working. See error in comment
var _states = [];
angular.forEach($scope.statesList, function (state, key2) {
if(_searchParams[key].indexOf(state.id) > -1)
var sp = _searchParams[key].split(',');
for(i = 0; i < sp.length; i++) {
if(state.id == sp[i]) {
state.selected = true;
} else {
state.selected = false;
}
}
}
this.push(state); // get unexpected token this
if(state.selected)
$scope.states.push(state);
}, _states);
So, I moved the this.push(state) line into the if (where it really should be anyway), and get the error below.
var _states = [];
angular.forEach($scope.statesList, function (state, key2) {
if(_searchParams[key].indexOf(state.id) > -1)
var sp = _searchParams[key].split(',');
for(i = 0; i < sp.length; i++) {
if(state.id == sp[i]) {
state.selected = true;
} else {
state.selected = false;
}
}
this.push(state);
}
if(state.selected) // get unexpected token if
$scope.states.push(state);
}, _states);
Now how can I fix this as I'm not sure what is going on in this forEach() that would be causing these errors?
The statesList is defined like this:
$scope.statesList = [
{ "id": "AK", "name": "Alaska", "selected": false},
{ "id": "AL", "name": "Alabama", "selected": false},
// SNIPPED most of states
{ "id": "WY", "name": "Wyoming", "selected": false},
{ "id": "DC", "name": "District of Columbia", "selected": false},
{ "id": "MX", "name": "Mexico", "selected": false}];
It appears that you are missing an opening curley brace {. Add it, like this:
if(_searchParams[key].indexOf(state.id) > -1) {
And then take out the split part you added. Otherwise, in some cases you'd set state.selected to true then to false.