images not displaying using array with input and ngFor - Angular - javascript

I'm trying to display an array of images via their source link using an ngFor but I am receiving errors and it's not working!
The image HTML code which is within my card component:
<div class="Session-Participants">
<div *ngFor="let image of {{ participantImages }}" >
<img src='{{image}}'/>
</div>
</div>
In the JS file:
#Input() participantImages? = [];
The data is coming from my other component and the html and JS are as below:
<div *ngFor="let sessions of getSortedSessionList()">
<div *ngFor="let session of sessions">
<tl-session-card
[title]="session.name"
[path]="sessionPath(session.id, session.name)"
[participantImages]="getParticipantDetails(session)" // HERE
>
</tl-session-card>
</div>
</div>
the JS:
participantImage = [];
getParticipantDetails(session) {
this.participantImage = session.roles[0].account.thumbnailURL;
return this.participantImage;
}
I'm expecting for the 'this.participantImage' to be returned and then sent to the card component and then broken down to be displayed separately.
I'm sure I am missing something?
Thanks if you can help at all?

Actually in the stackblitz link, you have a proper array and that not reflect perfectly the code you just provide above.
You need to ensure participantImage stay an array otherwise, the ngFor will not work as expected and you will see some errors in your console.
as #prashant-pimpale says, you need to append to the list of participantImage the result.
In the ts file It would be better to use
participantImage = [];
getParticipantDetails(session) {
// ensures this.participanImage keeps its array type and will process all
// other roles
this.participantImage = session.roles.map(account => account.thumbnailURL);
return this.participantImage;
}
Hope it helps
PS: would be better to set the attribute name of participantImage to participantImages since it represent a list of images ;)

Related

Angular show hide with combine condition

I have an array of object need to show hide based on filter like below:
HTML CODE:
Filter:
<div (click)="filter(1)"> F1 </div>
<div (click)="filter(2)"> F2 </div>
<div (click)="filter(3)"> F3 </div>
<div (click)="filter(4)"> F4 </div>
<div *ngFor="let data of datas">
<span *ngIf="data.show">
{{data.name}}
</span>
</div>
ts Code:
this.datas = `[{'name':'product one','filter':'1'},{'name':'product two','filter':'2'},{'name':'product three','filter':'3'},{'name':'product three','filter':'3'},{'name':'product','filter':''},{'name':'product','filter':''},{'name':'product one','filter':'1'},{'name':'product'}]`
filter(query){
this.datas.forEach(function (element, index) {
if (element.filter == query ) {
element.show = true;
} else {
element.show = false;
}
I have tried the above approach it's not working .
Expected like:
By default display all product.
Filter is toggle(on/off)
Need to filter like (F1 & F2 & F3) at the same time like combination
The array objects do not have the show property that you test in the *ngIf directive
Rather simple, really.
I made you a small stackblitz app. But you also really, really need to work on your code. Even as a description for your help, this is just pretty messy.
I didn't code your "Multiple Selections" for you.
https://stackblitz.com/edit/angular-ivy-fbpgdv?file=src/app/app.component.ts
Observation/Suggestions :
Instead of adding a new property show. You can easily achieve that by filtering out the datas array based on the value passed in the filter() method.
Instead of modifying the original array, you can make a deep copy and do the operation on click on filter().
Working Demo : https://jsfiddle.net/srvpw2bo/

How to name dynamically a reference in a div on Angular template inside a loop

I'm developing a project using Angular 8.3.
I have a loop (using *ngFor) and I need that every div that I add has an unique reference name created dinamically).
This is my example code:
<div *ngFor="let item of list; let i = index;">
<div
cdkDropList
#done0="cdkDropList"></div>
</div>
Below I have another drag and drop zone that must receive these elements:
<div
cdkDropList
#donesList="cdkDropList"
[cdkDropListData]="DonesList"
[cdkDropListConnectedTo]="[done0, done1]"
class="movie-list"
(cdkDropListDropped)="onDrop($event)">
<div *ngFor="let itemList of DonesList" cdkDrag>{{itemList}}</div>
</div>
I need to change dynamically #done0, e.g. (#done0, #done1, #done2, #done3, etc).
How can I do it? I have tryed using #done{{i}}} but it doesn't work.
I don't know if I can use trackBy in this case and how to apply it.
Many thanks,
Reference a container:
<div *ngFor="let item of list; let i = index;" #doneContainer>
<div cdkDropList></div>
</div>
and in .ts you have different references in a NodeList:
const list = this.doneContainer.childNodes
or in a more Angular way, which is better, as it will update when necessary:
#ViewChildren('doneContainer') list: QueryList<any>;

Get value of Select DOM Element in ngb-tabset in Angular Bootstrap

I have the following DOM element inside a *ngFor loop (with index set to idx):
<div class="row" *ngFor="let item of myArray let idx=index">
<select [id]="'myID' + idx"></select>
</div>
In my component, I need to get the element's value and tried this:
export class HelloComponent{
constructor() {}
ngAfterViewInit(){
console.log((<HTMLSelectElement>document.querySelector('#myID0')).value);
}
}
It throws the following error:
ERROR TypeError: Cannot read property 'value' of null
When I do console.log(document.querySelector('#myID0')) I get the element printed. For some reason, I can't get the value...
UPDATE
I was missing the fact that my select is inside a ngb-tabset
You can see the reproduction of the issue here. The full HTML code is:
<ngb-tabset>
<ngb-tab>
<ng-template ngbTabTitle="">Tab</ng-template>
<div class="row" *ngFor="let item of myArray let idx=index">
<select [id]="'myID' + idx">
<option>Hello</option>
</select>
</div>
<ng-template ngbTabContent=""></ng-template>
</ngb-tab>
</ngb-tabset>
When working with Angular I would look to avoid accessing the DOM in such ways. You should look at implementing viewchildren. This should give you all the information you need about the element. Sorry answer has drastically changed since you made the stackblitz
public #ViewChildren('idx')public domElement: QueryList<any>; // be sure to import.
<select #idx> // in HTML
#ViewChildren can be used to return an array of the tagged elements. Which would be done like so. This will return you an array of the *ngFor elements.
You could then set up something simple to find the correct element.
const test = this.domElements.find(element => element.yourvalue === whatYouExpect);
Give your select elements a template reference variable, and use ViewChildren to obtain a QueryList in your component.
<div class="row" *ngFor="let item of myArray let idx=index">
<select [id]="'myID' + idx" #selectElements></select>
</div>
#ViewChildren('selectElements', { read: ElementRef })
selectElements: QueryList<ElementRef>;
See https://angular.io/api/core/ViewChildren

extract JSON data in Angular2

I have the following JSON output: http://pastebin.com/9bHaBrbX
I would like to make this pseudocode a reality:
For every Model {
For every Year {
For every Style {
if submodel.body is NOT in Array:
load submodel.body to Array;
}
}
}
I would like to store this Array in my model.component so I can use it to make buttons such as:
<button *ngFor="let item in Array" ...> item </button>
How can I extract the data I want (Model[x].Years[y].Style[z].submodel.body) (where x,y,z are variables) from my json response?
I am having trouble conceptualizing how to iterate through nested json objects with JS/TS/Angular2.
Here is a hint :
<div *ngFor="let years of model.years">
<div *ngFor="let year of years">
<div *ngFor="let styles of year.styles">
<div *ngFor="let style of styles">
<!-- your conditions, submodel.body... -->
</div>
</div>
</div>
</div>
Side note: I agree with others above, you should try to write your code yourself.
Use simple http request, it will download the data and store it inside the items variable. Then you can do whatever you want with it - display, sort or just keep.
https://plnkr.co/edit/bU7W6f0aO6eelvyCnKzc?p=preview

How do I create a grid system using handlebars in Meteor.js?

I'm trying to build a simple memory card game in Meteor and I can't seem to create a grid of my cards to populate in html. I'm just trying to get a 4x4 grid for right now.
Here is the javascript:
Template.body.helpers({
cards: function() {
var allCards = Deck.find({}).fetch();
var chunks = [];
while (allCards.length > 0) {
chunks.push(allCards.slice(0, 4));
allCards = allCards.slice(4);
}
return chunks;
},
});
And here is the HTML:
<body>
<div class="container">
<div name="gameBoard">
{{#each cards}}
{{> cardsRow}}
{{/each}}
</div>
</div>
</body>
<template name="cardsRow">
<div class="row">
{{#each row}}
{{> card}}
{{/each}}
</div>
</template>
<template name="card">
<span class="text">{{text}}</span>
</template>
Right now I just have simple text entries in the db to see what I'm doing before I pull in images. I've tried console logging from my JS and I believe I'm creating the array of spliced rows correctly so I think the problem may be in the way I have arranged the markdown.
I tried pulling the each cards loop into a template as well instead of inside the body but I'm not sure how to render templates on demand. This is potentially an option since I have a new game button event listener that could call a render. I'm just not sure how to explicitly render in Meteor.
I tried following this previous post but I couldn't get it to work:
How do I populate a bootstrap grid system using handlebars for each command in Meteor.js?
Thoughts? I can provide more of my code base if needed.
Neither row in {{#each row}} in the "cardsRow" template, nor {{text}} in the "cards" template, refer the way that you hope they do. You need to define row and text as template helpers for each of these templates. In a template helper, this refers to the data object associated with the template.
In your case, when you iterate through #each cards in "container", this is passed into the "cardsRow" template as one of the chunks defined in your cards helper function. The helpers below should illustrate this, and are sufficient for your example.
Template.cardsRow.helpers({
row: function() {
console.log(this); // a chunk of cards
return this;
}
});
Template.card.helpers({
text: function() {
console.log(this); // a number in a chunk
return this;
}
});

Categories

Resources