class active CSS issue in angular - css

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.

Related

Angular material; How to change mat-menu background color programmatically?

I have this piece of code for my mega menu:
<button mat-button [matMenuTriggerFor]="objectmenu">Objects</button>
<mat-menu #objectmenu="matMenu" >
<div class="menu-content" [style.backgroundColor]="getUnSelectedRandomColor()" style="height: 550px;">
<div fxFlex="100" fxFlex.gt-sm="30" fxFlex.sm="45" class="dropdown-menu-items">
<div class="dropdown-menu-btns" *ngFor="let parent of (objectList$ | async)"
(mouseover)="openCategory($event,
parent)"
[style.background-color] = "this.selectedColor === (parent.categoryId * 100) ? getSelectedRandomColor() : getUnSelectedRandomColor()"
>{{parent.name}}</div>
</div>
<div class="theme-container">
<div class="theme-container" style=" padding-bottom: 0px !important; padding-top: 7px !important;">
<div fxLayout="column" fxLayout.gt-sm="row wrap" fxLayoutAlign="center center" class="content border-lighter">
<div fxFlex="100" fxFlex.gt-sm="100" fxLayout="column" fxLayoutAlign="center center">
<h2 *ngIf="this.selectedCategory" class="uppercase">{{this.selectedCategory.name}}</h2>
</div>
</div>
<div class="content border-lighter" [style.backgroundColor]="getSelectedRandomColor()" style="height: 380px;">
<div fxLayout="row wrap" fxLayoutAlign="space-between">
<div fxFlex="100" fxFlex.gt-sm="70" fxFlex.sm="45" style="column-count: 2;">
<ul class="ht-dropdown megamenu-two d-flex"
*ngFor="let parent of (childCategories$ | async)" style="list-style: none;">
<label [routerLink]="['/products']" [queryParams]="{categories: parent.categoryId}"
routerLinkActive="router-link-active">{{parent.name}}</label>
<li *ngFor="let child of parent.childrenCategories"
[routerLink]="['/products']" [queryParams]="{categories: child.categoryId}"
routerLinkActive="router-link-active">
{{child.name}}
</li>
</ul>
</div>
<div fxFlex="100" fxFlex.gt-sm="30" ngClass.lt-md="pt-5" style="background-size: contain !important;"
[style.background]="selectedCategoryUrl">
</div>
</div>
</div>
</div>
<div fxLayout="row" fxLayout.xs="column" fxLayoutAlign="space-between center" >
<img *ngFor="let brand of (relatedBrandsList$ | async)" [src]=" brand.thumbnail | safeHtml" style="width: 110px; height: 110px; border-radius: 50%;"/>
</div>
</div>
</div>
</mat-menu>
and it gives me the following style:
As shown in the picture, the top and the bottom edges of the menu panel are not taking the dynamic background color which I generate in my angular code by getUnSelectedRandomColor() method.
The getUnSelectedRandomColor() method is as follow:
openCategory(evt, category: Category) {
this.selectedCategory = category;
this.selectedCategoryUrl = `url('../../assets/categories/${category.categoryId}.webp')`;
this.childCategories$ = this.store.pipe(select(getChildCategories(category.categoryId)));
this.relatedBrandsList$ = this.store.pipe(select(getRelatedBrands(category.categoryId)));
this.selectedColor = category.categoryId * 100;
}
getSelectedRandomColor() {
const color = 'hsl(' + this.selectedColor + ', 30%, 75%)';
return color;
}
getUnSelectedRandomColor() {
const color = 'hsl(' + this.selectedColor + ', 30%, 86%)';
return color;
}
How can I do this?
Angular 9
What happens is that you are not affecting the menu panel item, you must get the panelId which is a property of MatMenu, with the panel id you get the element and then change the value of the attribute you want, to achieve this you can use property decorator that configures a view query ViewChild and the service Renderer2.
Here I show you an example in which I dynamically change the background of the panel according to the menu item that emits the mouseover stackblitz
import { Component, ViewChild, Renderer2 } from '#angular/core';
import { MatMenu } from '#angular/material/menu/';
#Component({
selector: 'my-app',
template: './app.component.html',
})
export class AppComponent {
#ViewChild('menu', {static: true}) menu: MatMenu
constructor(private _renderer2: Renderer2) {
}
changeBackgroundPanel(colorValue: string) {
const el = document.getElementById(this.menu.panelId);
this._renderer2.setStyle(el, 'background', colorValue);
}
}
<button mat-raised-button [matMenuTriggerFor]="menu" color="primary">Open Menu</button>
<mat-menu #menu="matMenu">
<button mat-menu-item (mouseover)="changeBackgroundPanel('blue')">Blue</button>
<button mat-menu-item (mouseover)="changeBackgroundPanel('orange')">Orange</button>
<button mat-menu-item (mouseover)="changeBackgroundPanel('red')">Red</button>
</mat-menu>
[Solution for Angular 8]
See the example working here: stackblitz
Component:
import { Component, Renderer2 } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.scss' ]
})
export class AppComponent {
constructor(private _renderer2: Renderer2) {
}
changeBackgroundPanel(colorValue: string) {
const el = document.getElementById('myPanelId');
this._renderer2.setStyle(el, 'background', colorValue);
}
}
Html:
<button mat-raised-button [matMenuTriggerFor]="menu" color="primary">Open Menu</button>
<mat-menu #menu="matMenu">
<div id="myPanelId" class="menu-panel">
<button mat-menu-item (mouseover)="changeBackgroundPanel('blue')">Blue</button>
<button mat-menu-item (mouseover)="changeBackgroundPanel('orange')">Orange</button>
<button mat-menu-item (mouseover)="changeBackgroundPanel('red')">Red</button>
</div>
</mat-menu>
CSS:
.menu-panel {
margin: -8px 0;
padding: 8px 0;
}
Finally I found the answer:
::ng-deep .mat-menu-content{
padding-top: 0px !important;
padding-bottom: 0px !important;
}
I removed the paddings using the above style and then the white gaps were removed

Multiple stylesheets issue using React

I am new to react, I have an issue on how to maintain stylesheets in react.
For Eg: If I have box structures in different components with the same class names which are import to Page-A & Page-B, I maintained different stylesheets & appended those to their respective pages. If I change the style properties for Page-B in respective stylesheet using the same class name, changes are reflecting in both the Page-A & Page-B pages, which is suppose to reflect in Page-B only. Please help to solve this.
Page-A<div class="wrapper">Headline<div>.wrapper{background:red; width:200px; height:200px;}
Page-B<div class="wrapper">Headline<div>.wrapper{background:black; width:400px; height:400px;}
import React, { Component } from 'react';
import NavbarafterLogin from './NavigationBar/navbarafterlogin';
import '../../Css/afterlogins.css';
class Home extends Component {
render() {
return (
<div class="col-sm-12 col-xs-12">
<NavbarafterLogin/>
<div class="body-wrapper">
<div class="container">
<ViewProfile/>
</div>
</div>
</div>
)
}
}
export default Home;
import React, { Component } from 'react'
import NavbarBeforeLogin from './NavigationBar/navbarbeforelogin';
import '../../Css/beforelogins.css';
class Index extends Component {
render() {
return (
<div class="col-sm-12 col-xs-12">
<NavbarBeforeLogin />
<div class="body-wrapper clearfix">
<div class="col-sm-12 col-xs-12">
<div class="banner-sec">
<div class="jumbotron">
<div class="container">
<h1>Submit <strong>Profile</strong></h1>
</div>
</div>
</div>
</div>
</div>
</div>
)
}
}
export default Index;

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)

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;
}

I can't put a CSS class on a template

I'm reading a book about Angular 2 and one of the chapters is about Forms. I'm using Semantic UI Framework and when I put a class, specify the "error" class the div is disappear. Is very very strange I don't know what happened. I have to mention what works perfectly if I replace "error" class with another like "negative" for instead.
import { Component } from '#angular/core';
import {
FormBuilder,
FormGroup,
Validators,
AbstractControl,
FormControl
} from '#angular/forms';
#Component({
selector: 'demo-form-sku-builder',
template: `
<div class="ui raised segment">
<h2 class="ui header">Demo Form: Sku with Builder</h2>
<form [formGroup]="myForm"
(ngSubmit)="onSubmit(myForm.value)"
class="ui form">
<div class="field"
[class.error]="!sku.valid && sku.touched">
<label for="skuInput">SKU</label>
<input type="text"
id="skuInput"
placeholder="SKU"
[formControl]="myForm.controls['sku']">
<div *ngIf="!sku.valid"
class="ui error message">SKU is invalid</div>
<div *ngIf="!sku.hasError('required')"
class="ui error message">SKU is required</div>
</div>
<button type="submit" class="ui button">Submit</button>
</form>
</div>
`
})
export class DemoFormSkuBuilder {
myForm: FormGroup;
sku: AbstractControl;
constructor(fb: FormBuilder) {
this.myForm = fb.group({
'sku': ['', Validators.required]
});
this.sku = this.myForm.controls['sku'];
}
onSubmit(value: string): void {
console.log('you submitted value: ', value);
}
}
Is this if statement backwards?
<div *ngIf="!sku.hasError('required')"
class="ui error message">SKU is required</div>
Shouldn't it be:
<div *ngIf="sku.hasError('required')"
class="ui error message">SKU is required</div>
Without the not operator?
Use below code instead of [class.error]="!sku.valid && sku.touched"
<div class="field" [ngClass]="{ 'error' : !sku.valid && sku.touched}">
For more detail
Another way of doing is
import { Component } from '#angular/core';
import {
FormBuilder,
FormGroup,
Validators,
AbstractControl,
FormControl
} from '#angular/forms';
#Component({
selector: 'demo-form-sku-builder',
template: `
<div class="ui raised segment">
<h2 class="ui header">Demo Form: Sku with Builder</h2>
<form #myForm=ngForm
(submit)="onSubmit(myForm.value)"
class="ui form">
<div class="field"
[ngClass]="{ 'error' : !sku.valid && sku.touched}">
<label for="skuInput">SKU</label>
<input type="text"
id="skuInput"
placeholder="SKU"
name='sku'
#sku='ngModel' ngModel
required>
<div *ngIf="!sku.valid"
class="ui error message">SKU is invalid</div>
<div *ngIf="!sku.touched && !sku.errors?.required"
class="ui error message">SKU is required</div>
</div>
<button type="submit" class="ui button">Submit</button>
</form>
</div>
`
})
export class DemoFormSkuBuilder {
constructor() {
}
onSubmit(value: string): void {
console.log('you submitted value: ', value);
}
}
Fixed. by default, semantic UI hides these unless the whole form is in the same state. You can create an another css called styles.css for example and use this:
.ui.form .error.message,
.ui.form .success.message,
.ui.form .warning.message {
display: block;
}

Resources