Angular associate json value to img path - json

I have to display data that comes from an api that works well, I need to display each country with its corresponding flag but I don't understand how to associate the value of a json with the path of an image.
example : for the
libelle: Cambodge bigramme: KH
display: src/assets/flags/KH.jpg
libelle: France bigramme: FR
display: src/assets/flags/FR.jpg
I have tried to be as clear as possible.
thank you.
json
"drapeaux": [
{
"id": 1,
"mnemo": "KHM",
"libelle": "Cambodge",
"bigramme": "KH"
},
{
"id": 2,
"mnemo": "KHM",
"libelle": "France",
"bigramme": "FR"
}
]
}
service
getAll(): Observable<Ipost[]> {
return this.http.get<Ipost[]>(this.api);
}
components.ts
getAllNations() {
let resp = this.homeService.getAll();
resp.subscribe(result => {
this.postArray = result;
});
}
html
<div class="col-12">
<mat-card>
<div class="row">
<div class="col-1" *ngFor="let post of postArray">
{{post.libelle}}
<img [src]="post.bigramme.jpg" alt="flag">
</div>
</div>
</mat-card>
</div>

You have two options:
Option 1: In your service:
getAll(): Observable<Ipost[]> {
return this.http.get<Ipost[]>(this.api).pipe(
map(p => ({
...p,
bigramme: `src/assets/flags/${p.bigramme}.jpg`
}))
)
}
And then your Component's html:
<div class="col-12">
<mat-card>
<div class="row">
<div class="col-1" *ngFor="let post of postArray">
{{post.libelle}}
<img [src]="post.bigramme" alt="flag">
</div>
</div>
</mat-card>
</div>
Option 2: Or you can change only your Component's html:
<div class="col-12">
<mat-card>
<div class="row">
<div class="col-1" *ngFor="let post of postArray">
{{post.libelle}}
<img src="src/assets/flags/{{ post.bigramme }}.jpg" alt="flag">
</div>
</div>
</mat-card>
</div>

Related

Vue.js dynamic images not working in v-for

im trying to display some images inside a v-for putting the results in the img src=""
<div v-for="piatto in portata" class="card mb-3">
<div class="row">
<div class="col-lg-4">
<img src="'/img/food/' + piatto.img_id + '.jpg'" alt="" style="height:;" class="img-fluid rounded-start img-thumbnail" >
</div>
<div class="col-lg-8">
<div class="card-body mt-3">
<h3 class="card-title">{{piatto.food_name}}</h3>
<h4 class="card-text text-primary">{{piatto.price}}€</h4>
<button type="button" #click="sendOrder(piatto.food_name)" class="btn btn-dark">Aggiungi</button>
</div>
</div>
</div>
</div>
The <img src="'/img/food/' + piatto.img_id + '.jpg'" syntax doesnt seem to work. I dunno if im doing some error in the syntax, or maybe this way of solving the problem is just not viable.
Im pretty new to vue. Thanks in advance
If you are using Webpack
If the images are hosted somewhere on the Internet, you can do that
<template>
<section style="display: flex">
<div v-for="element in elements" :key="element.id" class="">
<img :src="`${imageInitialUrl}${element.imageId}`" />
<p>{{ element.name }}</p>
</div>
</section>
</template>
<script>
export default {
data() {
return {
imageInitialUrl: 'https://source.unsplash.com/random/200x200?sig=',
elements: [
{
id: 1,
name: 'bob',
imageId: '1',
},
{
id: 2,
name: 'patrick',
imageId: '2',
},
{
id: 3,
name: 'sarah',
imageId: '3',
},
],
}
},
}
</script>
This is how it will look.
This is how its written if the images are local
<img :src="require(`#/assets/images/${element.imageId}.jpg`)" />
With this kind of structure

AngularJS nested objects in the same bootstrap row

i have a JSON object
{
"products": [
{
"devices": [
{
"label": "P1D1"
},
{
"label": "P1D2"
}
]
},
{
"devices": [
{
"label": "P2D1"
},
{
"label": "P2D2"
}
]
}
]
}
and i want to have in HTML something like this
<div class="row">
<div class="col-3">
P1D1
</div>
<div class="col-3">
P1D2
</div>
<div class="col-3">
P2D1
</div>
<div class="col-3">
P2D2
</div>
</div>
AngularJS is the language i am using, but i don't seem the find the right syntax
<div class="row">
<div ng-repeat="product in obj.products">
<div class="col-3" ng-repeat="device in product.devices">
{{device.label}}
</div>
</div>
</div>
How can i achieve all the subitems to be displayed in a bootstrap column next to eachother?
I think you can't do it directly using only HTML. Alternatively you can use some manipulation in Javascript to flatten your data.
JAVASCRIPT
$scope.getItems = function(){
return $scope.obj.products.flatMap(function(element){
return element.devices;
})
}
HTML
<div class="col-3" ng-repeat="device in getItems()">
{{device.label}}
</div>
Check my example:
https://codepen.io/avgustint/pen/XWYyoyd?editors=1111

Angular routes doesnt change

I have a problem loading a component inside another component. It just doesn't show , but in browser the route changes , but my component doesn't update...
So i have:
--homepage
--coins--
--coinspreview <-- i cannot access this component;
--services
app-component.html
<app-homepage>
</app-homepage>
app-homepage.html
<section id="home">
<div class="bg">
<img class="my-bg" src="/assets/images/bg.jpg">
</div>
<div class="container middle">
<div class="row">
<div class="col-lg-12 col-sm-12 col-12">
<div class="hero">
<h4 class="hero-title">
Top 100 Cryptocurrency
</h4>
</div>
</div>
</div>
</div>
</section>
<section id="coins">
<app-coins></app-coins>
//here it shows my another component
</section>
app-coins.html
<div class="container">
<div class="row justify-content-center align-items-center">
<div class="col-lg-3 col-md-4 col-sm-6 col-6" *ngFor="let coin of coins$ | async">
<div class="main" [routerLink]="['./coins/coins-preview']">
<img class="mini" src="{{coin.image}}" alt="{{coin.name}}" />
<div class="name">{{coin.name}}</div>
<div class="prices">
<p class="coin-price">
Pret actual: {{coin.current_price}}
</p>
<p class="coin-market-cap">
Capitalizare: {{coin.market_cap}}
</p>
</div>
</div>
</div>
</div>
</div>
And this are all my routes inside app-routing-module.
const routes: Routes = [
{
path: '',
redirectTo: 'homepage',
pathMatch: 'full'
},
{
path: 'homepage',
component: HomepageComponent
},
{
path: "coins",
component: CoinsComponent,
children: [
{
path: "coins/coins-preview",
component: CoinsPreviewComponent
}
]
}
];
I don't know what to do else.. Im so stuck but I cannot understand why It doesnt load ????
When defining the child route dont repeat the parent route name. That should make it working

How to add Row after every 3 columns in angular

What i am trying to do is add a row div after every 3 colum divs
Example Output need:
<div class="row">
<div class="col-md-6"></div>
<div class="col-md-6"></div>
<div class="col-md-6"></div>
</div>
I have an array of products i am iltrating like this
<div class="row" *ngFor="let p of relatedProperties;let i = index">
<div class="col-md-6" *ngIf="relatedProperties[i].title !== undefined">{{ relatedProperties[i].title }}</div>
<div class="col-md-6" *ngIf="relatedProperties[i].title !== undefined">{{ relatedProperties[i].title }}</div>
<div class="col-md-6" *ngIf="relatedProperties[i].title !== undefined">{{ relatedProperties[i].title }}</div>
</div>
But the problem is that my every row prints same title on one iltration and second on next iltration
Current output
<div class="row">
<div class="col-md-6">Title1</div>
<div class="col-md-6">Title1</div>
<div class="col-md-6">Title1</div>
</div>
<div class="row">
<div class="col-md-6">Title2</div>
<div class="col-md-6">Title2</div>
<div class="col-md-6">Title2</div>
</div>
<div class="row">
<div class="col-md-6">Title3</div>
<div class="col-md-6">Title3</div>
<div class="col-md-6">Title3</div>
</div>
Desired Output
<div class="row">
<div class="col-md-6">Title1</div>
<div class="col-md-6">Title2</div>
<div class="col-md-6">Title3</div>
</div>
<div class="row">
<div class="col-md-6">Title4</div>
<div class="col-md-6">Title5</div>
<div class="col-md-6">Title6</div>
</div>
<div class="row">
<div class="col-md-6">Title7</div>
<div class="col-md-6">Title8</div>
<div class="col-md-6">Title9</div>
</div>
If you split your Array into subarrays with always 3 titel's then you can easy loop through this Array in your template.
https://ng-run.com/edit/zZsztdvTOTpzbUC5Buuj?open=app%2Fapp.component.ts
component html
<div class="row" *ngFor="let row of newTitleArr; let i = index">
<div class="col" *ngFor="let col of newTitleArr[i]">{{ col.title }}</div>
</div>
component ts
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
titleArr = [
{ title: 'title1' },
{ title: 'title2' },
{ title: 'title3' },
{ title: 'title4' },
{ title: 'title5' },
{ title: 'title6' },
{ title: 'title7' },
{ title: 'title8' },
{ title: 'title9' },
{ title: 'title10' },
{ title: 'title11' },
{ title: 'title12' },
{ title: 'title13' },
];
newTitleArr:any[];
ngOnInit() {
this.newTitleArr = this.splitArr(this.titleArr, 3)
}
splitArr(arr, size) {
let newArr = [];
for(let i = 0; i< arr.length; i += size) {
newArr.push(arr.slice(i, i+size));
}
return newArr;
}
}
Maybe this works, but Im unsure
<ng-container *ngFor="let p of relatedProperties; let i = index">
<div class="row" *ngIf="(i + 1) / 3 === 1">
<div class="col-md-6" *ngIf="relatedProperties[i - 2].title != null">{{ relatedProperties[i].title }}</div>
<div class="col-md-6" *ngIf="relatedProperties[i - 1].title != null">{{ relatedProperties[i].title }}</div>
<div class="col-md-6" *ngIf="relatedProperties[i].title != null">{{ relatedProperties[i].title }}</div>
</div>
</ng-container>
Also, I gotta say this feels pretty hacky, but if this is what you request, this should work
edit:
Note that strict null (a == null) is better than checking for undefined (a === undefined), as it will check for both undefined or null. In your case title != null.
Also, you could build an iterable that holds the structure you want in a cleaner way.
instead of having [title1, title2, title3, title4, title5, title6...] you should try to have [[title1, title2, title3], [title4, title5, title6], ...] which is way cleaner and allows you to simply have two *ngFors inside your template
<element1 *ngFor="let innerArray of myArray; let i = index">
<element2 *ngFor="let title of innerAray; let j = index">
</element2>
</element1>
And finally, I suggest you avoid calling a variable 'p', that's bad practice.
You can use this to add a row after every 3 columns.
<ng-container *ngFor="let p of relatedProperties; let i = index">
<div class="row" *ngIf="(i%3)==0">
<div class="col-md-6" *ngFor="let p of relatedProperties.slice(i, i+3)>
<span *ngIf="relatedProperties[i].title !== undefined"> {{ relatedProperties[i].title }} </span>
</div>
</div>
</ng-container>

AngularJS + bootstrap carousel help to display all the images

I have an array of objects, where I have the url of the image. I need to display these images in carousel:
<div class="item active">
<div class="row cst-carouselImg">
<div class="col-sm-3 col-xs-6" ng-repeat="image in pack.hotels.current.hotelImages | limitTo:'4'">
<a href="#"><img
ng-src="<?php
echo 'http://photos.hotelbeds.com/giata/';
?>{{image.path}}"
alt="Image" class="img-responsive"></a>
</div>
</div>
</div>
At this point I have only the first 4 pictures from the array. Next I display the next 4 images from the array:
<div class="item">
<div class="row cst-carouselImg">
<div class="col-sm-3 col-xs-6" ng-repeat="image in pack.hotels.current.hotelImages" ng-if="$index > 3 && $index <8">
<a href="#"><img
ng-src="<?php echo
'http://photos.hotelbeds.com/giata/';
?>{{image.path}}"
alt="Image" class="img-responsive"></a>
</div>
</div>
</div>
How can I display all the images using ng-repeat instead of manually adding <div class="item"> and setting manually $index?
Here i take some sample array you can modify it accordingly
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl',function($scope, $timeout) {
$scope.hotelImages=[{id:1},{id:2},{id:3},{id:4},{id:5},{id:6},{id:7}];
$scope.loopCount=Math.ceil($scope.hotelImages.length/4);
$scope.getNumber = function(num) {
var arr=[];
for(i=0;i<num;i++){
arr.push(i);
}
return arr;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<div class="item" ng-repeat="i in getNumber(loopCount) track by $index">
Carousel :-{{i}}
<div class="row cst-carouselImg">
<div class="col-sm-3 col-xs-6" ng-repeat="image in hotelImages" ng-if="$index >=(i*4) && $index <(i*4)+4" >
image:- {{image.id}}
</div>
</div>
</div>
</div>
If I understood you correctly you are aiming at having a nested ng-repeat, one for the items and one for the images. Let me know if I misunderstood you or you need some clarifications. Please see this snippet below:
var app = angular.module("app", []);
app.controller('exampleCtrl', function($scope){
$scope.hotels= [
[
{
path: "hotel1 path1",
otherprop: true
},
{
path: "hotel1 path2",
otherprop: false
},
{
path: "hotel1 path3",
otherprop: true
}
],
[
{
path: "hotel2 path1",
otherprop: true
},
{
path: "hotel2 path2",
otherprop: true
}
],
[
{
path: "hotel3 path1",
otherprop: false
},
{
path: "hotel3 path2",
otherprop: false
},
{
path: "hotel3 path3",
otherprop: false
},
{
path: "hotel3 path4",
otherprop: true
}
]
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="exampleCtrl">
<div class="item" ng-repeat="hotel in hotels">
<p>This is Hotel #{{$index+1}}</p>
<div class="row cst-carouselImg">
<div class="col-sm-3 col-xs-6" ng-repeat="image in hotel">
<a href="#">
<img ng-src="{{image.path}}" class="img-responsive" alt="(this is alt text)"/>
Image {{$index+1}}'s path: {{image.path}}
</a>
</div>
</div>
</div>
</div>
</div>