How to nest 3 map loop functions in ReactJS - javascript

I've been researching with no success. The answers I'm finding resolve 2 nested loops on react (with map) and I have 2 loops working already. My problem is that I need 3 of them, and I am getting errors on the third even if I have been using the same structure.
Json looks something like this:
{
"Table": [
{
"Power": "20HP",
"Count": "5",
"Vehicles": [
{
"Code": "T01-01",
"Hours": [
{
"Hour": "5:00",
"Status": "1"
},
{
"Hour": "6:00",
"Status": "2"
}
]
},
{
"Code": "T01-01",
"Hours": [
{
"Hour": "5:00",
"Status": "1"
},
{
"Hour": "6:00",
"Status": "2"
}
]
}
]
}
]
}
I have an object called table, which has an array of elements (different vehicle power types like 10 hp, 20 hp...), and each power has a set of vehicles. Finally, each vehicle has an array of hours with a status.
I want an HTML table with the power on de first column, Vehicle code on the second column and the hours on the next X columns (24).
My current code works only until second loop. On the third, I get something about "Parsing error: Unexpected token, expected ","" on VS Code.
My react code within the render is the following:
{this.state.report.Table.map((d, idx) => (
<tr>
<td style={{border:"1px solid"}} >{d.Power}</td>
{d.Vehicles.map((n, idy) => (
<td style={{border:"1px solid"}}>{n.Code}</td>
***************
{n.Hours.map((h, idz) => (
<td className={classes.available}></td>
))}
****************
))}
</tr>
))}
If I remove the code within the ***, it works, but with the third loop It does not. The error on VS Code prompts on the beginning of the third loop, in "{n."
Thanks in advance for your help, let me know if I missed something or if you need more details. Im sure I am missing a code rule, as you can imagine from my question, I'm not fluent with React.

The only overt thing I see missing is the middle mapping needs to return a single node.
{this.state.report.Table.map((d, idx) => (
<tr key={idx}>
<td style={{border:"1px solid"}} >{d.Power}</td>
{d.Vehicles.map((n, idy) => (
<React.Fragment key={indy}> //<-- return single node from map here
<td style={{border:"1px solid"}}>{n.Code}</td>
{n.Hours.map((h, idz) => (
<td key={idz} className={classes.available}></td>
))}
</React.Fragment>
))}
</tr>
))}

Related

Trying to display a table with data from API, array inside JSON Object ANGULAR

I'm working in a project to help a friend, so most of the code in the services and the backend was already there, so I've been struggling with the structure and sometimes I get lost.
Here's my problem
This is the structure of the data on the API:
{
"title": "",
"iconURL": ",
"linkedRightsIDs": [
""
],
"linkedRights": [
{
"id": ,
"creationDate": "",
"sections": [
"women"
],
"defLanguage": "en",
"countryApplied": "united states",
"statesApplied": [
"all"
],
"title": "",
"translations": [
"en"
],
"disable": false,
"content": null
}
]
}
What I'm trying to achieve, is to make a table inside my component using the LinkedRights data. Right now, this structure only have 1 linkedRight (I deleted the data inside for privacy)
Anyways, here's the method regarding the service and model in my component.ts:
onModelLoadedAsync() {
super.onModelLoadedAsync();
if (this.mode == 'create') {
this.model = LocalityInfo;
} else {
if (this.model.iconURL){
this.imageSrc = this.model.iconURL;
}
}
if(this.mode == 'edit'){
const data= Object.entries(this.model.linkedRights); //this is me just testing
console.log(data);
}
}
here's the html of the table I'm trying to display, this is and edit route so there's a query param for the id in this view
<div class="table-responsive">
<table class="table table-hover">
<thead class="thead-dark">
<tr>
<th>Title</th>
<th>Sections</th>
<th>States</th>
<th>Enabled</th>
<th>Creation Date</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of data">
<td>{{item.title}}</td>
<td>{{item.sections}}</td>
<td>{{item.statesApplied}}</td>
<td>{{!item.disabled}}</td>
<td>{{item.creationDate}}</td>
</tr>
</tbody>
</table>
</div>
</div>
What I was trying to do, was to convert the JSON into an array so I could display it since there's an error that shows on the console that said this:
core.js:6456 ERROR Error: Cannot find a differ supporting object '[object Object]' of type'object'. NgFor only supports binding to Iterables such as Arrays.

Blank screen in vue.js if not using created() life cycle hook or spread operator (...)

The following example gives me a blank screen (jsfiddle here). Even the parts which have nothing to do with the loop are not being rendered.
HTML:
<div id="app">
<button #click="objectFromApi">
run objectFromApi function
</button>
<div
v-for="obj in myObject[0].results"
:key="obj.id"
>
<p>
{{ obj.message }}
</p>
</div>
</div>
JavaScript:
new Vue({
el: "#app",
data: {
myObject: []
},
methods: {
objectFromApi: function(){
this.myObject.push(
{
"count": 5,
"results": [
{
"id": 1,
"message": "object 1"
},
{
"id": 2,
"message": "object 2"
}
]
}
)
}
},
//created() {
// this.objectFromApi()
//}
})
Nevertheless it does work if:
1.) Either using objectFromApi function directly in the created life cycle hook (what I don't want!)
created() {
this.objectFromApi()
}
2.) Or (without the use of created life cycle hook) if I go directly into the nested results array and spread the objects out like this (what I also don't want!)
this.myObject.push(
...{
"count": 5,
"next": "http://127.0.0.1:8000/api/someurl/?page=2",
"previous": null,
"results": [
{
"id": 1,
"message": "object 1"
},
{
"id": 2,
"message": "object 2"
}
]
}.results
)
When using option 2.) of course the v-for loop has to look different:
v-for="obj in myObject" instead of v-for="obj in myObject[0].results"
What is wrong with my initial example?
When the component is first rendering the array myObject will be empty.
During rendering it attempts this:
<div
v-for="obj in myObject[0].results"
:key="obj.id"
>
The value of myObject[0] will be undefined. Attempting to access the results property of undefined will result in an error. This error will cause rendering to fail. Nothing will be shown, even the parts that didn't fail.
There are various ways to fix this problem. You could prepopulate the data with suitable empty properties:
data: {
myObject: [
{
results: []
}
]
}
Alternatively, as you've noted, you could change the loop to use v-for="obj in myObject", changing objectFromApi accordingly to only store the results array in myObject. Even if you don't want that exact change some similar change is probably a good idea because the [0] part strongly suggests you've got a problem with your data model. The key thing here is that it avoids trying to access nested objects that don't exist. The use of the spread operator in your second example is largely irrelevant.
Or you could skip the loop in the template:
<template v-if="myObject[0]">
<div
v-for="obj in myObject[0].results"
:key="obj.id"
>
...
</div>
</template>

searchkit: RefinementListFilter can't access certain data in json

I'm usig searchkit as part of a website, but have problems in accessing my data that's been converted into json format previously.
My json directory looks like this:
(...)
hits:
0:
_index: content
_type: content
_source:
meta:
author: content
(...)
json
and I'm using RefinementListFilter (in ReactDOM.render) and this works fine:
<RefinementListFilter id="index" title="Index" field={"_index"}/>
<RefinementListFilter id="Type" title="Type" field={"_type"}/>
whereas i can't seem to access the content that is written under author:
<RefinementListFilter id="Author" title="Author" field={"_source.meta.author"}/>
this doesn't work (no error, nothing happens when I type this), although when i use _source.meta.author in this context it works like expected:
class SearchHit extends React.Component {
render() {
const result = this.props.result;
return (
<div className={this.props.bemBlocks.item("author")}> <b> Index: </b> {result._index} </div>
<div className={this.props.bemBlocks.item("author")}> <b> Author: </b> {result._source.meta.author} </div>
)}}
What am I doing wrong? The first and last snippet work just fine, it's just the middle one that doesn't.
The problem is within the field indices of your elasticsearch instance.
According to the docs, Searchkit needs two different kinds of indexed fields for searching and filtering.
In your case it seems like the field author is not indexed correctly.
To solve this, you need to change the elasticsearch mapping for the field author:
...
"meta": {
"properties": {
"author": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
...
You can then access the authors in the Refinementfilter via
<RefinementListFilter id="author" title="Author" field={"meta.author.raw"}/>
Try to restructure your JSON file for distinct clarification. You need two different fields for searching and filtering.
"meta": {
"properties": {
"author": {
"type": "text",
"fields": {
"val": {
"type": "keyword"
}
}
While in a Refinementfilter, it can be accessed this way
<RefinementListFilter id="Author" title="Author" field={"meta.author.val"}/>

How to add single parenthesis to string using angular or other java script function

I am utilizing Angular JS to manage write a batch of SQL test scripts.
I have a JSON file with multiple test scenarios, each scenario contains a list of projects to test:
$scope.tests = [
{
"Date": "12/31/2017",
"Project": "'93555','94558'",
"STAT": "BDEC",
"Type": "All",
"Amount": 4000,
"Purpose": "This purpose"
},
{
"Date": "12/31/2017",
"Project": "'93555','94558'",
"STAT": "BDEC",
"Type": "Elimination",
"Amount": 6000,
"Purpose": "That purpose"
}
];
Then I used the projects which gets inserted into the angular
<div ng-if="test.Project.length > 0">
AND PROJECT in ({{test.Project}})
</div>
Which Renders like this:
AND PROJECT in ('93555','94558')
PERFECT!
Then I need to log results
<div>DBMS_OUTPUT.PUT_LINE ( 'FAIL: {{test.STAT}} PROJECT {{ test.Project }}: EXPECTED {{test.Amount}} CALCULATED ' || RESULT || '***********'); </div>
Which Renders:
DBMS_OUTPUT.PUT_LINE ( 'FAIL: BDEC PROJECT '93555','94558': EXPECTED 4000 CALCULATED ' || RESULT || '***********');
In order to escape the single parenthesis inside the PUT_LINE, I need to add one more single parenthesis. It should look like this.
DBMS_OUTPUT.PUT_LINE ( 'FAIL: BDEC PROJECT ''93555'',''94558'': EXPECTED 4000 CALCULATED ' || RESULT || '***********');
If I were only dealing with one object, I think I would write a function, but there are multiple objects. The answer is probably obvious, but I can't figure it out.
you can use the Oracle's quote operator q'[]', then you don't need to escape the single quotation marks:
DBMS_OUTPUT.PUT_LINE ( q'[FAIL: BDEC PROJECT '93555','94558': EXPECTED 4000 CALCULATED ]' || RESULT || '***********');

Angular 2: Filter by value in nested array?

I’ve been experimenting with this GitHub repo via a course on Lynda.com (https://github.com/planetoftheweb/learnangular) by Ray Villalobos -- it functions similarly to a basic web app that I’m hoping to build, but I’ve recently hit a bit of a road block.
In that repo linked above, in app/component.app.ts, is the following array:
var ARTISTS: Artist[] = [
{
"name": "Barot Bellingham",
"shortname": "Barot_Bellingham",
"reknown": "Royal Academy of Painting and Sculpture",
"bio": "Some bio here."
},
// etc...
]
This array is filtered by a pipe as seen in app/pipe.search.ts:
export class SearchPipe implements PipeTransform {
transform(pipeData, pipeModifier) {
return pipeData.filter((eachItem) => {
return eachItem['name'].toLowerCase().includes(pipeModifier.toLowerCase()) ||
eachItem['reknown'].toLowerCase().includes(pipeModifier.toLowerCase());
});
}
}
Here's the filter input:
<input class="search-input" [(ngModel)]="field1Filter" placeholder="type in search term here" (click)="showArtist(item); field1Filter=''">
And the code for the filter results:
<ul class="artistlist cf" *ngIf="field1Filter">
<li class="artistlist-item cf"
(click)="showArtist(item);"
*ngFor="let item of (artists | search: field1Filter)">
<artist-item class="content" [artist]=item></artist-item>
</li>
</ul>
<artist-details *ngIf="currentArtist" [artist]="currentArtist"></artist-details>
This all works perfectly, however, in my project, I would need to include three nested arrays, and have the ability to filter based upon the values in those arrays. A sample of the kind of array I need will look something like this:
var ARTISTS: Artist[] = [
{
"name": "Barot Bellingham",
"shortname": "Barot_Bellingham",
"reknown": "Royal Academy of Painting and Sculpture",
"bio": "Some bio here...",
"friends": [
"James",
"Harry",
"Bob",
"Liz",
"Kate",
"Jesse"
],
"emails": [
"bb#this.com",
"aa#this.com"
],
"car": [
"honda",
"scion",
"aston martin"
]
},
// etc...
]
Therefore, I hope to filter by “Harry,” and only display objects that contain “harry” in either “name,” “reknown,” “friends,” "emails," or "cars." Is this possible, and if so, how can I edit the pipe filter to do this? Thank you!!
(I'm pretty green at angular and JS in general, so I want to apologize in advance if I’ve used incorrect terminology or overlooked/misunderstood something basic.)
I deleted my prior answer because it was more confusing than helpful. I pasted example code without applying it to your variables/properties/objects and it was misleading. Let's try again:
export class SearchPipe implements PipeTransform {
transform(pipeData, pipeModifier) {
pipeModifier = pipeModifier ? pipeModifier.toLowerCase() : null;
return pipeModifier ? pipeData.filter(eachItem => {
eachItem['name'].toLowerCase().indexOf(pipeModifier) !== -1 ||
eachItem['reknown'].toLowerCase().indexOf(pipeModifier !== -1) : pipeData;
});
}
}
The first line of code in the transform method ensures that the modifier passed in is also lowercase so that the compare always compares lower case values. It also has a null check to ensure it does not try to lowercase it if it is null.
The second line of code also uses the "?" syntax to handle the case of a null pipeModifier.
I changed includes to indexOf. Includes checks arrays. Are these items, such as eachItem['name'], an array?
That should be closer.
NOTE: Without a provided plunker ... I did not check the syntax or correct execution of this code.

Categories

Resources