I'm trying to do a simple thing in my Angular 7 application.
Basically, I have a title and when I click on it, a comment will ease-in from above to place itself just below the title. The problem is, when the comment is moving, it shows on top of the title which is not quite the effect wanted.
I tried adding a z-index property on the CSS to elevate the title but to no avail.
app.component.ts
import { Component } from '#angular/core';
import { trigger, transition, style, animate } from '#angular/animations';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ],
animations: [
trigger('slideInOut', [
transition(':enter', [
style({transform: 'translateY(-100%)'}),
animate('200ms ease-in', style({transform: 'translateY(0%)'}))
]),
transition(':leave', [
animate('200ms ease-in', style({transform: 'translateY(-100%)'}))
])
])
]
})
export class AppComponent {
visible = false;
showMessage() {
this.visible = !this.visible;
}
}
app.component.html
<div (click)="showMessage()">
<div class="title">Click here to reveal the comment</div>
<div class="title">25/04/2019 17:30:00</div>
<div class="comment" *ngIf="visible" [#slideInOut]>Lorem ipsum...</div>
</div>
app.component.css
.title {
background-color: aqua;
z-index: 1000;
cursor: pointer;
}
.comment {
background-color: red;
z-index: 0;
}
I created a StackBlitz to show the problem.
Thanks for your help!
In order to z-index work. You need to add position: relative or absolute to the element. In your case, add also position: relative to the .title.
You can add the following:
.title, .comment{
position:relative;
}
z-index only works on positioned elements (position: absolute, position: relative, position: fixed, or position: sticky).
See Fork
Related
HTML
<div class="nav--small nodeLevel newColor" id="rowItem-{{i}}" *ngFor="let root of rootzTemplates; let i=index" (click)="nodeClickLevel1(root,i)">
<p style="padding: 19px 1px;color: #fff; text-align: center;">
{{root}}
</p>
</div>
CSS
.activeColor {
background-color: grey;
}
JavaScript
constructor(private el: ElementRef) { }
nodeClickLevel1(root, id){
this.myTag = this.el.nativeElement.querySelector("#rowItem-" + id);
this.myTag.classList.remove('activeColor');
this.myTag.classList.add('activeColor');
}
Now div is dynamic, say number of div element is 6, on click event i have to change particular clicked div background-color to grey and rest of color should remain same.
Now if I click on div say 2, only 2nd div has highlight with grey color, rest of the color should remain same and vice versa.
Change your function like this
nodeClickLevel1(root, id){
this.myTag = root
}
change your template code like this
[class.newColor]="root === myTag"
Hope it will solve your problem.
Your code can be much simpler, no need for troublesome ElementRef, no need for index ids, etc.
So here is the code:
//our root app component
import { Component, NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
#Component({
selector: 'my-app',
// templateUrl: "app.html",
template: `
<div class="nav--small nodeLevel newColor" [class.activeColor]="root === myTag" *ngFor="let root of rootzTemplates" (click)="nodeClickLevel1(root)">
<p style="padding: 19px 1px;color: #fff; text-align: center;">{{root}}</p>
</div>
`,
})
export class App {
name: string;
constructor() { }
protected myTag:any;
public rootzTemplates: any[] = ["first", "2nd", "3rd"];
nodeClickLevel1(root){
this.myTag = root;
}
}
#NgModule({
imports: [BrowserModule],
declarations: [App],
bootstrap: [App],
})
export class AppModule {}
and css:
.activeColor {
background-color: grey !important;
}
.nav--small{
background-color: black;
}
Here is the working PLNKR link:
http://plnkr.co/edit/oRZa3E5WtYpusKHd
I am working on angular formio, in that I am using a custom css class, name CustomCSS I have added the same in css file as follows
Here is stackblitz
app.component.scss
.CustomCSS {
margin: auto;
width: 50%;
border: 3px solid rgb(1, 248, 1);
padding: 10px;
background-color: coral;
}
app.component.ts
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
ngOnInit() {
debugger;
this.triggerRefresh = new EventEmitter();
this.http.get('http://....')
.subscribe(
response => {
this.form = response.json();// this is my html script from DB
},
err => {console.error(err)}
);
}
}
app.component.html
<formio [refresh]="triggerRefresh" [form]="form" [submission]="submission" (submit)="onSubmit($event)"></formio>
My Html this.form script as follows
{
"components":[
{
"label":"City",
"widget":"choicesjs",
"customClass":"CustomCSS",
"tableView":true,
"data":{
"values":[
{
"label":"abc",
"value":"abc"
]
},
"selectThreshold":0.3,
"calculateServer":false,
"validate":{
"required":true
},
"key":"city",
"type":"select",
"indexeddb":{
"filter":{
}
},
"input":true
},
{
"type":"button",
"label":"Submit",
"key":"submit",
"disableOnInvalid":true,
"input":true,
"tableView":false
}
],
"id":4
}
In my script also the css class name available but it is not appending in the view.
One possible way to make it work from your component is to modify the style encapsulation for that component.
import { Component, OnInit, ViewEncapsulation } from '#angular/core'; // <-- add ViewEncapsulation
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ],
encapsulation: ViewEncapsulation.None // <-- add this line
})
More information on encapsulation.
That being said.
I still recommend to use global styles and implement css selectors to target formio generated html elements like in your example:
#app formio .control-label {
font-weight: bold;
}
I'm trying to animate a div, when the mouse enters that specific div, apparently i couln't make it done.
Any ideas how this would work in my context?
This is the animations inside the TS file
animations: [
trigger('explainerAnim', [
transition('* => *', [
query('.card', style({ opacity: 0, transform: ' translateX(-400px'})),
query('.card', stagger('100ms', [
animate('1000ms 0.9s ease-out', style({opacity:1, transform: 'translateX(0)'}))
]))
])
])
]
And this is the div that i want to show based on mouse enter
<div [#explainerAnim] class="col-sm-12 text-center about-page">
<div class="card">
<div class="developer-photo"></div>
<div class="card-body">
<h2>Who`s this guy?</h2>
<p>
I'm a Full-Stack Developer working for AppyWay in London. <br />
I have a serious passion for implementing high quality web
applications <br />
using the Microsoft stack E.g .Net Core.
</p>
</div>
</div>
<div class="card developer-details">
<div class="card-header developer-header">
<h2>I`m Norbert Csibi</h2>
<h5>Full-Stack Developer</h5>
</div>
<div class="card-body">
<p>
I am passionate about building excellent software that improves
the lives of those around me.
</p>
<table class="table table-borderless">
<thead>
<tr>
<th scope="col"></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">EMAIL</th>
<td>#gmail.com</td>
</tr>
<tr>
<th scope="row">PHONE</th>
<td>55255</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
You can add a (mouseenter) and (mouseleave) directives on the div element that you want to trigger the animation.
<div (mouseenter)="startAnimation()" (mouseleave)="stopAnimation()">
</div>
Then you can use the angular animation states to add two states, one animated and the other without it. And set the two different states inside the startanimation() and stopAnimation() methods.
Here I let you an example of how to use the angular states:
In the TypeScript:
#Component({
selector: 'app-open-close',
animations: [
trigger('openClose', [
// ...
state('open', style({
height: '200px',
opacity: 1,
backgroundColor: 'yellow'
})),
state('closed', style({
height: '100px',
opacity: 0.5,
backgroundColor: 'green'
})),
transition('open => closed', [
animate('1s')
]),
transition('closed => open', [
animate('0.5s')
]),
]),
],
templateUrl: 'open-close.component.html',
styleUrls: ['open-close.component.css']
})
export class OpenCloseComponent {
isOpen = true;
toggle() {
this.isOpen = !this.isOpen;
}
}
In the HTML:
<div [#openClose]="isOpen ? 'open' : 'closed'" class="open-close-container">
<p>The box is now {{ isOpen ? 'Open' : 'Closed' }}!</p>
</div>
Since this question was high in my search ranking, and is not that old 😉, I think others might be helped with a 'full' example
You can position the diw with the.highlight class with relative/absolute positions, but I use css-grid in this example.
TLDR;
Hostlisteners are used to change the animation states
when mouse enters and leaves
#HostListener('mouseenter', ['$event'])
onOver(event: MouseEvent): void {
this.highlightAnimationState = this.highlightStates.mouseEnter;
// console.log('mouseenter');
// console.log('Enter: this.highlightAnimationState :>> ', this.highlightAnimationState );
}
Full example >>
this is a class used to represent a row, a race track, for a team, like this:
| Team Name | (dots representing percent of max until finished at 100%) | Team Info
it is used like this in the parent component (having an array of teams to display).
race-board.component.html
<main class="main-content">
<div *ngFor="let team of raceTeams">
<app-race-track [team]="team">
<!-- if you are not familiar with ng-content (see 'app-race-track' component)
it is simply used to output whatever is inside the tags here -->
<app-race-track-divider [colorClass]="dividerPositions.getColor(i)"></app-race-track-divider>
</app-race-track>
</div>
</main>
race-track.component.html
<div
class="race-track-row"
*ngIf="team; else loadingTemplate">
<div [#highlightTrigger]="highlightAnimationState" class="highlight">
<!-- note, this is used to create higlight effect on mouseover -->
</div>
<div class="divider">
<ng-content>
<!-- here a divider line is printed; if it should be. -->
</ng-content>
</div>
<div class="team-details">
<div class="team-name">
{{team?.Name | shorten | uppercase }}
</div>
</div>
<div class="race-track" #raceTrackContainer>
<ng-container *ngFor="let item of filledDots; let i = index">
<div class="percentage-dot" id="filled-dot-{{i}}">
<mat-icon class="mat-icon-scale-up mat-icon-color-dark-grey" [inline]="true">
lens
</mat-icon>
</div>
</ng-container>
</div>
<div class="team-info">
<img src="../assets/images/race-board/raceboard-team-image.png" />
</div>
</div>
<ng-template #loadingTemplate>
... Loading race team ...
</ng-template>
</div>
You can position the div with the .highlight class using relative/absolute positions, but I use css-grid and it looks like this
race-track.component.scss
#use 'src/app/race-board-app-module' as appStyles;
/* the container of the component */
.race-track-row {
position: relative;
margin-top: 0.4rem;
width: fit-content;
display: grid;
grid-template-columns: 200px auto 80px;
grid-template-rows: auto 3rem ;
row-gap: 0.3rem;
// column-gap: 15px;
/* note: use dots to leave an area blank */
grid-template-areas:
" . track-divider . "
" team-details race-track team-info ";
}
/*note, this is used to create highlight effect on mouseover */
.highlight{
width: 100%;
grid-row: 2/3;
grid-column: 1/4;
}
.divider {
grid-area: track-divider;
}
.race-track{
grid-area: race-track;
position: relative;
padding-left: 2rem;
padding-right: appStyles.$race-track-padding-right;
display: flex;
flex-wrap: nowrap;
}
/** name (perhaps also icon and percent later?) */
.team-details {
grid-area: team-details;
justify-self: right;
align-self: center;
margin-right: 0.5rem;
padding-left: 1rem;
}
.team-name{
font-weight: 500;
}
.percentage-dot {
// align-items: center;
padding-left: appStyles.$padding-dots-container;
align-self: center;
}
.team-info{
grid-area: team-info;
display: flex;
align-items: center;
justify-content: center;
align-self: center;
}
/* variable must be imported like this for scale and calc to function */
$icon-scale: appStyles.$icon-scale;
.mat-icon-scale-up {
transform: scale($icon-scale);
padding: appStyles.$padding-dot-icons;
}
race-track.component.ts
/* you probably don't need all of the imports here, but cpy paste from implentation so .. */
import { Component, Input, OnInit, OnDestroy, ViewChild, ElementRef, AfterViewChecked, Renderer2, HostListener } from '#angular/core';
import { trigger, state, style, transition, animate, keyframes } from '#angular/animations';
#Component({
selector: 'app-race-track',
templateUrl: './race-track.component.html',
styleUrls: ['./race-track.component.scss'],
animations: [
trigger('highlightTrigger', [
state('in', style({
opacity: 0.1,
backgroundColor: 'lightblue'
})),
state('out', style({
opacity: 0.0,
backgroundColor: 'lightblue'
})),
/*
this transitions has keyframes to controll the in-out speed with offset (time in point from in to out, ) you can also use
*/
transition('* <=> *', animate(50, keyframes([
style({
opacity: 0.03,
offset: 0.3
}),
style({
opacity: 0.05,
offset: 0.5
}),
style({
opacity: 0.1, /* this should, but don't have to, match the 'final' state (i.e. 'in') */
offset: 1
}),
])))
])
]
})
export class RaceTrackComponent implements OnInit, OnDestroy, AfterViewChecked {
//animation:
highlightAnimationState = "";
highlightStates = {
mouseEnter: 'in',
mouseLeave: 'out'
}
#Input() public team?: RaceBoardTeam;
/** dark icons; reprecenting team score as percent of max */
public filledDots?: number[];
constructor() { }
/** Animations: hostlisteners are used to change the animation states
* when mouse enters and leaves the race-track
*/
#HostListener('mouseenter', ['$event'])
onOver(event: MouseEvent): void {
this.highlightAnimationState = this.highlightStates.mouseEnter;
// console.log('mouseenter');
// console.log('Enter: this.highlightAnimationState :>> ', this.highlightAnimationState );
}
#HostListener('mouseleave', ['$event'])
onOut(event: MouseEvent): void {
this.highlightAnimationState = this.highlightStates.mouseLeave;
// console.log('mouseleave');
// console.log('Leave: this.highlightAnimationState :>> ', this.highlightAnimationState );
}
// other stuff omitted ....
}
app.html
<app-chat></app-chat>
chat.html
<h1>Hello</h1>
chat.ts
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-chat',
templateUrl: './chat.component.html',
styleUrls: ['./chat.component.css']
})
export class ChatComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
chat.css
h1 {
background-color: #000;
}
I need to know why the chat.css doesn't work in my browser. When I used CSS directly without chat component it works (like below).
app.html
<h1>Hello</h1>
app.css
h1 {
background-color: #000;
}
So what is the solution?
Try this!
::ng-deep h1{
background-color: #000;
}
Try !important in your chat.css file
h1{
background-color: #000 !important;
}
or
Use the powerful weapon of CSS style.css. But, before using it you have to set the class name for h1 tag.
chat.html
<h1 class="exampleClassName">Helo<h1>
Next, in your style.css file
.exampleClassName{
background-color: #000;
}
I did an example and it works: https://stackblitz.com/edit/angular-u99pry
Is it possible to do the following....
app.component.html
<app-nav></app-nav>
<div class="page-wrapper">
<div class="page-content clearfix">
<router-outlet></router-outlet>
</div>
</div>
Can I apply following CSS to page-wrapper and page-content class when router to particular Component and after going to other Component remove as it is... ?
CSS
.page-content {
margin-bottom: 0px;
}
#media screen and (min-width: 1367px) {
.page-wrapper {
width: 100%;
}
}
I also try View Encapsulation option (None) but this apply style to header which is always their... even I route to other Component.
#Component({
// ...
encapsulation: ViewEncapsulation.None,
styles: [
// ...
]
})
You are on the right track and need to style the page-wrapper and page-content from each component that displayed in the <router-outlet> by using ViewEncapsulation.None. So, by writing styles like this, every time the parent elements's(page-wrapper and page-content) styles will be override based on component.
#Component({
selector: 'component-x',
encapsulation: ViewEncapsulation.None,
styles: [`
.page-wrapper, .page-content{
background-color: red;
}
`]
});
#Component({
selector: 'component-y',
encapsulation: ViewEncapsulation.None,
styles: [`
.page-wrapper, .page-content{
background-color: green;
}
`]
});