'How can I loop a list of items within a looped component in Angluar so that the icons and text doesn't appear if they're not in JSON file?
I've made looped a card where I am trying to show my projects and a bit of meta-data about them. Most of the meta-data are one time data so I don't need to loop them.
But the roles section (Highlighted in this image) has multiple roles in them. Some cards will have 2 roles and some 4 roles. I don't know how to loop them inside an already existing looped component.
Here's how I my code works ATM:
landing / projects-section / landing-projects.component.html
<div class="container-fluid common-page-container landing-projects-container">
<div #target class="container-fluid content-container">
<h1 class="common-page-header-h1 with-subheader">
Fortune favours the bold <span>(font)</span>
</h1>
<div class="common-page-sub-header">
Over my 8+ years of designing, I have been lucky enough to work with some amazing people & teams. Together, we’ve <br>
discussed and figured user problems, debated the best UX to solve them, and delivered decent products to test the water.<br>
Below is a selected list of projects that I’ve helped companies design & build over the years.<br>
Some are a success, some are a failure - but all learning in disguise ✨
</div>
<div class="row">
<div *ngFor="let item of data" class="landing-projects-section-container col-12">
<component-projects-card ProjectTitle={{item.ProjectTitle}} ProjectDescription={{item.ProjectDescription}} ProjectImage={{item.ProjectImage}} ProjectDate={{item.ProjectDate}} ProjectWorkTitle={{item.ProjectWorkTitle}} ProjectRoles1={{item.ProjectRoles1}} ProjectRoles2={{item.ProjectRoles2}} ProjectRoles3={{item.ProjectRoles3}} ProjectRoles4={{item.ProjectRoles4}}>
</component-projects-card>
</div>
</div>
</div>
</div>
landing / projects-section / landing-projects.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'component-landing-projects',
templateUrl: './landing-projects.component.html',
styleUrls: ['./landing-projects.component.css']
})
export class LandingProjectsComponent implements OnInit {
data: any =
[
{
"ProjectTitle": "SellerCrowd",
"ProjectDescription": "Designing a social platform to help salespeople exchange insights anonymously & hit sales goals faster.",
"ProjectImage": "../assets/projects/project-tiles/sellercrowd.png",
"ProjectDate": "Jan ’18 - Oct ‘21",
"ProjectWorkTitle": "Senior Product Designer",
"ProjectRoles1": "I was hired by SellerCrowd during a time when the code + design wasn’t scalable. The company was looking to redesign the product from scratch.",
"ProjectRoles2": "Understood user problems by looking at user feedback, talking to users, & analyzing user behavior with tools like Smartlook.",
"ProjectRoles3": "Working cross-functionally to define product strategy & roadmaps in collaboration with the Product & Engg. team - while keeping in mind the user and business goals and trying to strike a balance between the two.",
"ProjectRoles4": "Designing + prototyping solutions and ensuring pixel-perfect implementation of the interface & experience in collaboration with the QA & Engg. team.",
"ProjectRandomFact": "SellerCrowd was my first remote job and my first day with the company was at a company-wide yearly meetup in Madrid, Spain 🇪🇸",
"ProjectTeamSize": "2 PMs, 9 Devs, 3 QAs, 1 Designer (me)",
"ProjectURL": "www.sellercrowd.com",
},
]
constructor() { }
ngOnInit(): void {
}
}
landing / projects-card / projects-card.component.html
<div class="row projects-card-container">
<div class="col-5 projects-card-container-left">
<div class="projects-card-container-image" [ngStyle]="{'background-image': 'url(\''+ ProjectImage + '\')'}">
</div>
</div>
<div class="col-7 projects-card-container-right">
<div class="col-12">
<div class="projects-card-container-right-title-description">
<span class="projects-card-title">{{ProjectTitle}}</span>
<span class="projects-card-title-right-line">------</span>
<span class="projects-card-description">{{ProjectDescription}}</span>
</div>
<div class="">
<div class="d-flex projects-card-container-right-meta-data">
<div class="">
<img src="../assets/projects/icon-time.svg" alt="" class="projects-card-container-right-meta-data-icons icon-project-date">
</div>
<div class="projects-card-container-right-meta-data-text">
{{ProjectDate}}
</div>
</div>
<div class="d-flex projects-card-container-right-meta-data">
<div class="">
<img src="../assets/projects/icon-title.svg" alt="" class="projects-card-container-right-meta-data-icons icon-project-title">
</div>
<div class="projects-card-container-right-meta-data-text">
{{ProjectWorkTitle}}
</div>
</div>
<div class="d-flex projects-card-container-right-meta-data">
<div class="">
<img src="../assets/projects/icon-roles.svg" alt="" class="projects-card-container-right-meta-data-icons icon-project-role">
</div>
<div class="projects-card-container-right-meta-data-text">
{{ProjectRoles1}}
</div>
</div>
<div class="d-flex projects-card-container-right-meta-data">
<div class="">
<img src="../assets/projects/icon-roles.svg" alt="" class="projects-card-container-right-meta-data-icons icon-project-role">
</div>
<div class="projects-card-container-right-meta-data-text">
{{ProjectRoles2}}
</div>
</div>
<div class="d-flex projects-card-container-right-meta-data">
<div class="">
<img src="../assets/projects/icon-roles.svg" alt="" class="projects-card-container-right-meta-data-icons icon-project-role">
</div>
<div class="projects-card-container-right-meta-data-text">
{{ProjectRoles3}}
</div>
</div>
<div class="d-flex projects-card-container-right-meta-data">
<div class="">
<img src="../assets/projects/icon-roles.svg" alt="" class="projects-card-container-right-meta-data-icons icon-project-role">
</div>
<div class="projects-card-container-right-meta-data-text">
{{ProjectRoles4}}
</div>
</div>
</div>
</div>
</div>
</div>
landing / projects-card / projects-card.component.ts
import { Component, OnInit, AfterViewInit, Input } from '@angular/core';
@Component({
selector: 'component-projects-card',
templateUrl: './projects-card.component.html',
styleUrls: ['./projects-card.component.css']
})
export class ProjectsCardComponent implements OnInit {
@Input()
ProjectTitle: String
@Input()
ProjectDescription: String
@Input()
ProjectImage: String
@Input()
ProjectDate: String
@Input()
ProjectWorkTitle: String
@Input()
ProjectRoles1: String
@Input()
ProjectRoles2: String
@Input()
ProjectRoles3: String
@Input()
ProjectRoles4: String
@Input()
ProjectRandomFact: String
@Input()
ProjectTeamSize: String
@Input()
ProjectURL: String
constructor() { }
ngOnInit(): void { }
}
Solution 1:[1]
- Why not create an array of roles ?
export class LandingProjectsComponent implements OnInit {
data: any =
[
{
"ProjectTitle": "SellerCrowd",
"ProjectDescription": "Designing a social platform to help salespeople exchange insights anonymously & hit sales goals faster.",
"ProjectImage": "../assets/projects/project-tiles/sellercrowd.png",
"ProjectDate": "Jan ’18 - Oct ‘21",
"ProjectWorkTitle": "Senior Product Designer",
"roles": [
"I was hired by SellerCrowd during a time when the code + design wasn’t scalable. The company was looking to redesign the product from scratch.",
"Understood user problems by looking at user feedback, talking to users, & analyzing user behavior with tools like Smartlook.",
"Working cross-functionally to define product strategy & roadmaps in collaboration with the Product & Engg. team - while keeping in mind the user and business goals and trying to strike a balance between the two.",
"Designing + prototyping solutions and ensuring pixel-perfect implementation of the interface & experience in collaboration with the QA & Engg. team."
]
"ProjectRandomFact": "SellerCrowd was my first remote job and my first day with the company was at a company-wide yearly meetup in Madrid, Spain ??",
"ProjectTeamSize": "2 PMs, 9 Devs, 3 QAs, 1 Designer (me)",
"ProjectURL": "www.sellercrowd.com",
},
]
constructor() { }
ngOnInit(): void {
}
}
and then loop over them as
<div class="row projects-card-container">
<div class="col-5 projects-card-container-left">
<div class="projects-card-container-image" [ngStyle]="{'background-image': 'url(\''+ ProjectImage + '\')'}">
</div>
</div>
<div class="col-7 projects-card-container-right">
<div class="col-12">
<div class="projects-card-container-right-title-description">
<span class="projects-card-title">{{ProjectTitle}}</span>
<span class="projects-card-title-right-line">------</span>
<span class="projects-card-description">{{ProjectDescription}}</span>
</div>
<div class="">
<div class="d-flex projects-card-container-right-meta-data">
<div class="">
<img src="../assets/projects/icon-time.svg" alt="" class="projects-card-container-right-meta-data-icons icon-project-date">
</div>
<div class="projects-card-container-right-meta-data-text">
{{ProjectDate}}
</div>
</div>
<div class="d-flex projects-card-container-right-meta-data">
<div class="">
<img src="../assets/projects/icon-title.svg" alt="" class="projects-card-container-right-meta-data-icons icon-project-title">
</div>
<div class="projects-card-container-right-meta-data-text">
{{ProjectWorkTitle}}
</div>
</div>
<div *ngFor="let role of roles" class="d-flex projects-card-container-right-meta-data">
<div class="">
<img src="../assets/projects/icon-roles.svg" alt="" class="projects-card-container-right-meta-data-icons icon-project-role">
</div>
<div class="projects-card-container-right-meta-data-text">
{{role}}
</div>
</div>
<div class="d-flex projects-card-container-right-meta-data">
<div class="">
<img src="../assets/projects/icon-roles.svg" alt="" class="projects-card-container-right-meta-data-icons icon-project-role">
</div>
<div class="projects-card-container-right-meta-data-text">
{{ProjectRoles4}}
</div>
</div>
</div>
</div>
</div>
</div>
- Also, do not make so many
@Input()params inProjectsCardComponent. Make a single param lets say@INput() dataand create an obj with all the properties that you are passing separately. Reason:
- You can create
typefor that object using typescript and control what is required. - You will have lesser code on HTML and you can move the responsibility to create proper payload into your component. Better quality !
- There are other reasons as well but then we need to dive into how we should design components and so on. It'll deviate away from this question.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
