Angular 5 input output - input

In my application there is a toolbar in the a navigation component. This navigation component is part of the app.component along with the place for other components to show. I have a login page from where I want to transfer a variable to the app.component and then on the basis of the variable the toolbar should be changed. From login component I am transferring the variable through #output and eventemitter but in app.component I am not receiving it. The code is as follows.
app.component.ts
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
myrole = 'NoUser';
ngOnInit() {
console.log(this.myrole);
}
}
login.component.ts
import { Component, OnInit, Output, EventEmitter } from '#angular/core';
import { Router, ActivatedRoute } from '#angular/router';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
Name: string;
Pass: string;
#Output() myrole = new EventEmitter();
constructor(private rout: Router) { }
ngOnInit() {
}
OnName(event: any)
{
this.Name = event.target.value;
if (this.Name === 'admin' || this.Name === 'Admin') {
this.myrole.emit('admin');
} else if (this.Name === 'user' || this.Name === 'User') {
this.myrole.emit('user');
} else {
this.myrole.emit('NoUser');
}
console.log(this.myrole);
}
onPass(event: any)
{
this.Pass = event.target.value;
}
Submit() {
this.rout.navigate(['*']);
}
}
navi.component.ts
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'app-navi',
templateUrl: './navi.component.html',
styleUrls: ['./navi.component.css']
})
export class NaviComponent implements OnInit {
#Input() myrole: string;
ngOnInit(): void {
console.log(this.myrole);
}
}
app.component.html
<app-navi [myrole]='myrole'></app-navi>
<br>
<router-outlet></router-outlet>

Related

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked in HTTP loading interceptor

Goal:
Im trying to show a loading icon on every ajax call.To this end, I added an HTTP interceptor which sets a variable to true when one or more requests are ongoing and to false when all have completed. The UI tests for this value and shows a loader or not, depending.
Problem:
On every ajax call, an error is thrown:
ExpressionChangedAfterItHasBeenCheckedError:
Expression has changed after it was checked.
Previous value: 'ngIf: [object Object]'. Current value: 'ngIf: true'.
Simplified Stakckblitz with reproducible error:
https://stackblitz.com/edit/angular-h4rpfb
Code:
appcomponent.html:
<p *ngIf="loaderService.isLoading | async">
Loading!
</p>
<p *ngIf="!(loaderService.isLoading | async)">
Not Loading!
</p>
<button (click)="loadSomething()">Load Something</button>
{{matches|async}}
appcomponent.ts:
import { Component } from "#angular/core";
import { HttpClient } from "#angular/common/http";
import { LoaderService } from "./core";
import { Observable } from "rxjs";
#Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
matches: Observable<any>;
constructor(public loaderService: LoaderService, private http: HttpClient) {}
loadSomething() {
this.matches = this.http.get("https://jsonplaceholder.typicode.com/posts");
}
}
loader.interceptor.ts:
import { Injectable } from '#angular/core';
import {
HttpErrorResponse,
HttpResponse,
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import { LoaderService } from './loader.service';
#Injectable()
export class LoaderInterceptor implements HttpInterceptor {
private requests: HttpRequest<any>[] = [];
constructor(private loaderService: LoaderService) { }
removeRequest(req: HttpRequest<any>) {
const i = this.requests.indexOf(req);
if (i >= 0) {
this.requests.splice(i, 1);
}
console.log(i, this.requests.length);
this.loaderService.isLoading.next(this.requests.length > 0);
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
this.requests.push(req);
this.loaderService.isLoading.next(true);
return Observable.create(observer => {
const subscription = next.handle(req)
.subscribe(
event => {
if (event instanceof HttpResponse) {
this.removeRequest(req);
observer.next(event);
}
},
err => { this.removeRequest(req); observer.error(err); },
() => { this.removeRequest(req); observer.complete(); });
// teardown logic in case of cancelled requests
return () => {
this.removeRequest(req);
subscription.unsubscribe();
};
});
}
}
loader.service.ts:
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { ReplaySubject } from 'rxjs/ReplaySubject';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
#Injectable()
export class LoaderService {
public isLoading = new BehaviorSubject(false);
constructor() {}
}
Ok I got it to work by adding this to the component with the loader:
changeDetection: ChangeDetectionStrategy.OnPush
So the appcomponent.html now looks like this:
import { Component,ChangeDetectionStrategy } from "#angular/core";
import { HttpClient } from "#angular/common/http";
import { LoaderService } from "./core";
import { Observable } from "rxjs";
#Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
matches: Observable<any>;
constructor(public loaderService: LoaderService, private http: HttpClient) {}
loadSomething() {
this.matches = this.http.get("https://jsonplaceholder.typicode.com/posts");
}
}
Example:
https://stackblitz.com/edit/angular-n6fzjm

how to declare variable as public const in angular 8

I wanted to declare a constant variable like this public const SHIPMENT_MENU_ITEM='SHIPMENT';and use in my html by referring the const variable. But I am not able to do it. What I am missing here.
import { Component } from '#angular/core';
#Component({
selector: 'app-header-bar',
templateUrl: './header-bar.component.html',
styleUrls: ['./header-bar.component.scss']
})
export class HeaderBarComponent {
activeLink: String = 'SHIPMENT';
constructor() {
}
onSelectNav(option) {
this.activeLink = option;
}
}
import { Component } from '#angular/core';
#Component({
selector: 'app-header-bar',
templateUrl: './header-bar.component.html',
styleUrls: ['./header-bar.component.scss']
})
export class HeaderBarComponent {
public SHIPMENT_MENU_ITEM: String= SHIPMENT';
activeLink: String = 'SHIPMENT';
constructor() {
}
onSelectNav(option) {
this.activeLink = option;
}
}

Unable to get data when making httpClient.get in angular 5

I am trying to do a http.get using httpclient. However, and i am getting
ReferenceError: data is not defined
Inside my component class when subscribing to service method.
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
const httpOptions = {
headers: new HttpHeaders()
.set('Authorization', 'Bearer xxxxx')
.set('Content-Type', 'application/json')
};
#Injectable()
export class SetsService {
constructor(private http: HttpClient) { }
getSet() {
return this.http.get('http://localhost:1234/api/users', httpOptions);
}
}
my component
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute } from '#angular/router';
import { Router } from '#angular/router';
import { SetsService } from '../services/sets.service';
import { Observable } from 'rxjs/Observable';
#Component({
selector: 'app-sets',
templateUrl: './sets.component.html',
styleUrls: ['./sets.component.scss']
})
export class SetsComponent implements OnInit {
id: string = "";
set: any = {};
constructor(private route: ActivatedRoute, private router: Router, private _setsService: SetsService) {
this.route.params.subscribe(res => this.id = res.id);
}
ngOnInit() {
this.getSets();
}
getSets(){
this._setsService.getSet().subscribe(
(data) => { this.set = data },
err => console.error(err),
() => { console.log('done loading set') }
);
}}
When i look at the network the API call is successful and returning data.
Inside the html I am simply trying to print the set object.

Angular 5: ERROR TypeError: Cannot read property 'offset' of undefined

Error:
ERROR TypeError: Cannot read property 'offset' of undefined
I had comic component, was working fine, but I decided to make a child component, and now it's not working.
I have a parent component 'comics', and a child component 'pagination'. The comics are displayed fine, but the pagination is not working.
In the code, the console.log(this.pagination); is returning an array like ('offset': 20, 'count':1)
But pagination.component.html ir returning an error Cannot read property 'offset' of undefined so pagination is empty, has no data. So parent comics.component.ts is not sharing this variable with child.
I tried to declare pagination: Pagination; in pagination.component.ts but pagination is still empty.
So I think I'm declaring something in a wrong mode, or I should declare something I'm not declaring. I searched, and I tried to find what's missing but I did not find anything and it's still not working.
my code:
// file: pagination.ts
export class Pagination {
offset: number;
count: number;
}
// file: /comics/comics.component.ts
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute, Params } from '#angular/router';
import { Comic } from '../comic';
import { Pagination } from '../pagination';
import { ComicService } from '../comic.service';
#Component({
selector: 'app-comics',
templateUrl: './comics.component.html',
styleUrls: ['./comics.component.css']
})
export class ComicsComponent implements OnInit {
comics: Comic;
pagination: Pagination;
constructor(
private route: ActivatedRoute,
private comicService: ComicService
) {}
ngOnInit() {
}
getComics(): void {
const offset = +this.route.snapshot.paramMap.get('offset');
this.comicService.getComics(offset, 20)
.subscribe(
result => {
this.comics = result['data']['results'];
console.log(this.comics);
this.pagination.offset = result['data']['offset'];
this.pagination.count = result['data']['count'];
console.log(this.pagination);
}
);
}
}
// file: /pagination/pagination.component.ts
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute, Params } from '#angular/router';
import { Pagination } from '../pagination';
#Component({
selector: 'app-pagination',
templateUrl: './pagination.component.html',
styleUrls: ['./pagination.component.css']
})
export class PaginationComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
// file: comics/comics.component.html
<div *ngFor="let comic of comics">
<h5>{{comic.title | uppercase}} </h5>
</div>
<app-pagination></app-pagination>
// file: pagination/pagination.component.html
<div>
<h5>{{pagination.offset}}</h5>
<span>{{pagination.count}}</span>
</div>
Versions used:
Angular CLI: 1.7.3
Node: 8.9.4
OS: darwin x64
Angular: 5.2.8
Given that these two components are in a parent-child relationship, your best option is to simply define offset and count as input properties for the child component, and pass them from the parent, like this:
comics.component.ts
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute, Params } from '#angular/router';
import { Comic } from '../comic';
import { Pagination } from '../pagination';
import { ComicService } from '../comic.service';
#Component({
selector: 'app-comics',
templateUrl: './comics.component.html',
styleUrls: ['./comics.component.css']
})
export class ComicsComponent implements OnInit {
comics: Comic;
offset;
count;
constructor(
private route: ActivatedRoute,
private comicService: ComicService
) {}
ngOnInit() {
}
getComics(): void {
const offset = +this.route.snapshot.paramMap.get('offset');
this.comicService.getComics(offset, 20)
.subscribe(
result => {
this.comics = result['data']['results'];
console.log(this.comics);
this.offset = result['data']['offset'];
this.count = result['data']['count'];
}
);
}
}
pagination.component.ts
import { Component, OnInit, Input } from '#angular/core';
import { ActivatedRoute, Params } from '#angular/router';
import { Pagination } from '../pagination';
#Component({
selector: 'app-pagination',
templateUrl: './pagination.component.html',
styleUrls: ['./pagination.component.css']
})
export class PaginationComponent implements OnInit {
#Input() offset;
#Input() count;
constructor() { }
ngOnInit() {
}
}
comics.component.html
<div *ngFor="let comic of comics">
<h5>{{comic.title | uppercase}} </h5>
</div>
<app-pagination [offset]="offset" [count]="count"></app-pagination>
pagination.component.html
<div>
<h5>{{offset}}</h5>
<span>{{count}}</span>
</div>

Creating restricted members area in Angular Fire 2

I am trying to make an application using angularfire 2. Can't find the perfect way to make the members area restricted that means only authenticated members can access that area. Here is my 'login.component.ts' file
import { Component, OnInit, HostBinding } from '#angular/core';
import { AngularFire, AuthProviders, AuthMethods } from 'angularfire2';
import { FormControl, FormGroup, Validators } from '#angular/forms';
import { Router } from '#angular/router';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css'],
})
export class LoginComponent {
state: string = '';
error: any;
login: FormGroup;
constructor(
public af: AngularFire,
private router: Router
) {
//official angfire 2 app example
//this.af.auth.subscribe(auth => console.log(auth));
}
ngOnInit() {
this.login = new FormGroup({
username: new FormControl('', Validators.required),
password: new FormControl('', Validators.required)
});
}
onSubmit() {
//console.log(this.login.value, this.login.valid);
var value = this.login.value;
//console.log(value.username);
//console.log(value.password);
this.af.auth.login({
email: value.username,
password: value.password,
},
{
provider: AuthProviders.Password,
method: AuthMethods.Password,
}).then(
(success) => {
console.log(success);
this.router.navigate(['/members']);
}).catch(
(err) => {
console.log(err);
this.error = err;
})
}
}
and the members.component.ts file
import { Component, OnInit } from '#angular/core';
import { AngularFire, AuthProviders, AuthMethods } from 'angularfire2';
import { Router } from '#angular/router';
#Component({
selector: 'app-other',
templateUrl: './members.component.html',
styleUrls: ['./members.component.css']
})
export class MembersComponent implements OnInit {
//name: "";
//state: string = '';
constructor(
public af: AngularFire,
private router: Router
) {
this.af.auth.subscribe(auth => {
if(auth) {
console.log(auth);
}
});
}
logout() {
this.af.auth.logout();
console.log('logged out');
this.router.navigate(['/login']);
}
ngOnInit() {
}
}
I know my code may be seem like a dumb one but actually I am trying to study over this. But there is not enough documentation to solve my problem I guess. Thanks in advance.
https://coursetro.com/posts/code/32/Create-a-Full-Angular-Authentication-System-with-Firebase
this is a great tutorial that solves your problem