call a method inside a ngFor in my html (angular6) - angular6

I'm new to stackOverflow, couldn't find an answer to my question.
I'm trying to use an ngFor inside an ngFor.
Is it possible to call a method inside an *ngFor:
something like this :
<div *ngFor="let nbStar of myMethod(skill.level)">
where myMethod is using data from my first ngFor as parameter to generate an array of numbers.
my code:
<div *ngFor="let skill of skills">
<div class="picture">
<img src="{{skill.skillPicture}}"/>
</div>
<div class="title-skill">
<h3>{{skill.skillName | uppercase}} </h3>
Niveau:
<div *ngFor="let nbStar of generateStarsArray(skill.level)">
<i class="fas fa-star"></i>
</div>
</div>
</div>
Thanks a lot for any clues.

Yes you could use it. but make sure your method returns always an array.
For the following template
<div *ngFor="let skill of skills">
<div class="picture">
<img src="{{skill.skillPicture}}"/>
</div>
<div class="title-skill">
<h3>{{skill.skillName | uppercase}} </h3>
Niveau:
<div *ngFor="let nbStar of generateStarsArray(skill.level)">
<i class="fas fa-star"></i>
</div>
</div>
</div>
in component.ts method generateStarsArray should be something like below
public generateStarsArray(level): Array<any> {
let stars = [];
//---> some logic
return stars;
}

Related

vuejs 3 v-if and v-else

hey I am building an spa app with vuejs 3 and I am stuck with v-if and v-else not working as intended
<div v-if="this.isScroll" #click = "toggleIsScroll" class ="spinner-container ">
<i ref = "icon" class = "bi bi-pause-fill icon"> </i>
<div ref="spinner" class ="spinner-border text-dark loader "> </div>
</div>
<div v-else #click = "toggleIsScroll" class ="spinner-container ">
<i ref = "icon" class = "bi bi-play-fill icon"> </i>
<div ref="spinner" class ="spinner-border text-dark loader visually-hidden"> </div>
</div>
the docs says that v-else needs to come right after v-if but I don't know if it works if v-if has children inside it
i have tried to create the v-if section and v-else section in separate components and use v-if and v-else on those as follows
<CustomComponent v-if="this.IsScroll"/>
<SecondCustomComponent v-else/>
but it just renders both components always so how should I go about this?
can you use v-else on followed v-if element even if the v-if one has child elements before the v-else?
When it comes to displaying components conditionally, it would be best to go with v-show since it won't re-render every time when you make it hide/show
<CustomComponent v-show="this.IsScroll"/>
<SecondCustomComponent v-show="!this.IsScroll"/>
v-if and v-else should work with children inside the element. Also you don't need to do v-if="this.isScroll" but just v-if="isScroll".
Assuming that IsScroll is set in the data, the this is not required.
Use v-show if you need to toggle something often, and use v-if if the condition is unlikely to change at runtime.
data: {
IsScroll: true
},
methods:{
toggleIsScroll(){
.....
}
}
<div v-if="isScroll" #click= "toggleIsScroll" class ="spinner-container ">
<i ref = "icon" class = "bi bi-pause-fill icon"> </i>
<div ref="spinner" class ="spinner-border text-dark loader "> </div>
</div>
<div v-else #click= "toggleIsScroll" class ="spinner-container ">
<i ref = "icon" class = "bi bi-play-fill icon"> </i>
<div ref="spinner" class ="spinner-border text-dark loader visually-hidden"> </div>
</div>

moving ngfor data outside of it's tag

it's my first time posting so critic for etiquette.
been using *ngFor="let item of items" in a ionic project but I ran into a problem, that being that once *ngFor is used in the a tag, I don't know who I can transfare the data for a selected item into a tag that is outside of the original tag containing it.
code:
<ion-list>
<div class="wrapper">
<ion-item-group class="day" *ngFor="let day of Excursion_Schedule" >
<ion-item-divider class="dayCard" (click)="day.displayItineraryFlag= !day.displayItineraryFlag"><ion-icon name="ios-arrow-forward" item-right></ion-icon>{{day.ExcSch_date | date:'dd'}}</ion-item-divider>
<!-- CODE I WANT TO MOVE --> <ng-container *ngIf="day.displayItineraryFlag">
<div ion-item class="cardtitle" *ngFor="let place of day.Excursion_CustomRoadMap">
<p>check</p>
<ion-item-divider class="cardtitle" *ngIf="place.Exc_CustomRoadMap_Name" (click)="place.displayStationDetailsFlag= !place.displayStationDetailsFlag">
<div class="textW">{{place.Description}} - {{place.Exc_CustomRoadMap_StartTime}}</div>
<br>
<div *ngIf="place.displayStationDetailsFlag">
<div class="mapNpic">
<img class="pics" src="{{place.Photo}}" alt="">
<img class="pics" src="https://media-cdn.tripadvisor.com/media/photo-s/14/5f/96/77/nice-view-of-the-sunset.jpg" alt="">
</div>
<div class="dits">
<br> <br>
<h3>Adress</h3>
<h3>Phone Number</h3>
<h3>Email</h3>
<h3>Website</h3>
</div>
</div>
</ion-item-divider>
</div>
</ng-container>
</ion-item-group>
</div>
<p>
TESTING 123
<!-- PLACE WHERE I WANT TO MOVE ng-container TO -->
</p>
Just use interpolation. To achieve this you have to write the selected item into a variable and then interpolate it into the outer area. Here is an example:
TS
selectedItem: any;
Excursion_Schedule: Array<any> = [];
HTML
<div><span>{{selectedItem}}</span>
<div *ngFor="let day of Excursion_Schedule">
<!-- write the selected day into the local variable here -->
</div>
</div>

scroll to the tag by its value/content after clicking on a link

I have a link whose value is coming from an api and Details of that link are displayed later in the page.
I want to scroll down to specific details. Details are also coming from an api so I can not write an id to each and every detail available.
e.g. HTML
<div class="row ml-0 mr-0 pb-2" *ngFor="let advance of advanceDetails">
<div class="col-4 dl-value"><a (click)="scroll()">{{advance.AdvNumber}}</a></div>
</div>
This is where I want to scroll:
<div class="row ml-0 mr-0" *ngFor="let advance of advanceDetails">
<div class="col-5">
<label class="dl-label">Advance Number</label>
<p class="dl-value">{{advance.AdvNumber}}</p>
</div>
<div class="col-5">
<label class="dl-label">Other Details</label>
<p class="dl-value">{{advance.details}}</p>
</div>
</div>
I want to scroll down by value of advance number. what will be inside scroll() function in ts? Any help would be appreciated. Thanks in advance :)
It’s not the cleanest way, but you can set a unique id to each item with ngFor indexes.
Then, get the element by id with the unique ID (and check if the element exist), finally scroll to it with scrollIntoView function.
Component.html
<div class="list" *ngFor="let advance of advanceDetails; let i = index">
<div class="list-item" id="advanced-{{i}}">
<p>{{advance.details}}</p>
</div>
</div>
Component.ts
scroll(id : any) {
const advancedItemSelected = document.getElementById('advanced-' + id);
if (advancedItemSelected) {
advancedItemSelected.scrollIntoView(true);
}
}

Cannot read property '0' of undefined in angular 6

I'm getting this error in console, Cannot read property '0' of undefined but still I'm getting the result as expected.
This is my HTML code
<div class="col-md-3">
<div class="slider-product">
<a href="#">
<img src="{{featureProducts[0].img_path}}" alt="Image" style="max-width:100%;">
<span class="tag">{{featureProducts[0].cat_name}}</span>
<div>
<a class="title">{{featureProducts[0].name}}</a>
</div>
<div class="price">
<i class="fa fa-inr"></i> {{featureProducts[0].min_price}}
</div>
</a>
</div>
</div>
Here is the function in typescript file
getFeatureProducts(){
this.httpClient.get(this.baseUrl+`/getFeatureProducts`)
.subscribe(
(data:any[]) => {
if(data.length) {
this.featureProducts = data;
}else{
this.featureProducts = null;
}
}
)}
featureProducts is declared inside the class as
featureProducts: any;
I know there is work around to this problem, like I can use multiple variables as below
in typescript
imgpath0 = this.featureProducts[0].imgPath;
And using this variable in html directly as
{{imgPath0}}
But this is not a better approach as I have lot of properties to be displayed in html and I cannot declare as many variables in ts.
Note: I don't want to loop using 'for' in html. Instead I need to fetch the properties as we usually do in JSON.
You can use *ngIf="featureProducts && featureProducts[0]" and prevent rendering the div until featureProducts object gets populated.
<div class="slider-product" *ngIf="featureProducts && featureProducts[0]">
<a href="#">
<img src="{{featureProducts[0].img_path}}" alt="Image" style="max-width:100%;">
<span class="tag">{{featureProducts[0].cat_name}}</span>
<div>
<a class="title">{{featureProducts[0].name}}</a>
</div>
<div class="price">
<i class="fa fa-inr"></i> {{featureProducts[0].min_price}}
</div>
</a>
</div>

routerLink from Object in Angular2

I'm trying to build a "Team Member" page from JSON data.
I can create the page with basic things like firstName, lastName, position.
Each team member has their own page with a little more information
What I cant figure out is how to include the team members url to my [routerLink].
My router link would look like this which I have setup in my routes
<a [routerLink]="['./glenn']">
And this is how I'm attempting to use it
<div class="team-members" *ngFor="let teammember of teammembers" >
<div class="clearfix">
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-6 team-member member-item" style="cursor: pointer;">
<a [routerLink]="['./"{{teammember.firstName}}"']">
<div class="member-pic-holder">
<img alt="" src='{{teammember.photo}}' />
<div class="member-overlay"></div>
</div>
<h4>{{teammember.firstName}}<br/>{{teammember.lastName}} <span class="fa fa-arrow-right"></span></h4>
<p class="company-position">{{teammember.position}}</p>
</a>
</div>
</div>
</div>
Any thoughts on this one please?
It's also breaking when I'm trying to include the team-members photo
<img alt="" src='{{teammember.photo}}' />
However one thing at a time!
Thanks
GWS
You are using the {{ foo.bar }} binding incorrectly, the {{ }} syntax allows you to do one way binding, what you want is to use regular js expressions when binding to your objects properties.
When binding to an html element attribute, you can use the [attr.{id|href|etc}] binding, in your case, for the href of the image you can use:
<img alt="" [attr.href] = 'teammember.photo' />
And for the router, simply use [routerLink] = "[teammember.firstName]" (not sure why you need the ./, if you do need it, you could append it using a getter on your team member class, as shown bellow.
For your routes, you could do something along the lines of:
Team Member Class
export class TeamMember {
// ...properties and constructor
private memberUrl: string = "foobar"
get MemberRoute(){
return `./${this.memberUrl}`;
}
}
Template:
<div class="team-members" *ngFor="let teammember of teammembers" >
<div class="clearfix">
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-6 team-member member-item" style="cursor: pointer;">
<a [routerLink]="[teammember.MemberRoute']">
<div class="member-pic-holder">
<img [attr.href] = 'teammember.photo' />
<div class="member-overlay"></div>
</div>
<h4>{{teammember.firstName}}<br/>{{teammember.lastName}} <span class="fa fa-arrow-right"></span></h4>
<p class="company-position">{{teammember.position}}</p>
</a>
</div>
</div>
</div>
Hope this helps!
can you try like this:
['./',teammember.firstName]
for img use
<img alt="" [src]="teammember.photo" />