How to add a filter to a #each block

Hello, I need your help !
I have a request result like this:

{
    "issues": [
        {
            "id": "13152",
            "key": "BRQ-1993",
            "fields": {
                "issuetype": {
                    "name": "Epic",
                }
            }
        },
        {
            "id": "13057",
            "key": "BRQ-1969",
            "fields": {
                "issuetype": {
                    "name": "Exigences",
                }
            }
        },
        {
            "id": "13158",
            "key": "BRQ-1999",
            "fields": {
                "issuetype": {
                    "name": "Epic",
                }
            }
        },
        {
            "id": "13056",
            "key": "BRQ-1968",
            "fields": {
                "issuetype": {
                    "name": "Exigences",
                }
			}
        }
    ]
}

I want to visualize this result in a HTML format:

let idProjet = pm.collectionVariables.get("idProjet");

var template = `
<html>
	<body>
		<table border="1">
			<tr>
				<th>Name</th>
				<th>Email</th>
			</tr>
			
			{{#each response.issues}}
					<tr>
						<td>{{key}}</td>
						<td>{{id}}</td>
					</tr>
			{{/each}}
		</table>
	</body>
</html>`;

pm.visualizer.set(template, {
    response: JSON.parse(responseBody)
});

It works but I need to filter my #each block to obtain only issues of type Epic (issuetype.name=‘Epic’). How can I do this ?

Thanks for your help

Hey @cmercierthess :wave:

Welcome to the Postman Community! :postman:

You could filter the response before passing that to the visualizer with something like this:

let template = `
<html>
	<body>
		<table border="1">
			<tr>
				<th>Name</th>
				<th>Email</th>
			</tr>
…
function filteredVisualizerPayload() {
    let issues = pm.response.json().issues.filter(issue => issue.fields.issuetype.name === "Epic");
    return { response: { issues: issues } };
}

pm.visualizer.set(template, filteredVisualizerPayload());

Thanks Danny for your reply.

I need to filter on issuetype.name=‘Epic’ and add another #each block inside to search for all tickets that have as parent the Epic found in the first #each. If I filter before passing that to the visualizer, I won’t have access to all the tickets.
I’ve tried using a #if after the #each but it get the error Missing helper.

You can still do all of the filtering for what you need using javascript in the tests section before passing that data to the visualizer.

The use of handlebars in the visualizer is limited in the sandbox, it’s not the full version of the library so it would have the same capability as you would give in the standalone version.

I must be missing something as Danny’s filter appears to work fine.

const response = pm.response.json();
let issues = response.issues.filter(issue => issue.fields.issuetype.name === "Epic");
console.log(issues);

var template = `

    <style type="text/css">
        .tftable {font-size:14px;color:#333333;width:100%;border-width: 1px;border-color: #87ceeb;border-collapse: collapse;}
        .tftable th {font-size:18px;background-color:#87ceeb;border-width: 1px;padding: 8px;border-style: solid;border-color: #87ceeb;text-align:left;position:sticky;top:0;}
        .tftable tr {background-color:#ffffff;}
        .tftable td {font-size:14px;border-width: 1px;padding: 8px;border-style: solid;border-color: #87ceeb;}
        .tftable tr:hover {background-color:#e0ffff;}
    </style>
    
    <table class="tftable" border="1">
        <tr>
			<th>Name</th>
			<th>Email</th>
        </tr>
		{{#each response}}
			<tr>
				<td>{{key}}</td>
				<td>{{id}}</td>
			</tr>
		{{/each}}
    </table>
    
`;

pm.visualizer.set(template, {
    response: issues
});

This returns the two objects defined as Epics.

Sorry, my JSON was not complete enough to understand my problem. Here’s a more complete version:

{
    "issues": [
        {
            "id": "13152",
            "key": "BRQ-1993",
            "fields": {
                "issuetype": {
                    "name": "Epic"
                }
            }
        },
        {
            "id": "13057",
            "key": "BRQ-1969",
            "fields": {
                "issuetype": {
                    "name": "Requirements"
                },
				"parent": {
					"key" : "BRQ-1999"
				}
            }
        },
        {
            "id": "13158",
            "key": "BRQ-1999",
            "fields": {
                "issuetype": {
                    "name": "Epic"
                }
            }
        },
        {
            "id": "13056",
            "key": "BRQ-1968",
            "fields": {
                "issuetype": {
                    "name": "Requirements"
                }
				"parent": {
					"key" : "BRQ-1993"
				}
			}
        }
    ]
}

I have to use a #each block for the “Epic” and for each “Epic” I have to get the “Requirements” whose parent is the current “Epic”. Something like that:

    {{#each response}} 'Epic
        <tr>
            <td>EPIC</td>
            <td>{{key}}</td>
            <td>{{id}}</td>
        </tr>
		{{#each response}} 'Requirements whose parent is the current Epic
		<tr>
            <td></td>
            <td>{{key}}</td>
            <td>{{id}}</td>
		</tr>
		{{/each}}
    {{/each}}

The main problem here is that you have an array of objects, but not all of the objects have the same keys.

My recommendation would be to filter for the Epics first, so you have a list of Epics.

Then filter the response for those Epics, but this would need to be done by looping through each object in the response, as the JavaScript find\filter method will error as it will produce a fatal error with the objects missing the relevant keys.

You need to use a method that won’t error if the key doesn’t exist.

If you create a blank array, You can then make a new object with just the epic, id and key, and then push it to the array during the inner loop.

You can then use this array for the Visualizer.

The following seems to work against your example response.

const response = pm.response.json();

let epics = response.issues.filter(issue => issue.fields.issuetype.name === "Epic");

requirements = [];

epics.forEach(epic => {
    response.issues.forEach(obj => {
        if ("parent" in obj.fields && obj.fields.parent.key === epic.key) {
            let newObj = {"epic": epic.key, "id": obj.id, "key": obj.key}
            requirements.push(newObj);
        }
    });
});

var template = `

    <style type="text/css">
        .tftable {font-size:14px;color:#333333;width:100%;border-width: 1px;border-color: #87ceeb;border-collapse: collapse;}
        .tftable th {font-size:18px;background-color:#87ceeb;border-width: 1px;padding: 8px;border-style: solid;border-color: #87ceeb;text-align:left;position:sticky;top:0;}
        .tftable tr {background-color:#ffffff;}
        .tftable td {font-size:14px;border-width: 1px;padding: 8px;border-style: solid;border-color: #87ceeb;}
        .tftable tr:hover {background-color:#e0ffff;}
    </style>
    
    <table class="tftable" border="1">
        <tr>
            <th>Epic</th>
			<th>Key</th>
			<th>Id</th>
        </tr>
		{{#each response}}
			<tr>
                <td>{{epic}}</td>
				<td>{{key}}</td>
				<td>{{id}}</td>
			</tr>
		{{/each}}
    </table>

`;

pm.visualizer.set(template, {
    response: requirements
});

1 Like

Thank you Mike !

I adapt your solution and it works well:

const response = pm.response.json();

let epicsJira = response.issues.filter(issue => issue.fields.issuetype.name === "Epic");
epics = [];
epicsJira.forEach(epic => {
    newChildren=[];
    let newEpic = {"id": epic.id, "key": epic.key, "type": epic.fields.issuetype.name};
    response.issues.forEach(ticket => {
        if ("parent" in ticket.fields && ticket.fields.parent.key === epic.key) {
            let newChild = {"id": ticket.id, "key": ticket.key, "type": ticket.fields.issuetype.name};
            newChildren.push(newChild);
        }
    });
    newEpic.children = newChildren;
    epics.push(newEpic);
});

pm.visualizer.set(template, {
    response: epics
});
2 Likes

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.