I'm currently using the Swiper (https://www.npmjs.com/package/angular2-useful-swiper) to create a gallery of images.
Is it possible to dynamically change the class of a div by iterating through an Array of objects and using ngClass? I'm not sure if it is supported with interpolation.
The error that I keep getting says "Identifier 'style' is not defined. 'Array' does not contain such a member.' But why is it that ngStyle, the h4 and p are able to grab the elements and iterate through it if that's the case?
slider.component.html
<div class="swiper-container">
<swiper class="swiper" [config]="config">
<div class="swiper-wrapper">
<div class="swiper-slide" *ngFor="let image of images">
<div class="swiper-slide--container">
<div class="symptom-slide-img"
[ngClass]="images.style" [ngStyle]="{'background-image': 'url(' + image.src + ')'}"></div>
<div class="caption">
<h4>{{ image.title }}</h4>
<p>{{ image.caption}}</p>
</div>
</div>
</div>
</div>
<div class="swiper-button-next"></div>
<div class="swiper-button-prev"></div>
</swiper>
</div>
slider.component.ts
import { Component, OnInit } from '#angular/core';
import { NgClass } from '#angular/common';
#Component({
selector: 'app-symptoms-slider',
templateUrl: './symptoms-slider.component.html',
styleUrls: ['./symptoms-slider.component.scss']
})
export class SymptomsSliderComponent implements OnInit {
images = [ {
'src': './path/image.png',
'title': 'Title',
'style': 'hvr-pulse-grow',
'caption':
'Caption'
},
{
'src': './path/image.png',
'title': 'Title',
'style': 'hvr-buzz',
'caption':
'Caption'
},
{
'src': './path/image.png',
'title': 'Title',
'style': 'hvr-wobble-vertical',
'caption':
'Caption'
},
{
'src': './path/image.png',
'title': 'Title',
'style': 'hvr-wobble-vertical',
'caption':
'Caption'
},
];
constructor() { }
ngOnInit() {
}
}
typo
[ngClass]="images. to [ngClass]="image. (remove unnecessary 's')
Related
My JSON looks like this:
users: [
{ 'name': 'User 1'},
{ 'name': 'User 2'},
{ 'name': 'User 3'},
{ 'name': 'User 4'},
{ 'name': 'User 5'},
{ 'name': 'User 6'},
]
Now i am looping this and i am displaying in the same div, But i need to diaplay the data by these conditions:
Up to length 3 should display in one div and rest things should display in another div(Ex another div right to that div). Here the JSON will be dynamic, The length may be <3 or >3. My requirement looks like this:
JSFiddle link
Vue is convenient to accomplish such tasks.
You need another two computed properties based on users.
template:
<div>{{left}}</div>
<div>{{right}}</div>
computed: {
left: function(){
return this.users.slice(0, 3);
},
reight: function() {
return this.users.slice(3);
}
}
Another option: https://jsfiddle.net/kth61cLu/1/
<div id="app">
<h3>Users</h3>
<div class="users1">
<div v-for="(user, index) in users" v-if="index < 3">
<p>{{user.name}}</p>
</div>
</div>
<div v-if="users.length > 3" class="users2">
<div v-for="(user, index) in users" v-if="index > 3">
<p>{{user.name}}</p>
</div>
</div>
</div>
Create a computed property that splits your array into two with the first having three elements and the second having the rest.
Then loop over the splitUsers array to display.
new Vue({
el: '#app',
data: {
users: [{"name":"User 1"},{"name":"User 2"},{"name":"User 3"},{"name":"User 4"},{"name":"User 5"},{"name":"User 6"}]
},
computed: {
splitUsers () {
const split = [ this.users.slice(0, 3) ]
if (this.users.length > 3) {
split.push(this.users.slice(3))
}
return split
}
}
})
#app { display: flex; }
#app div { padding: 1rem; border: 1px solid black; }
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<div id="app">
<div v-for="chunk in splitUsers">
<p v-for="user in chunk">{{ user.name }}</p>
</div>
</div>
OK, here is what you can try.
<h3>Users</h3>
<div v-for="(user) in users.slice(0,3)">
<p>{{user.name}}</p>
</div>
<div v-for="(user) in users.slice(3)">
<p>{{user.name}}</p>
</div>
Hope it helps!
I'm using the Swiper (https://www.npmjs.com/package/angular2-useful-swiper) to display a gallery of images and captions.
The code in the demo of this package iterates only through an array of image urls. I tried modifying by adding in a paragraph for image captions.
I want to iterate through 2 arrays (one is an array of links to the images, the other is an array of captions for the corresponding images.) I feel like this code almost works, it does iterate through both arrays, but it prints out 3 times, and not as a slider...
If there's a way to iterate through an array of objects (something I tried, but I got stuck with it too...)
Is there also a way to iterate through an array of classes and assign them to each div?
slider.component.ts
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-symptoms-slider',
templateUrl: './symptoms-slider.component.html',
styleUrls: ['./symptoms-slider.component.scss']
})
export class SymptomsSliderComponent implements OnInit {
variants = [
'hvr-pulse-grow',
'hvr-buzz',
'hvr-wobble-vertical',
];
passes = [
'Caption 1',
'Caption 2',
'Caption 3',
'Caption 4',
'Caption 5',
'Caption 6',
];
slides: Slide[];
images = [
'../assets/images/swiper-symptoms/fatigue.png',
'../assets/images/swiper-symptoms/craving.png',
'../assets/images/swiper-symptoms/chewing.png',
'../assets/images/swiper-symptoms/restless.png',
'../assets/images/swiper-symptoms/cold.png'
];
config: Object = {
pagination: '.swiper-pagination',
paginationClickable: true,
nextButton: '.swiper-button-next',
prevButton: '.swiper-button-prev',
slidesPerView: 4,
spaceBetween: 30,
loop: true,
breakpoints: {
// when window width is <= 320px
767: {
slidesPerView: 3,
spaceBetween: 10
}
}
};
constructor() { }
ngOnInit() {
}
}
slider.component.html
<swiper class="swiper" [config]="config">
<div class="swiper-wrapper test">
<div class="swiper-slide">
<img [ngClass]="variants" *ngFor="let image of images" [src]="image">
<div class="caption"><p *ngFor="let pass of passes">{{pass}}</p></div>
</div>
</div>
<div class="swiper-button-next"></div>
<div class="swiper-button-prev"></div>
</swiper>
Remove your passes variable.
Change your images array to following:
images = [ {
'src':'../assets/images/swiper-symptoms/fatigue.png',
'caption':'Caption 1'
},
{
'src':'../assets/images/swiper-symptoms/craving.png',
'caption':'Caption 2'
},
{
'src':'../assets/images/swiper-symptoms/chewing.png',
'caption':'Caption 3'
},
{
'src':'../assets/images/swiper-symptoms/restless.png',
'caption':'Caption 4'
},
{
'src':'../assets/images/swiper-symptoms/cold.png',
'caption':'Caption 5'
}
];
Then change your html to following:
<swiper class="swiper" [config]="config">
<div class="swiper-wrapper test">
<div class="swiper-slide" *ngFor="let image of images">
<img [ngClass]="variants" [src]="image.src">
<div class="caption">
<p>{{image.caption}}</p>
</div>
</div>
</div>
<div class="swiper-button-next"></div>
<div class="swiper-button-prev"></div>
</swiper>
Here is a demo: PLUNKER DEMO
I have added particles.js to an Angular 4 project like mentioned here
Json file is being loaded but I don't see particles on screen
In .ts component :
import { Component, Output, ViewEncapsulation, OnInit } from '#angular/core';
import { MnFullpageOptions, MnFullpageService } from 'ngx-fullpage';
declare var particlesJS: any;
#Component({
selector: 'app-root',
encapsulation: ViewEncapsulation.None,
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'app';
#Output() public options: MnFullpageOptions = new MnFullpageOptions({
autoScrolling: true,
controlArrows: false,
});
ngOnInit() {
particlesJS.load('particles-js', 'assets/particlesjs-config.json', console.log('callback - particles.js config loaded'));
}
constructor() { }
}
Html file :
<div id="particles-js" style="border:2px solid black; background-color:red">
<div class="menu-wrapper">
</div>
<div id="content-wrapper" [mnFullpage]="options" [mnFullpageNavigation]="true" [mnFullpageKeyboardScrolling]="true" [mnFullpageSlidesNavigation]="true" mnFullpageSlidesNavPosition="bottom">
<div class="section welcome-section fp-section fp-table ">
<div class="fp-tableCell ">
<div id="presentation" class="example-card" fxLayout="row">
<app-slide-presentation>
</app-slide-presentation>
</div>
</div>
</div>
<div class="section welcome-section fp-section fp-table">
<div class="fp-tableCell">
<div id="formation" class="example-card" fxLayout="row" fxLayoutAlign="center center">
<app-formation>
</app-formation>
</div>
</div>
</div>
<div class="section welcome-section fp-section fp-table">
<div fxLayout="row" class="fp-tableCell " style="height:100%; width:60%; overflow:hidden; margin:auto ; background-color:white ">
<div class="slide" >
<app-competences1>
</app-competences1>
<div class="slide" style="background-color:white">
>
</div>
<div class="slide">
</div>
<div class="slide">
</div>
<div class="slide">
</div>
</div>
</div>
</div>
</div>
</div>
In console I get callback message :
callback - particles.js config loaded
I have initiated a new project where everything is being working :
in ts component file :
import { Component, Input, Output, OnInit, ViewEncapsulation } from '#angular/core';
declare var particlesJS: any;
#Component({
selector: 'app-root',
encapsulation: ViewEncapsulation.None,
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'app';
ngOnInit() {
particlesJS.load('particles-js', 'assets/particlesjs-config.json', null);
}
}
in html :
<div id="particles-js"></div>
particles are loading perfectly.
I don't see the difference between 2 examples.
Adding "background-color" to 'particles-js' container worked for me.
#home.component.html:
<div id="particles-js"></div>
#home.component.scss:
#particles-js {
height: 100vh;
background-color: black;
}
In Angular 2, I got a list of items and based on a given condition (i.e based on location number) I am setting the list to repeat.
I need to hide the "remove text" for the first box each location.
Plunker:
https://plnkr.co/edit/xtX5BjTBjO61sD2tLwWN?p=preview:
[1]: https://plnkr.co/edit/xtX5BjTBjO61sD2tLwWN?p=preview
import {Component} from '#angular/core';
#Component({
selector: 'app',
template: `
<ul *ngFor="let locdata of locations">
<template ngFor let-item [ngForOf]="items"; let-i=index>
<div *ngIf="item.location==locdata.location">
<div class="title"> location {{ item.location}} <span *ngIf="isNotFirst(item)"> remove </span> </div>
<div class="container"> {{ item.sedule}}</div>
</div>
</template>
</ul>
`
})
export class App {
items: string[];
isNotFirst(item: any) {
return this.items.filter(i => i.location === item.location).map(i => i.id).indexOf(item.id) !== 0;
}
locations:any;
constructor() {
this.locations=[{location:1},{location:2},{location:3}];
this.items = [{
id:1,
location:1,
sedule:1
},
{
id:2,
location:2,
sedule:1
},
{
id:3,
location:1,
sedule:2
},
{
id:4,
location:2,
sedule:2
},
{
id:5,
location:1,
sedule:2
},
{
id:6,
location:2,
sedule:3
}, {
id:7,
location:3,
sedule:1
},
{
id:8,
location:3,
sedule:2
},
{
id:9,
location:3,
sedule:3
}];
}
}
assume you have a <span> in *ngFor logic, you can use first from *ngFor and show/hide <span> by *ngIf
<div *ngFor="let item in data; let first=first;">
{{item.attr}}
<span *ngIf="!first">
remove
</span>
</div>
your working plunker.
import {Component} from '#angular/core';
#Component({
selector: 'app',
template: `
<ul *ngFor="let locdata of locations">
<template ngFor let-item [ngForOf]="items"; let-i=index>
<div *ngIf="item.location==locdata.location">
<div class="title"> location {{ item.location}} <span *ngIf="isNotFirst(item)"> remove </span> </div>
<div class="container"> {{ item.sedule}}</div>
</div>
</template>
</ul>
`
})
export class App {
items: string[];
isNotFirst(item: any) {
return this.items.filter(i => i.location === item.location).map(i => i.id).indexOf(item.id) !== 0;
}
locations:any;
constructor() {
this.locations=[{location:1},{location:2},{location:3}];
this.items = [{
id:1,
location:1,
sedule:1
},
{
id:2,
location:2,
sedule:1
},
{
id:3,
location:1,
sedule:2
},
{
id:4,
location:2,
sedule:2
},
{
id:5,
location:1,
sedule:2
},
{
id:6,
location:2,
sedule:3
}, {
id:7,
location:3,
sedule:1
},
{
id:8,
location:3,
sedule:2
},
{
id:9,
location:3,
sedule:3
}];
}
}
After doing some deciphering of your template, I think that your basic html for a single item in your items collection looks like:
#Component({
selector: 'app',
template: `
<h4>Syntax 1</h4>
<div>
<div class="title">
location {{ item.location}}
<span *ngIf="true">remove</span>
</div>
<div class="container">
{{ item.sedule}}
</div>
</div>
`
})
export class App { .... }
If that's your basic template for a single item, you can then use *ngFor stamp out multiple versions of this HTML, one for each item in your items collection.
That gives you a template that looks like:
#Component({
selector: 'app',
template: `
<h4>Syntax 1</h4>
<div *ngFor="let item of items">
<div class="title">
location {{ item.location}}
<span *ngIf="true">remove</span>
</div>
<div class="container">
{{ item.sedule}}
</div>
</div>
`
})
export class App { .... }
The final piece to the puzzle is that you only want to show the remove text for a specific item in the collection - namely the first item. Thankfully, ngFor has a solution to this very same problem - you can ask ngFor to tell you the index of the current item in the list of items. You can make use of that index to show or hide the 'remove' text. Since the first item will have an index of 0, then your ngIf test will test against that value.
That gives you:
#Component({
selector: 'app',
template: `
<h4>Syntax 1</h4>
<ul>
<div *ngFor="let item of items; let i=index;">
<div class="title">
location {{ item.location}}
<span *ngIf="i != 0">remove</span>
</div>
<div class="container">
{{ item.sedule}}
</div>
</div>
</ul>
`
})
export class App { .... }
Notice the change in the ngFor statement - by using let i=index, you're creating a local template variable i that will be mapped to the current index of the item being output by ngFor. Then you can test against that value to show/hide an element if needed.
(Note that in addition to index, ngFor provides first, last, even and odd variables that you could also make use of. I used index in this example because it has the most wide reaching usage, but you could've easily used first for this use case.
See the documentation for more info about ngFor
See here:
https://plnkr.co/edit/nMvnonrBjRfq1n8tmfZT?p=preview
You need condition like:
*ngIf="i !== 1"
I have an array of Google Map Embed API URLs. However, when iterating over each item and binding them to the source of an iFrame.
I could use the following.
constructor(private sanitizer: DomSanitizationService) {
this.url = sanitizer.bypassSecurityTrustResourceUrl('https://www.google.com/maps/embed/v1/place?key=KEY&q=365 Badger Ave, Newark, New Jersey 07112');
}
But, I would have to do this for each item and I can't do so since I receive the array from an external source that updates.
How could I bypass the security for each of my URLs?
Here's app.component.ts
import { Component, Pipe } from '#angular/core';
import { DomSanitizationService } from '#angular/platform-browser';
#Pipe({name: 'secureUrl'})
export class Url {
constructor(private sanitizer:DomSanitizationService){
this.sanitizer = sanitizer;
}
transform(url) {
return this.sanitizer.bypassSecurityTrustResourceUrl(url).changingThisBreaksApplicationSecurity;
}
}
#Component({
selector: 'my-app',
pipes: [Url],
template: `
<div class="container">
<div style="padding-top: 20px">
<div class="row" *ngFor="let row of rows">
<div *ngFor="let event of row">
<div class="col s12 m6 l4">
<div class="card hoverable">
<div class="card-image waves-effect waves-block waves-light">
<img height="300" class="activator" [src]="event.thumbnail">
</div>
<div class="card-content">
<span class="card-title activator grey-text text-darken-4">{{event.title}}</span>
<p><a class="activator">Hosted by {{event.host.data.first_name}} {{event.host.data.last_name}}</a></p>
</div>
<div class="card-action grey lighten-2">
<a class="blue-grey-text lighten-3">Details</a>
<a class="blue-grey-text lighten-3">Join</a>
</div>
<div class="card-reveal" style="font-size: 15px">
<span class="card-title grey-text text-darken-4"><center>{{event.title}}</center><i class="material-icons right">close</i></span>
<hr>
<center>
<p class="truncate">{{event.description}}</p>
<hr>
<p>Starts {{event.start}}</p>
<iframe width="210" height="190" frameborder="0" style="border:0" src="{{event.address|secureUrl}}" allowfullscreen></iframe>
</center>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`
})
export class AppComponent {
public rows = GROUPS;
}
var EVENTS = [
{
id: 95,
title: "Event Name",
description: "The awesome event description",
thumbnail: "https://ucarecdn.com/58955d6b-bd4c-41f3-8a7b-4ce2bf013b13/IMG_4229.JPG",
access: "public",
code: null,
start: "1 week ago",
end: "6 days ago",
address: "https://www.google.com/maps/embed/v1/place?key=KEY",
host: {
data: {
id: 23,
avatar: "http://www.gravatar.com/avatar/9e557072ab393aa2fca6701eb7b23853?s=45&d=mm"
}
},
category: {
data: {
id: 1,
title: "Wedding",
description: "A marriage ceremony."
}
}
}
];
var chunk_size = 3;
const GROUPS = EVENTS.map(function(e,i){
return i%chunk_size===0 ? EVENTS.slice(i,i+chunk_size) : null;
})
.filter(x=>!!x)
You can use PIPE with DomSanitizationService as shown below;
//our root app component
import {Component, Pipe} from '#angular/core'
import {DomSanitizationService} from '#angular/platform-browser';
#Pipe({name: 'secureUrl'})
export class Url {
constructor(private sanitizer:DomSanitizationService){
this.sanitizer = sanitizer;
}
transform(url) {
return this.sanitizer.bypassSecurityTrustResourceUrl(url).changingThisBreaksApplicationSecurity;
}
}
#Component({
selector: 'my-app',
pipes: [Url],
template: `
<div *ngFor="let item of myUrls; let i = index">
{{item.url|secureUrl}}
</div>
`,
})
export class AppComponent {
myUrls=[{url:"google.com"},{url:"google1.com"},{url:"google2.com"}];
}