How to create horizontal scroll with cards using *ngFor? - ionic4

I'm using Ionic 4 and I'm trying to create a horizontal scroll that each item will be a card. And those cards will be displayed dynamically (with *ngFor).
I already tried something like this:
<div class="container">
<div class="scroll" scrollX="true">
<ion-card *ngFor="let item of items">
...
</ion-card>
</div>
</div>
That I searched before, but doesn't work.
What I'm expecting is something like this:
<ion-row>
<ion-item>
<ion-scroll scrollX=true"
<ion-card *ngFor="let card of cards>
<ion-card-header>
<ion-img src="..."/>
</ion-card-header>
<ion-card-content>
<p>...</p>
</ion-card-content>
</ion-card>
</ion-scroll>
</ion-item>
<ion-row>
So basically, slider of cards with *ngFor to get data from the DB. I saw that in ionic 4, ion-scroll doesn't exist anymore.

Thanks for the support guys. I found a solution.
.thumnails{
overflow-x: scroll;
overflow-y: hidden;
.list-thumbnail{
height: 100%;
white-space: nowrap;
.img-thumb{
display: inline-block;
border: 1px solid #ddd;
border-radius: 4px;
padding: 3px;
width: 50px;
height: 50px;
margin:0 2px 0 0;
line-height: 60px;
}
}
}
::-webkit-scrollbar {
display: none;
}
<div class="thumnails">
<div class="list-thumbnail">
<div class="img-thumb" [class.selected-img]="filter.selected" *ngFor="let filter of filters">
<ion-card class="card card__full">
<ion-card-header no-padding>
<ion-img [src]="filter.url" style="width: 100%;" </ion-img>
</ion-card-header>
<ion-card-content>
<p text-center>{{filter.name}}</p>
</ion-card-content>
</ion-card>
</div>
</div>
</div>

.ts file
slides: any[];
constructor(public navCtrl: NavController) {
this.slides = [{
title: 'Slide 1',
content: 'Slide 1 content'
},{
title: 'Slide 2',
content: 'Slide 2 content'
},{
title: 'Slide 3',
content: 'Slide 3 content'
},{
title: 'Slide 4',
content: 'Slide 4 content'
}]
}
your-file.html
<ion-content padding>
<ion-slides pager="true">
<ion-slide *ngFor="let slide of slides">
<h1>{{ slide.title}}</h1>
<div style="display:block">
{{ slide.content }}
</div>
</ion-slide>
</ion-slides>
</ion-content>
try this solution hope it'll resolve your problem.
please have a look on this working url

Related

JavaScript thumbnail swiper / slider doesn't work properly

I'm trying to make a simple swiper / slider with thumbnails. It works fine, the only problem is, that slides on the right, which do not have to be shown yet, are present on the screen, which makes the swiper wider than the webpage...
Here ist the picture, how it looks like
Does anyone know, how to fix it? What am I doing wrong?
Thanks for you help.
var galleryThumbs = new Swiper('.gallery-thumbs', {
spaceBetween: 10,
slidesPerView: 'auto',
freeMode: true,
watchSlidesVisibility: true,
watchSlidesProgress: true,
});
var galleryTop = new Swiper('.gallery-top', {
spaceBetween: 10,
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
grabCursor: true,
thumbs: {
swiper: galleryThumbs
}
});
html,
body {
position: relative;
height: 100%;
}
.swiper-container {
width: 100%;
height: 100%;
}
.swiper-slide{
display: -webkit-flex;
display: flex;
-webkit-justify-content: center;
justify-content: center;
align-items: center;
}
.gallery-top {
height: 60%;
width: 100%;
}
.gallery-thumbs {
height: 20%;
box-sizing: border-box;
padding: 10px 0;
}
.gallery-thumbs .swiper-slide {
width: 25%;
height: 100%;
opacity: 0.4;
}
.gallery-thumbs img{
width:40%
}
.gallery-thumbs .swiper-slide-thumb-active {
opacity: 1;
}
.gallery-top img{
width: 400px;
height:400px;
}
#media only screen and (min-width:100px) and (max-width:500px){
.gallery-top img{
width: 300px;
height:300px;
}
.gallery-thumbs img{
width:100%
}
}
<link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.min.css">
<script src="https://unpkg.com/swiper/swiper-bundle.min.js"></script>
<div class="swiper-container gallery-top">
<div class="swiper-wrapper">
<div class="swiper-slide slide-top">
<img src='https://picsum.photos/id/22/200/300'
alt='slide 1' />
</div>
<div class="swiper-slide slide-top">
<img src='https://picsum.photos/id/237/200/300'
alt='slide 2' />
</div>
<div class="swiper-slide slide-top">
<img src='https://picsum.photos/200/300'
alt='slide 3' />
</div>
</div>
</div>
<!-- Arrows -->
<div class="swiper-button-next swiper-button-black"></div>
<div class="swiper-button-prev swiper-button-black"></div>
<div class="swiper-container gallery-thumbs">
<div class="swiper-wrapper">
<div class="swiper-slide">
<img src='https://picsum.photos/200/300'
alt='slide 1' />
</div>
<div class="swiper-slide">
<img src='https://picsum.photos/200/300'
alt='slide 2' />
</div>
<div class="swiper-slide">
<img src='https://picsum.photos/200/300'
alt='slide 3' />
</div>
</div>
</div>
Your mistake.
The CDN is for swiper 8
https://unpkg.com/swiper#8.4.4/swiper-bundle.min.css
But your markup is of the old versions of swiper.
https://swiperjs.com/migration-guide
Change swiper-container to swiper
html,
body {
position: relative;
height: 100%;
}
.swiper-container {
width: 100%;
height: 100%;
}
.swiper-slide{
display: -webkit-flex;
display: flex;
justify-content: center;
align-items: center;
}
.gallery-top {
height: 60%;
width: 100%;
}
.gallery-thumbs {
height: 20%;
box-sizing: border-box;
padding: 10px 0;
}
.gallery-thumbs .swiper-slide {
width: 25%;
height: 100%;
opacity: 0.4;
}
.gallery-thumbs img{
width:40%
}
.gallery-thumbs .swiper-slide-thumb-active {
opacity: 1;
}
.gallery-top img{
width: 400px;
height:400px;
}
<link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.min.css">
<div class="swiper gallery-top">
<div class="swiper-wrapper">
<div class="swiper-slide slide-top">
<img src='https://picsum.photos/id/22/200/300'
alt='slide 1' />
</div>
<div class="swiper-slide slide-top">
<img src='https://picsum.photos/id/237/200/300'
alt='slide 2' />
</div>
<div class="swiper-slide slide-top">
<img src='https://picsum.photos/200/300'
alt='slide 3' />
</div>
</div>
</div>
<!-- Arrows -->
<div class="swiper-button-next swiper-button-black"></div>
<div class="swiper-button-prev swiper-button-black"></div>
<div class="swiper gallery-thumbs">
<div class="swiper-wrapper">
<div class="swiper-slide">
<img src='https://picsum.photos/200/300'
alt='slide 1' />
</div>
<div class="swiper-slide">
<img src='https://picsum.photos/200/300'
alt='slide 2' />
</div>
<div class="swiper-slide">
<img src='https://picsum.photos/200/300'
alt='slide 3' />
</div>
</div>
</div>
<script src="https://unpkg.com/swiper/swiper-bundle.min.js"></script>
<script>
var galleryThumbs = new Swiper('.gallery-thumbs', {
spaceBetween: 10,
slidesPerView: 'auto',
freeMode: true,
watchSlidesVisibility: true,
watchSlidesProgress: true,
});
var galleryTop = new Swiper('.gallery-top', {
spaceBetween: 10,
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
grabCursor: true,
thumbs: {
swiper: galleryThumbs
}
});
</script>

Styling selected value in Vue Select

I'm using vue select. In the dropdown, there are the labels (not only text). Is it possible to have also the label for the selected value?
<div class="form-group row">
<label for="project_status_id" class="col-sm-3 col-form-label">Projekt Status</label>
<div class="col-sm-9">
<v-select :options="resources.activeProjectStatus" :reduce="project_status_id => project_status_id.id" v-model="form.project_status_id" label="name" id="project_status_id" placeholder="Projekt Status" :class="$vSelectStyle($v.form.project_status_id)">
<template v-slot:option="option" >
<div v-html="option.status_label" class="mb-1">
</div>
</template>
</v-select>
<template v-if="$v.form.project_status_id.$error">
<p class="text-danger" v-if="!$v.form.project_status_id.required">
Projekt - Status ist erforderlich!
</p>
</template>
</div>
</div>
Assuming you want the HTML of the status_label, also assuming that status_label is a template string or similar, then use the selected-option slot with the slot's content being the same as your option slot without the class attached.
The key part in the example below is, as mentioned, the selected-option slot:
<!-- Using OP's `option` key -->
<template v-slot:selected-option="option">
<div v-html="option.status_label"></div>
</template>
The example below is a fork of Vue-Select's Codepen example with modifications for the answer.
Vue.config.productionTip = false;
Vue.component('v-select', VueSelect.VueSelect);
new Vue({
el: '#app',
data: {
options: [
{
name: `<span style="padding: 4px; background: green; border-radius: 0.25rem; color: white;">Foo</span>`
},
{
name: `<span style="padding: 4px; background: orange; border-radius: 0.25rem; color: white;">Bar</span>`
},
{
name: `<span style="padding: 4px; background: red; border-radius: 0.25rem; color: white;">Baz</span>`
}
]
}
});
body {
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
}
h1 {
font-size: 26px;
font-weight: 600;
color: #2c3e5099;
text-rendering: optimizelegibility;
-moz-osx-font-smoothing: grayscale;
-moz-text-size-adjust: none;
}
#app {
max-width: 30em;
margin: 1em auto;
}
<script src="https://unpkg.com/vue#latest"></script>
<script src="https://unpkg.com/vue-select#latest"></script>
<link rel="stylesheet" href="https://unpkg.com/vue-select#latest/dist/vue-select.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:600">
<div id="app">
<h1>Vue Select</h1>
<v-select :options="options" label="label">
<template v-slot:option="option" >
<div v-html="option.name" style="padding: 2px 0;"></div>
</template>
<template v-slot:selected-option="option">
<div v-html="option.name"></div>
</template>
</v-select>
</div>

amp-img not showing in carousel

I used an AMP carousel to show a list of articles abstracts.
For some reason only the abstracts which were visible at page load have pictures.
( If i rotate the screen more but not all pictures are loaded. )
What am i doing wrong?
Feel free to ask for more info.
Here's the layout:
<amp-carousel class="articles-carousel" layout="fixed-height" height="200" type="carousel">
<article role="button" tabindex="1" class="article-abstract" on="tap:AMP.setState({selectedArticle:1072}),AMP.scrollTo('id' = 'article_1072')">
<footer>
<amp-img height="128" layout="fixed" src="/server/929/rabbis/11.jpg" width="128"/>
<div class="article-abstract-author">
<address>
<a rel="author">הרב דוד חי הכהן</a>
</address>
</div>
</footer>
<header>
<a class="article-external-link-container" href="/929/307/1072" target="_blank">
<i class="fas fa-external-link-alt"/>
</a>
<h1>נקודות אור בימי אחאב(2)</h1>
</header>
</article>
<article role="button" tabindex="2" class="article-abstract" on="tap:AMP.setState({selectedArticle:1108}),AMP.scrollTo('id' = 'article_1108')">
<footer>
<amp-img height="128" layout="fixed" src="/server/929/rabbis/24.jpg" width="128"/>
<div class="article-abstract-author">
<address>
<a rel="author">הרב חיים בן סניור</a>
</address>
</div>
</footer>
<header>
<a class="article-external-link-container" href="/929/307/1108" target="_blank">
<i class="fas fa-external-link-alt"/>
</a>
<h1>מלחמת אחאב ובן הדד</h1>
</header>
</article>
<article role="button" tabindex="3" class="article-abstract" on="tap:AMP.setState({selectedArticle:1112}),AMP.scrollTo('id' = 'article_1112')">
<footer>
<amp-img height="128" layout="fixed" src="/server/929/rabbis/6.jpg" width="128"/>
<div class="article-abstract-author">
<address>
<a rel="author">הרב צבי שוויגר</a>
</address>
</div>
</footer>
<header>
<a class="article-external-link-container" href="/929/307/1112" target="_blank">
<i class="fas fa-external-link-alt"/>
</a>
<h1>המוותר על דברי נביא</h1>
</header>
</article>
<article role="button" tabindex="4" class="article-abstract" on="tap:AMP.setState({selectedArticle:1113}),AMP.scrollTo('id' = 'article_1113')">
<footer>
<amp-img height="128" layout="fixed" src="/server/929/rabbis/6.jpg" width="128"/>
<div class="article-abstract-author">
<address>
<a rel="author">הרב צבי שוויגר</a>
</address>
</div>
</footer>
<header>
<a class="article-external-link-container" href="/929/307/1113" target="_blank">
<i class="fas fa-external-link-alt"/>
</a>
<h1>עונש אחאב</h1>
</header>
</article>
</amp-carousel>
Here's the stylesheet:
.articles-carousel {
padding: 1em 0;
}
.article-abstract {
text-align: center;
vertical-align: text-top;
width: 155px;
height: 200px;
}
.article-abstract:focus {
outline: none;
}
.article-abstract:first-child {
margin-right: 12px;
}
.article-abstract header {
display: table;
width: 141px;
max-width: 100%;
}
.article-abstract h1 {
display: table-cell;
font-size: 12px;
line-break: normal;
margin: 0;
text-align: center;
width: 128px;
word-break: break-word;
white-space: normal;
}
.article-abstract footer {
display: inline-flex;
}
.article-abstract-author {
margin: 0px 3px 0 0;
max-width: 12px;
}
.article-abstract-author address {
transform: rotate(-90deg);
}
.article-abstract-author a {
font-size: 11px;
}
.article-external-link-container {
display: block;
width: 16px;
}
You can see that only three of four pictures appeared:
UPDATE:
Bachcha Singh says it's a bug. After adding:
.articles-carousel {
direction:ltr;
}
.articles-carousel > div * {
direction:rtl;
}
it now works. However, i will be glad to make it at least feel like rtl... say with setting initial position to carousel end.
UPDATE#2:
Seems to be solved in amp-carousel-0.2.
Nothing is wrong with your code, after some R & D I found that This is a bug in rtl handling of lazy loading.
For now you can change the direction for amp-carousel and set the design according to your need, Till AMP team will not fixed this bug.
.articles-carousel { direction:ltr; }
If you can change the amp-carousel type carousel to slides, than its also work.

Vue 2 select2 custom template for label

I know I can change the template for the option slot, but can we do the same for the label slot? Like for option:
<v-select inputId="originsId" :options="origins" label="city" placeholder="Search...">
<template slot="option" slot-scope="origin">
<div class="flex">
<div class="col">
<span>{{ origin.city }}</span>
</div>
<div class="col">
<span>{{ origin.country }}</span>
</div>
</div>
</template>
</v-select>
Is there some way I can style the label when the option is selected? Now it only shows the label="city" value. I need something like:
<v-select inputId="originsId" :options="origins" label="city" placeholder="Search...">
<template slot="label" slot-scope="origin">
<div class="flex">
<div class="col">
<span>Selected city: {{ origin.city }}</span>
</div>
<div class="col">
<span>Selected country: {{ origin.country }}</span>
</div>
</div>
</template>
<template slot="option" slot-scope="origin">
<div class="flex">
<div class="col">
<span>{{ origin.city }}</span>
</div>
<div class="col">
<span>{{ origin.country }}</span>
</div>
</div>
</template>
</v-select>
Basically I need some custom styling and additional info other then label="city" when the option is selected.
As Vue-select Github: L324 and Vue-select Github: L539, uses <slot name="selected-option"> will be one solution.
Updated: from Vue-select Github you will see there is one parent slot = selected-option-container, but I found it hasn't been deployed to the dist. In future, you should be able to use this slot to custom the whole container and the selected options.
Like below demo:
Vue.component('v-select', VueSelect.VueSelect)
new Vue({
el: '#app',
data: {
options: [
{
title: 'Read the Docs',
icon: 'fa-book',
url: 'https://codeclimate.com/github/sagalbot/vue-select'
},
{
title: 'View on GitHub',
icon: 'fa-github',
url: 'https://codeclimate.com/github/sagalbot/vue-select'
},
{
title: 'View on NPM',
icon: 'fa-database',
url: 'https://codeclimate.com/github/sagalbot/vue-select'
},
{
title: 'View Codepen Examples',
icon: 'fa-pencil',
url: 'https://codeclimate.com/github/sagalbot/vue-select'
}
]
}
})
body {
font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;
}
h1,.muted {
color: #2c3e5099;
}
h1 {
font-size: 26px;
font-weight: 600;
text-rendering: optimizelegibility;
-moz-osx-font-smoothing: grayscale;
-moz-text-size-adjust: none;
}
#app {
max-width: 30em;
margin: 1em auto;
}
#app .dropdown li {
border-bottom: 1px solid rgba(112, 128, 144, 0.1)
}
#app .dropdown li:last-child {
border-bottom: none;
}
#app .dropdown li a {
padding: 10px 20px;
display: flex;
width: 100%;
align-items: center;
font-size: 1.25em;
}
#app .dropdown li a .fa {
padding-right: 0.5em;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<script src="https://unpkg.com/vue-select#latest"></script>
<div id="app">
<h1>Vue Select - Custom Option Templating</h1>
<v-select :options="options" label="title">
<template slot="selected-option" slot-scope="option">
<div class="flex">
<div class="col">
<span class="fa" :class="option.icon"></span>
<span>Selected item: {{ option.title }}</span>
</div>
</div>
</template>
<template slot="option" slot-scope="option">
<span class="fa" :class="option.icon"></span>
{{ option.title }}
</template>
</v-select>
</div>

How can I make my owl carousel direction follow the mouse wheel direction

When i scroll mouse wheel it moves but when i change scrolling direction it does not change its direction.
How can i make my owl carousel direction follow the mouse wheel direction ?
When i scroll mouse wheel it moves but when i change scrolling direction it does not change its direction.
How can i make my owl carousel direction follow the mouse wheel direction ?
var owl = $('.owl-carousel');
owl.owlCarousel({
loop: true,
margin: 10,
padding: 10,
responsiveClass: true,
rtl: false,
stagePadding: 100,
smartSpeed: 550,
autoplay: true,
autoplayTimeout: 1000,
autoplayHoverPause: true,
nav: true,
responsiveClass: true,
responsive: {
0: {
items: 1,
nav: true
},
600: {
items: 3,
nav: true
},
1000: {
items: 5,
nav: true,
}
}
})
owl.on('mousewheel', '.owl-stage', function (e) {
if (e.deltaY > 0) {
owl.trigger('next.owl');
} else {
owl.trigger('prev.owl');
}
e.preventDefault();
});
html{
width: 100vw;
background: linear-gradient(0deg,#aaaaaa,#f0f0f0) no-repeat;
}
.demo-container{
margin-top: 5em;
background: linear-gradient(0deg,#aaaaaa,#f0f0f0);
}
.owl-carousel .owl-stage-outer{
overflow: visible;
}
.sb-carousel-wrap {
position: relative;
margin-left: -15px;
margin-right: -15px;
z-index: 1;
}
.sb-carousel-wrap .brand-carousel-gradient {
position: absolute;
top: 0;
width: 105px;
height: 100%;
z-index: 10;
}
.brand-carousel-gradient.left {
left: 0;
background-image: linear-gradient(to left, rgba(255, 255, 255, 0.0), #fbfbfb);
}
.brand-carousel-gradient.right {
right: 0;
background-image: linear-gradient(to right, rgba(255, 255, 255, 0.0), #fbfbfb);
}
.sb-car-img{
overflow: hidden;
}
.sb-car-img:hover img{
transform: scale(1.2);
}
.sb-itm-img {
transition: all 0.6s ease-in 0s;
-webkit-transition: all 0.6s ease-in 0s;
-ms-transition: all 0.6s ease-in 0s;
}
.my-slider{
float: left:
width:100%;
padding: 0 15px;
overflow: hidden;
}
<div class="my-slider">
<div class="sb-carousel-wrap">
<div class="brand-carousel-gradient left"></div>
<div class="brand-carousel-gradient right"></div>
<div class="demo-container">
<div class="owl-carousel owl-theme">
<div class="item">
<div class="sb-car-img">
<img src="https://images.pexels.com/photos/923361/pexels-photo-923361.jpeg?auto=compress&cs=tinysrgb&h=350" class="sb-itm-img" alt="">
</div>
</div>
<div class="item">
<div class="sb-car-img">
<img src="https://images.pexels.com/photos/923361/pexels-photo-923361.jpeg?auto=compress&cs=tinysrgb&h=350" class="sb-itm-img" alt="">
</div>
</div>
<div class="item">
<div class="sb-car-img">
<img src="https://images.pexels.com/photos/923361/pexels-photo-923361.jpeg?auto=compress&cs=tinysrgb&h=350" class="sb-itm-img" alt="">
</div>
</div>
<div class="item">
<div class="sb-car-img">
<img src="https://images.pexels.com/photos/923361/pexels-photo-923361.jpeg?auto=compress&cs=tinysrgb&h=350" class="sb-itm-img" alt="">
</div>
</div>
<div class="item">
<div class="sb-car-img">
<img src="https://images.pexels.com/photos/923361/pexels-photo-923361.jpeg?auto=compress&cs=tinysrgb&h=350" class="sb-itm-img" alt="">
</div>
</div>
<div class="item">
<div class="sb-car-img">
<img src="https://images.pexels.com/photos/923361/pexels-photo-923361.jpeg?auto=compress&cs=tinysrgb&h=350" class="sb-itm-img" alt="">
</div>
</div>
<div class="item">
<div class="sb-car-img">
<img src="https://images.pexels.com/photos/923361/pexels-photo-923361.jpeg?auto=compress&cs=tinysrgb&h=350" class="sb-itm-img" alt="">
</div>
</div>
</div>
</div>
</div>
</div>
<link rel="stylesheet" type="text/css" href="https://owlcarousel2.github.io/OwlCarousel2/assets/owlcarousel/assets/owl.carousel.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="https://owlcarousel2.github.io/OwlCarousel2/assets/owlcarousel/owl.carousel.js"></script>
I had the same issue.
In Chrome developer tools (F12), inspect the wheel event with a log:
console.log(e);
This will show you that e.deltaY does not exist in the event object. However, the property e.originalEvent does, and e.originalEvent.deltaY exists here.
Therefore, change the callback to this:
...
if (e.originalEvent.deltaY > 0) {
...
The scroll should work correctly in both directions now.
[edit] I looked into getting it working in IE(11). IE11 shows the wheel event object property e.originalEvent.wheelDelta which is not present in the Chrome object, and this can be used in the same way as deltaY.
In this case, we can use
...
if (e.originalEvent.wheelDelta> 0) {
...
and it should work on both Chrome and IE11.
To get this working in Firefox as well, a different callback event AND property is needed:
Callback is DOMMouseScroll and property to test is e.originalEvent.detail, as follows:
owl.on('DOMMouseScroll','.owl-stage',function(e){
if (e.originalEvent.detail > 0){
owl.trigger('next.owl');
}
else {
owl.trigger('prev.owl');
}
e.preventDefault();
});
As a side note, I looked at the Owl demo, and this does indeed run as described in the documentation, using e.deltaY.
I had the same issue.
To solve this problem simply replace:
if (e.deltaY > 0) {
with:
if (e.originalEvent.deltaY>0){