Trigger Event on route change Angular 4 - javascript

Hey I have two header components header.component and header-home.component so when your on the homepage you see the header-home and when your not you just see header now In my header component Ive set up an .active class that puts an underline underneath the selected nav item which works when going between the nav on the pages with the header.component but not when I click on the nav in the header-home which takes me to a page that now has header
app.component.ts
import { Component, OnInit } from '#angular/core';
import { Router, Event, NavigationStart } from '#angular/router';
import { NgIf } from '#angular/common';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
routeHidden = true;
title = 'app';
constructor(private router: Router)
{}
ngOnInit() {
this.router.events.subscribe( (e) => {
if (e instanceof NavigationStart) {
if (e.url === '/') {
this.routeHidden = false;
} else {
this.routeHidden = true;
}
}
});
}
}
app.component.html
<app-header *ngIf="routeHidden"></app-header>
<app-header-home *ngIf="!routeHidden"></app-header-home>
<router-outlet></router-outlet>
<app-footer></app-footer>
header.component.ts
import { Component, OnInit } from '#angular/core';
import { NgStyle } from '#angular/common';
declare var jquery: any;
declare var $: any;
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {
title: any;
image: any;
constructor(
) { }
ngOnInit() {
$('.hamburger').click(function(){
$('.hamburger').toggleClass('is-active');
$('.mobile-nav_ul').toggleClass('mobile-nav_ul_active');
});
$('.mobile-nav_ul').click(function(){
$('.hamburger').toggleClass('is-active');
$('.mobile-nav_ul').toggleClass('mobile-nav_ul_active');
});
$('ul li').on('click', function() {
$('li').removeClass('active');
$(this).addClass('active');
});
}
basically is there a way I can grab that click event in the header-home.component and then apply the .active class to the nav item I clicked on in the header.component
any help would be appreciated!

Related

Angular: hiding a component with *ngIf doesn't work

I have just started with Angular and have already faced an issue: a button actually toggles the variable I need (show) but it doesn't affect the course.component
course.component must show app-csgo-course, boolean show is true because the component is visible, but after it toggles in navbar.component, nothing changes.
<app-csgo-course *ngIf="show"> </app-csgo-course>
import { NavbarComponent } from './../navbar/navbar.component';
import { Component, OnInit} from '#angular/core';
import { CourseService } from 'src/app/course.service';
#Component({
selector: 'app-course',
templateUrl: './course.component.html',
styleUrls: ['./course.component.css']
})
export class CourseComponent implements OnInit {
constructor() { }
ngOnInit(): void { }
service = new CourseService;
show = this.service.GetShow();
}
In navbar.component there's a button which toggles the "show" variable
<button (click)="ToggleShow()" >
<li class="nav-item active" id="csgo-logo">
<a href="#">
<img class="game-logo" src="assets\img\csgo-logo.png" title="Counter Strike: Global Offensive">
<!-- <a>CS:GO <span class="sr-only">(current)</span></a> -->
</a>
</li>
</button>
import { CourseService } from 'src/app/cheat.service';
import { Component, OnInit, Input, Output, } from '#angular/core';
#Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {
service = new CourseService;
show = this.service.GetShow();
ngOnInit(): void {
}
public ToggleShow() {
this.service.show = this.service.ToggleShow();
console.log(this.service.show);
return this.service.show;
}
}
The course.service file
#Injectable({
providedIn: 'root'
})
export class CourseService {
show: boolean = true;
GetShow() {
return this.show;
}
ToggleShow() {
return this.show = !this.show
}
constructor() { }
}
}
Would appreciate your help!
Since you are new to Angular, let me break it down for you.
You need to create a BehaviorSubject to capture the event of toggle (this is called reactive programming which is a achieved using RxJS in Angular ).
Do not use new for a service, rather inject it in constructor.
course.service
#Injectable({
providedIn: 'root'
})
export class CourseService {
private show: boolean = true;
private toggle$ = new BehaviorSubject<boolean>(true);
constructor() { }
toggleEvent() {
return this.toggle$.asObservable();
}
toggleShow() {
this.show = !this.show
this.toggle$.next(this.show);
}
}
in NavbarComponent
import { CourseService } from 'src/app/cheat.service';
import { Component, OnInit, Input, Output, } from '#angular/core';
#Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {
show = boolean;
// IMP: make sure to inject the service and not do "new CourseService;"
constructor(public service: CourseService){}
ngOnInit(): void {
this.service.toggleEvent().subscribe(showFlag => {
this.show = showFlag;
})
}
public ToggleShow(): void {
this.service.toggleShow();
}
}
in courseComponent
import { Component, OnInit} from '#angular/core';
import { CourseService } from 'src/app/course.service';
#Component({
selector: 'app-course',
templateUrl: './course.component.html',
styleUrls: ['./course.component.css']
})
export class CourseComponent implements OnInit {
show: boolean ;
// IMP: make sure to inject the service and not do "new CourseService;"
constructor(public service: CourseService){}
ngOnInit(): void {
this.service.toggleEvent().subscribe(showFlag => {
this.show = showFlag;
})
}
}
PS: I would suggest you to read about "how to unsubscribe an observable" and how it causes memory leaks. Once you get some idea, you should implement that in the above provided code as well. That's a best practice. Happy learning. Let me know if you have any more questions

How to update other component html text value

This is my app.component.html source code:
<split-flap></split-flap>
<button (click)="flip('+')">+</button><button (click)="flip('-')">-</button>
This is my app.component.ts source code:
import { Component } from '#angular/core';
import { SplitFlapComponent } from './split-flap/split-flap.component';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers:[SplitFlapComponent]
})
export class AppComponent {
constructor(private splitFlapComponent: SplitFlapComponent)
{
}
flip(flag)
{
console.log(flag);
this.splitFlapComponent.title=flag;
}
}
This is my split-flap.component.ts:
import { Component, OnInit, Input, Output } from '#angular/core';
#Component({
selector: 'split-flap',
templateUrl: './split-flap.component.html',
styleUrls: ['./split-flap.component.css']
})
export class SplitFlapComponent implements OnInit {
title: string;
constructor() {
this.title = 'split-flap works1!';
}
ngOnInit() {
}
}
This is my split-flap.component.html:
<p>{{title}}</p>
My app.component.html has two buttons, both of them pass a sign to split-flap.component, would you tell me how can I the update split-flap.component.html content? Because most of the examples for input box only, I cannot find an example for <p>.
Try like this:
Solution 1 : #Input()
app.component.html
<split-flap [title]="title"></split-flap>
app.component.ts
title: string;
constructor() {
this.title = 'split-flap works1!';
}
flip(flag)
{
console.log(flag);
this.title=flag;
}
split-flap.component.ts:
#Input() title: string
Solution 2 : ViewChild()
app.component.html
<split-flap #child ></split-flap>
app.component.ts
#ViewChild('child') child: SplitFlapComponent ;
flip(flag)
{
console.log(flag);
this.child.title=flag;
}

Theme switcher on localstorage observable service

I implemented a dynamic theme switcher (with tutorial) in my angular app. It work's but when I reload website, the choice is not remembered.
I read about localStorage and i will use it but still doesn't work because I don't know how "where" I should get data from this localStorage, that the choice of the theme will be remembered when I reload the page.
I have this code:
theme.service.ts new version
import { Injectable } from '#angular/core';
import { Subject } from 'rxjs/Subject';
#Injectable()
export class ThemeService {
private _themeDark: Subject<boolean> = new Subject<boolean>();
isDarkFunction() {
let value = localStorage.getItem('isDark');
this._themeDark.next(value);
return this._themeDark.asObservable();
}
isThemeDark = this.isDarkFunction();
setDarkTheme(isThemeDark: boolean) {
this._themeDark.next(isThemeDark);
localStorage.setItem('isDark', JSON.stringify(isThemeDark));
}
}
navbar.component.html
<div class="container-fluid switcher-container">
<mat-slide-toggle [checked]="isThemeDark | async" (change)="toggleDarkTheme($event.checked)">Dark theme</mat-slide-toggle>
</div>
navbar.component.ts
import { Component, OnInit } from '#angular/core';
import { ThemeService } from '../services/theme.service';
import { Observable } from 'rxjs/Observable';
#Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.scss']
})
export class NavbarComponent implements OnInit {
isThemeDark: Observable<boolean>;
constructor(
private themeService: ThemeService) { }
ngOnInit() {
this.isThemeDark = this.themeService.isThemeDark;
}
toggleDarkTheme(checked: boolean) {
this.themeService.setDarkTheme(checked);
}
}
app.component.ts
import { Component, OnInit } from '#angular/core';
import { Observable } from "rxjs/Observable";
import { ThemeService } from "./services/theme.service";
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
providers: [ThemeService]
})
export class AppComponent implements OnInit {
isThemeDark: Observable<boolean>;
constructor(
public themeService: ThemeService) {
}
ngOnInit() {
this.isThemeDark = this.themeService.isThemeDark;
}
}
Please help,
Regards
You might write something like the following in theme.service.ts.
I don't know if it will run flawlessly as is but the idea is to read from localstorage in isThemeDark().
isThemeDark() {
let value = localStorage.getItem('isDark');
this._themeDark.next(value);
return this._themeDark.asObservable();
}
I think it's because you when you do localStorage.getItem('isDark') the result is a string, not a boolean. Maybe try:
let value = JSON.parse(localStorage.getItem('isDark')) === true;
Also check manually if the localstorage is kept after a refresh. Some browsers have a setting to clear everything on refresh.

Call modal from one sibling component to other angular

I have this Angular6 component arquitecture in my app
Main component
<app-navbar></app-navbar>
<app-dashboard></app-dashboard>
Dashboard component
<app-meseros>
</app-meseros>
<app-ultimospedidos></app-ultimospedidos>
<app-modal></app-modal>
I want to call modal from navbar.component, my modal is on dashboard on component modal.component
This is what i have tried
<!--navbar.component.html -->
<a class="nav-link btn btn-primary" (click)="openModal()">Crear pedido</a>
<!--navbar.component.ts -->
import { Component, OnInit } from '#angular/core';
import { BootstrapService } from '../../services/bootstrap.service';
#Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {
constructor(public bootstrapService: BootstrapService) {}
ngOnInit() {}
openModal() {
this.bootstrapService.toggle();
}
}
I created a service so i can communicate between my navbar.component and modal.component, this is my service
import { Injectable } from '#angular/core';
#Injectable({
providedIn: 'root'
})
export class BootstrapService {
isOpen: any = false;
constructor() {}
toggle() {
console.log(!this.isOpen);
return (this.isOpen = !this.isOpen);
}
}
Then in modal.component.ts i want to subscribe to these changes so i can launch modal on boolean value change.
import { Component, OnInit } from '#angular/core';
import { BootstrapService } from '../../services/bootstrap.service';
import { NgbModal, ModalDismissReasons } from '#ng-bootstrap/ng-bootstrap';
#Component({
selector: 'app-modal',
templateUrl: './modal.component.html',
styleUrls: ['./modal.component.css']
})
export class ModalComponent implements OnInit {
isOpen;
closeResult: string;
modalname: string;
constructor(
public modalService: NgbModal,
public bootstrapService: BootstrapService
) {}
open(content) {
// console.log(this.bootstrapService.popup);
this.modalService
.open(content, { ariaLabelledBy: 'modal-basic-title' })
.result.then(
result => {
this.closeResult = `Closed with: ${result}`;
},
reason => {
this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
}
);
}
private getDismissReason(reason: any): string {
if (reason === ModalDismissReasons.ESC) {
return 'by pressing ESC';
} else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
return 'by clicking on a backdrop';
} else {
return `with: ${reason}`;
}
}
ngOnInit() {
this.bootstrapService.toggle().subscribe(isOpen => {
this.isOpen = isOpen;
console.log(isOpen);
});
}
}
Im not even able to subscribe to the change from bootstrapService, i get following error,
RROR in src/app/components/modal/modal.component.ts(41,36): error TS2339: Property 'subscribe' does not exist on type 'boolean'.
if i try to subscribe to value on service like this
this.bootstrapService.isOpen.subscribe(isOpen => {
this.isOpen = isOpen;
console.log(isOpen);
});
i get error on console from browser which says
DashboardComponent.html:1 ERROR TypeError: this.bootstrapService.isOpen.subscribe is not a function
i hope someone can shade some light on this approach, and if this is the best approach to take on this kind of implementations, thanks in advance!
Solved it, i was calling wrong EventEmitter from wrong library, this is updated working code
first i call service from component where i want to call my modal
import { Component, OnInit } from '#angular/core';
import { BootstrapService } from '../../services/bootstrap.service';
#Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {
constructor(public bootstrapService: BootstrapService) {}
ngOnInit() {}
openModal() {
this.bootstrapService.toggle();
}
}
Then i emit my changes so i can subscribe from modal component
import { Injectable, Output, EventEmitter } from '#angular/core';
#Injectable({
providedIn: 'root'
})
export class BootstrapService {
isOpen: any = 'isOpen';
#Output() change: any = new EventEmitter();
constructor() {}
toggle() {
this.change.emit(this.isOpen);
console.log(this.isOpen);
}
}
i reference my template with `#ViewChild('crearpedido') modalInstance;`
and finally subscribe to changes, call modal on subscribe changes.
import { Component, OnInit, ViewChild } from '#angular/core';
import { BootstrapService } from '../../services/bootstrap.service';
import { NgbModal } from '#ng-bootstrap/ng-bootstrap';
#Component({
selector: 'app-modal',
templateUrl: './modal.component.html',
styleUrls: ['./modal.component.css']
})
export class ModalComponent implements OnInit {
isOpen;
closeResult: string;
#ViewChild('crearpedido') modalInstance;
constructor(
public modalService: NgbModal,
public bootstrapService: BootstrapService
) {}
ngOnInit() {
this.bootstrapService.change.subscribe(isOpen => {
this.isOpen = isOpen;
console.log(this.isOpen);
this.modalService.open(this.modalInstance);
});
}
}
Here is working repo!!
https://github.com/soyisraelortiz/componentscommunication

Javascript Angular 4 eventEmitter with ngClass

I am using Angular 4 and eventEmitter to change a class name.
The class css is:
.paintRed {
background-color: red;
}
Now for the Angular part:
I have a button component:
button.compoment.ts:
import { Component, OnInit, Output, EventEmitter } from '#angular/core';
#Component({
selector: 'app-button',
templateUrl: './button.component.html',
styleUrls: ['./button.component.scss']
})
export class ButtonComponent implements OnInit {
#Output() outputEvent: EventEmitter<any> = new EventEmitter();
constructor() { }
ngOnInit() {}
sendOutEvent() {
this.outputEvent.emit('paintRed');
}
}
button.component.html
<p (click)="sendOutEvent()">Click to Emit</p>
Finally on my app.component.ts I have:
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'app';
handleEvent(value) {
console.log(value);
document.getElementById('elementId').classList.add(value);
}
}
and my app.component.html looks like this:
<div id="elementId">
<app-button (outputEvent)="handleEvent($event)"></app-button>
</div>
The above will successfully add the class "paintRed" to elementId but what I want to do is this:
<div ngClass="myClass">
<app-button (outputEvent)="handleEvent($event)"></app-button>
</div>
Basically I want to use ngClass to change the value sent by handleEvent($event) ...
How can I do that?
In your app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'app';
myClass = '';
handleEvent(value) {
console.log(value);
myClass = value;
}
}
And your html:
<div [ngClass]="myClass">
<app-button (outputEvent)="handleEvent($event)"></app-button>
</div>

Categories

Resources