How attach event in componet inside a slot - polymer-3.x

I create a web component like this:
class P3ELayout extends PolymerElement {
static get template() {
return html`
<slot name="app"></slot>;
}
}
tapButton(evt) {
console.log(evt);
}
}
In my index i create this component:
<body>
<p3e-layout>
<div slot="app" >
<app-header-layout fullbleed>
<app-header reveals>
<app-toolbar>
<div main-title>P3E</div>
<paper-icon-button icon="icons:account-circle" on-click="tapButton"></paper-icon-button>
</app-toolbar>
</app-header>
<div class="layout-container layout-horizontal">
<div class="layout-vertical layout-flex-auto layout-content">
content
</div>
</div>
</app-header-layout>
<app-drawer id="settingDrawer" align="right" swipe-open>
setting-drawer
</app-drawer>
</div>
</p3e-layout>
</body>
I expected to attach on the on-click event of the button but tapButton is never trigger. Can i attach on the component event inside the slot?

Related

class active CSS issue in angular

I have separate component of a tile in which i show all the list of data so when i click the tile it should show active class CSS in particular tile but now where ever i click it shows active class in all tiles.
div class="container-fluid" style="margin-top: 12px" *ngIf="!loading">
<div class="container-fluid " *ngIf="!done">
<adm-tile
[heading]='heading'
[orderno]='stock.id'
[time]='stock.created_at'
[category]='stock.request_category.name'
[status_type]='getStatus(stock.status)'
[name]='stock.requester.first_name'
[branch]='stock.to_department.name'
[date]='stock.delivery_date'
[priority]='stock.priority'
[index_no] = 'i'
[data]= 'stock'
[title]="'Requested To'"
[title1] = "'From'"
(selected)="onButton06($event)"
*ngFor="let stock of stock_list ; let i = index" ></adm-tile>
<div class="wrapper-card __list-card --small-card" style="margin-top:-5px" (click)="button01()" [class.active-border-selection]="index_no === selectedIndex1">
<div class="media">
<div class="media-body">
<div class="rowa split" style="position: relative">
<div class="col-6" style="position: relative">
<div >
<div style="height: 19px;overflow: hidden !important;">
<label class=" bold2">{{heading}}</label><span class="bold2">:#{{orderno}} </span>
<span class="bold2 desktop"> - {{your_date | timeAgo}}</span>
</div>
<div style="height: 22px">
<label class="bold3 ">{{category}}</label>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
button01() {
this.selectedIndex1 = this.index_no;
}
Based on your question for only one button or card to be active at one time, check below code. You need to set active in the parent component only not in child as all child are independent components.
Parent Component
import { Component } from '#angular/core';
#Component({
selector: 'payroll-search',
template: `
<div *ngFor="let stock of stock_list ; let i = index" >
<hr-files-search
style="position: relative; display:block"
(sendIndex)="getIndex($event)"
[class.active-border-selection]="i == selectedIndex"
[index_no] = 'i'
></hr-files-search>
</div>
`
})
export class PayrollSearchComponent {
stock_list = [1,2,3,4,4,5];
public selectedIndex: number;
public getIndex(event) {
this.selectedIndex = event;
}
}
Child component
import { Component, Input , OnInit, Output, EventEmitter } from '#angular/core';
#Component({
selector: 'hr-files-search',
template: `
<div class="card" (click)="button01(index_no)">
<div class="card-content">
<h6>hello</h6>
</div>
</div>
`
})
export class HrFilesSearchComponent implements OnInit {
#Input() index_no: any;
#Output() sendIndex = new EventEmitter();
ngOnInit() {
}
selectedIndex1;
button01(index) {
this.sendIndex.emit(index);
}
}
Here is the stackblitz solution.

Angular: How can I request the images as needed to accelerate the load (using ngx-bootstrap)

I am making a request to a personal API that returns the url of about 300 images (approximately) and all these images I must show them in a Carousel.
The problem is that my page lasts a long time to load because when the surcharge begins to load the 300 images. the carousel shows 6 images per pass, and what I want is for you to load the images as you click on the "NEXT" or "PREV" button to make the page load faster. That would be the right way to do it, right?
I'm starting with angular and it's the first time I make an application of this type. Somebody could help me? I have researched but I have not found much information that helps me or I do not know the terminology of what I need to use in this case.
This is the code of the carousel where I show the images that I comment, I am using NGX-BOOTSTRAP:
<div class="container" >
<div class="d-flex justify-content-center align-items-center">
<div class="d-flex align-items-center justify-content-center">
<div> <span class="text-hot">
<b>HOT</b> </span> </div>
</div>
<div id="div-redondo" class="d-flex ml-2 align-items-center justify-content-center">
<div class="text-hot align-middle">
list
</div>
</div>
</div>
</div>
<!-- Imagen de Pre-Carga-->
<div class="container-fluid d-flex justify-content-center" id="cont-preCarga" *ngIf="preCarga">
<img src="../../assets/images/slider/spinner.gif">
</div>
<app-modal [inmueble]="this.inmueble2" class="modal fade" id="exampleModal2" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"> </app-modal>
<carousel [itemsPerSlide]="itemsPerSlide"
[singleSlideOffset]="singleSlideOffset"
[interval]="false"
[noWrap]="noWrap">
<slide class="col-md-2" *ngFor="let imagenPortada of this.hostlistService.inmuebles; let index=index" style="width: 500px;">
<img src="{{url}}{{imagenPortada.id}}_{{imagenPortada.fotos[0]}}" alt="imagen de slide" style="display: block; width: 100%; height: 300px;"> <!-- <-----HERE IS WHERE I AM SHOWING THE IMAGES -->
<!--<img src="../../assets/images/slider/logo.png" alt="imagen de slide" style="z-index: 10; width: 100%; height: 300px; position: absolute; left: 0; top:0;">-->
<!-- <div class="carousel-caption">
<h4>Slide {{index}}</h4>
</div> -->
<div class="row">
<div class="col-12">
<p class="text-left text-precio"> <i class="fas fa-dollar-sign">
</i> Precio: {{imagenPortada.precio | currency: 'USD':true:'1.2-2'}}
</p>
</div>
</div>
<div class="row">
<div class="col-12">
<p class="text-left"> <i class="fas fa-map-marker-alt"></i> Ubicacion: {{imagenPortada.precio | currency: 'USD':true:'1.2-2'}}
</p>
</div>
</div>
<div class="row">
<div class="d-flex col-12">
<div class="cont-verDetalles d-flex justify-content-center">
<button (click)="obtenerInfo(imagenPortada)" type="button" class="mt-2 btn btn-secondary" data-toggle="modal" data-target="#exampleModal2">Ver detalles</button>
</div>
</div>
</div>
</slide>
</carousel>
This is an image of the carousel, where I only show 6 images, when I click on the "NEXT" or "PREV" button they run one by one to show the following:
And here you can see what I want to avoid, that they are loading the pile of images that I do not need to show until I need them in the carousel since they are too many:
How could I do to avoid that?
I would be very grateful to the person who can help me with this. Thanks in advance.
This is a good question. To start off, we'll have 2 arrays
a masterArray which has all the URLs of the images;
an imagesArray which will be array linked to the carousel, it will have only 1 image to start of with... which means that when the page loads, we had loaded only one image.
we simply add a url from the masterArray into the imagesArray on each slide change event [name of the event is: activeSlideChange];
relevant HTML (single slide carousel):
<carousel (activeSlideChange)='gotChange()'>
<slide *ngFor="let img of imagesArray; let idx of index" >
<img src="{{img}}" alt="slide {{idx}}" style="display: block; width: 100%;">
</slide>
</carousel>
relevant TS (single slide carousel):
import { Component, ViewChild } from '#angular/core';
import { CarouselComponent } from 'ngx-bootstrap';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
#ViewChild(CarouselComponent) myCarousel: CarouselComponent;
name = 'Angular';
masterArray = ['https://valor-software.com/ngx-bootstrap/assets/images/nature/1.jpg',
'https://valor-software.com/ngx-bootstrap/assets/images/nature/2.jpg',
'https://valor-software.com/ngx-bootstrap/assets/images/nature/3.jpg',
'https://valor-software.com/ngx-bootstrap/assets/images/nature/4.jpg',
'https://valor-software.com/ngx-bootstrap/assets/images/nature/5.jpg',
'https://valor-software.com/ngx-bootstrap/assets/images/nature/6.jpg',
'https://valor-software.com/ngx-bootstrap/assets/images/nature/7.jpg',
'https://valor-software.com/ngx-bootstrap/assets/images/nature/8.jpg',
];
imagesArray = ['https://valor-software.com/ngx-bootstrap/assets/images/nature/1.jpg'];
loopcomplete: boolean = false;
constructor() { }
gotChange() {
console.log('got change', this.myCarousel.activeSlide);
if (!this.loopcomplete) {
if (this.myCarousel.activeSlide + 1 < this.masterArray.length) {
this.imagesArray.push(this.masterArray[this.myCarousel.activeSlide + 1]);
} else { this.loopcomplete = true; }
}
}
}
complete working stackblitz here
the image to show the lazy loading of images
UPDATE: in light of questioner's comment below... the event that we're looking for is slideRangeChange
relevant HTML (multi slide carousel):
<carousel [itemsPerSlide]="itemsPerSlide"
[singleSlideOffset]="singleSlideOffset"
[noWrap]="noWrap"
(activeSlideChange)='gotChange()'
(slideRangeChange)='gotRangeChange()'
[showIndicators]='false'
[interval]='false'
>
<slide *ngFor="let img of imagesArray; let idx of index" >
<img [src]="img" alt="slide {{idx}}" style="display: block; width: 100%;">
</slide>
</carousel>
relevant TS (multi slide carousel):
import { Component, ViewChild } from '#angular/core';
import { CarouselComponent } from 'ngx-bootstrap';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
#ViewChild(CarouselComponent) myCarousel: CarouselComponent;
name = 'Angular';
masterArray = ['https://valor-software.com/ngx-bootstrap/assets/images/nature/1.jpg',
'https://valor-software.com/ngx-bootstrap/assets/images/nature/2.jpg',
'https://valor-software.com/ngx-bootstrap/assets/images/nature/3.jpg',
'https://valor-software.com/ngx-bootstrap/assets/images/nature/4.jpg',
'https://valor-software.com/ngx-bootstrap/assets/images/nature/5.jpg',
'https://valor-software.com/ngx-bootstrap/assets/images/nature/6.jpg',
'https://valor-software.com/ngx-bootstrap/assets/images/nature/7.jpg',
'https://valor-software.com/ngx-bootstrap/assets/images/nature/8.jpg',
];
imagesArray = ['https://valor-software.com/ngx-bootstrap/assets/images/nature/1.jpg',
'https://valor-software.com/ngx-bootstrap/assets/images/nature/2.jpg',
];
loopcomplete: boolean = false;
itemsPerSlide = 2;
singleSlideOffset = true;
noWrap = true;
activeRange = 0;
constructor() { }
gotRangeChange() {
if (!this.loopcomplete) {
if (this.activeRange + 2 < this.masterArray.length) {
this.activeRange = this.activeRange + 2;
this.imagesArray = this.imagesArray.concat(this.masterArray[this.activeRange]);
this.imagesArray = this.imagesArray.concat(this.masterArray[this.activeRange + 1]);
} else {
this.loopcomplete = true;
}
}
}
}
complete working stackblitz (multi slide carousel)

How to force containers to reorganize on disappearance of others in Vue?

I have a Vue project in which I'm displaying information about all projects hosted on a GitLab instance, e.g. name, ID, ... and most importantly, associated pipelines and their schedules.
I know how to display all projects (1 project = 1 card) and change their CSS behavior depending on their properties. For instance, the grey cards below correspond to projects with no scheduled pipelines and the blue ones have some pipelines scheduled:
Now I'd like to offer an alternative option to the user by letting them clicking a checkbox for displaying the projects with scheduled pipelines only.
On the page displaying the cards, I added the checkbox:
<template>
<input
type="checkbox"
name="showOnlyScheduled"
value="false"
id="checkbox-style"
v-model="checked"
>
Show only projects that have scheduled pipelines
<div class="row">
<div
class="col-sm-12 col-md-4 col-lg-3"
id="card-grid"
v-for="project in projects"
:key="project.id"
>
<Schedules
:projectName="project.name"
:projectId="project.id"
:projectUrl="project.web_url"
:checkBoxChecked="checked"
></Schedules>
</div>
</div>
</template>
And in the file handling card displaying:
<template>
<div>
<div
class="card card-block"
id="card-style"
:class="{ 'has-no-pipelines': !hasPipelines(), 'has-pipelines': hasPipelines(), 'disable-card': !hasPipelines() && checkBoxChecked}"
>
<div class="card-block">
<h5 class="card-title">
<a
id="title-link"
:href="projectUrl"
target="_blank"
rel="noopener noreferrer"
>{{ projectName }}</a>
</h5>
<div class="card-text">
<div v-if="this.schedules.pipelines.length > 0">
<div v-for="(pipeline,index) in schedules.pipelines" :key="index" id="schedules">
<p>
<a
:href="projectUrl + '/pipeline_schedules'"
id="link-schedules"
target="_blank"
rel="noopener noreferrer"
>Pipeline #{{ pipeline.id }}</a>
- {{ pipeline.description }}
</p>
</div>
</div>
<div v-else id="no-schedules">
<div>
<div>No scheduled pipelines yet.</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "Schedules",
props: {
projectName: String,
projectId: Number,
projectUrl: String,
checkBoxChecked: {
type: Boolean,
default: false
}
},
data() {
return {
schedules: {}
};
},
mounted() {
this.GitLabAPI.get(
"/projects/" + this.projectId + "/pipeline_schedules",
{},
[this.schedules, "pipelines"]
);
},
methods: {
hasPipelines() {
if (this.schedules.pipelines.length > 0) return true;
else return false;
}
}
};
</script>
<style scoped>
.has-pipelines {
background-color: #1565c0 !important; /* blue */
}
.has-no-pipelines {
background-color: #424242 !important; /* grey */
}
.disable-card {
visibility: hidden;
display: none;
opacity: 0;
}
</style>
This code indeed makes the cards with no scheduled pipelines disappear ... but the cards do not reorganize so to be next to one another:
I guess the cards don't realign because even though I disable some CSS properties, it doesn't make the containers disappear from the DOM.
How can I make the cards realign after I made some of them disappear?

Angular 6 not call ngClass

I have a component to show a left box. This component changes a public flag "flagBlocoLateral" to identify if this box is visible or not.
import {Component, Input, OnInit} from '#angular/core';
#Component({
selector: 'app-bloco-lateral',
template: `
<div class="bloco-lateral" [ngClass]="{'bloco-lateral--aberto':flagBlocoLateral}">
<div class="bloco-lateral__conteudo" *ngIf="flagBlocoLateral">
<div class="row">
<div class="col-12">
<h4>Ajuda</h4>
</div>
<div class="col-12" [innerHTML]="textoInformativo">
</div>
</div>
</div>
<div class="bloco-lateral__menu">
<ul>
<li matTooltip="Ajuda" (click)="toggleBlocoLateral(!flagBlocoLateral)">
<fa-icon icon="info-circle"></fa-icon>
</li>
</ul>
</div>
</div>`
})
export class BlocoLateralComponent implements OnInit {
#Input()
textoInformativo: string;
flagBlocoLateral = false;
constructor() {
}
ngOnInit() {
}
toggleBlocoLateral(flag) {
this.flagBlocoLateral = flag;
}
}
In my typescript code I'm using my compontent and a public "flagBlocoLateral" property to call ngClass. If I call toggleBlocoLateral inside component, ngClass not working.
<app-bloco-lateral #blocoLateral></app-bloco-lateral>
<div class="bloco-central" [ngClass]="blocoLateral.flagBlocoLateral ? 'bloco-central--resize':''">
But if I try print the "flagBlocoLateral" property outside the component (using {{blocoLateral.flagBlocoLateral}}), the attribute ngClass works fine.
Any Ideas?
Thanks.
Try to negate the value directly inside the called method and not by handing in a parameter. This step is actually not necessary.
In your HTML-File:
<li matTooltip="Ajuda" (click)="toggleBlocoLateral()">
In your TS-File:
toggleBlocoLateral() {
this.flagBlocoLateral = !this.flagBlocoLateral;
}

TypeError: Swiper is not a constructor

I'm trying to get Swiper to work but it always throw me an error "Swiper is not a constructor"
I'm using http://idangero.us/swiper/get-started/#.WMsuihJ96MI as the Swiper library and installed this library as a meteor package.
client/body.js
Template.slider.onRendered(function(){
var mySwiper = new Swiper ('.swiper-container', {
// Optional parameters
direction: 'vertical',
loop: true,
// If we need pagination
pagination: '.swiper-pagination',
// Navigation arrows
nextButton: '.swiper-button-next',
prevButton: '.swiper-button-prev',
// And if we need scrollbar
scrollbar: '.swiper-scrollbar',
});
});
client/body.html
<body>
<h1>Test</h1>
{{> slider }}
</body>
<template name="slider">
<!-- Slider main container -->
<div class="swiper-container">
<!-- Additional required wrapper -->
<div class="swiper-wrapper">
<!-- Slides -->
<div class="swiper-slide">Slide 1</div>
<div class="swiper-slide">Slide 2</div>
<div class="swiper-slide">Slide 3</div>
</div>
<!-- If we need pagination -->
<div class="swiper-pagination"></div>
<!-- If we need navigation buttons -->
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
<!-- If we need scrollbar -->
<div class="swiper-scrollbar"></div>
</div>
</template>
#mutdmour You should try Swiper.default(element,options)
Make sure to console you Swiper instance and check if, It's really a constructor or it's an object which has it's constructor in it's property. Sorry if I give a wrong info. Because my english is very weak and this is my first reply to a Forum.
In my case i fixed it by changing
import {Swiper, SwiperOptions} from "swiper";
to
import Swiper, {SwiperOptions} from "swiper";

Resources