I have a component alphabatesComponent. It has a method postLetters(). I want to call wordsComponent listOfAlphabates() method whenever I call postLetters() in alphabatesComponent.
// Service
private _listners = new Subject<any>();
constructor(private httpClient: HttpClient) { }
listen(): Observable<any> {
debugger;
return this._listners.asObservable();
}
filter(filterBy: string) {
debugger;
this._listners.next(filterBy);
}
// alphabates component
export class alphabatesComponent {
postLetters(): void {
this.asynService.filter('Register click');
}
}
// this is my words component
constructor() {
this.asyncService.listen().subscribe((m: any) => {
this.listOfAlphabates();
}
}
listOfAlphabates() {}
}
for state managment use rxJs:
in alphabates component:
filter () {
this.asynService.onFilterChanged.next('Registerclick');
}
in asynService:
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
public onFilterChanged: BehaviorSubject<any> = new
BehaviorSubject('');
in word component:
import {Subscription} from 'rxjs/Subscription';
private onFilterChanged: Subscription;
constructor(public asynService: AsynService,) {
this.onFilterChanged = this.asynService.onFilterChanged
.subscribe((filterBy) => {
this.listOfAlphabates(filterBy);
});
}
public ngOnDestroy(): void {
// note: Do not forget to unsubscribe!
this.onFilterChanged.unsubscribe();
}
listOfAlphabates(text) {
console.log(text);
}
Related
Actually I'm confronted to 2 issues with Angular.
My first consists on adding articles in a basket in different component. I send an object to a service and a second component retrieve it ...
My second issue is when i want to have a second product, i wish to display both of them and not overwritting it. I have been reading this : http://jasonwatmore.com/post/2018/06/25/angular-6-communicating-between-components-with-observable-subject in order to give me some skills ...
In my view i added a button :
<button class="btn btn-danger" (click)="onAddProduct()">Ajouter</button>
Here is my article component :
export class ProductComponent implements OnInit {
#Input() private product: Product;
private basketData: BasketdataService;
constructor(private basketData: BasketdataService) { }
ngOnInit() {
}
onAddProduct() {
console.log(this.product);
this.basketData.onAddBasket(this.product);
}
}
My service here retrieve the datas and share them with the basket component
export class BasketdataService {
private subject = new Subject<any>();
onAddBasket(product: Product) {
this.subject.next(product);
}
onGetBasket(): Observable<Product> {
return this.subject.asObservable();
}
removeArticleBasket() {
this.subject.next();
}
Here is my basketComponent
export class BasketmenuComponent implements OnInit, OnDestroy {
product : Product;
subscription : Subscription;
constructor(private basketdataService: BasketdataService) {
this.subscription = this.basketdataService.onGetBasket().subscribe(message => { this.product = product; });
}
ngOnInit() {
}
ngOnDestroy() {
// unsubscribe to ensure no memory leaks
this.subscription.unsubscribe();
}
}
I receive this error :
ERROR ReferenceError: product is not defined at SafeSubscriber._next
In basketComponent you've an error, try this:
export class BasketmenuComponent implements OnInit, OnDestroy {
product : Product;
subscription : Subscription;
constructor(private basketdataService: BasketdataService) {
this.subscription = this.basketdataService.onGetBasket().subscribe(product=> { this.product = product; });
}
ngOnInit() {
}
ngOnDestroy() {
// unsubscribe to ensure no memory leaks
this.subscription.unsubscribe();
}
}
It's not "message", but "product" in this.subscription
I have written a directive in angular4, which works on input fields.
When I apply that on SPAN tag, it is not working.
Can we apply the directives on SPAN TAG, or is there any work around.
<span dirTemp>45789</span>
dirTemp actually corrects the value to 45,789
import { Directive, HostListener, ElementRef, OnInit, AfterViewInit, AfterViewChecked, AfterContentChecked } from '#angular/core';
#Directive({
// tslint:disable-next-line:directive-selector
selector: '[dirTemp ]',
})
export class FormatterDirective implements AfterViewChecked {
private el: HTMLInputElement;
constructor(
private elementRef: ElementRef,
private cPipe: MyPipe
) {
this.el = this.elementRef.nativeElement;
}
// ngOnInit() {
// this.el.value = this.cPipe.transform(this.el.value);
// }
ngAfterViewChecked(): void {
this.el.value = this.cPipe.parse(this.el.value);
this.el.value = this.cPipe.transform(this.el.value);
}
#HostListener('focus', ['$event.target.value'])
onFocus(value) {
console.log('in formatter directive:', value);
this.el.value = this.cPipe.parse(value);
}
#HostListener('focusout', ['$event.target.value'])
onFocusout(value) {
this.el.value = this.cPipe.transform(value);
}
}
Workaround: span doesn't have value but has innerText or innerHTML. So, On ngOnInit you can do:
ngOnInit() {
if(this.el.tagName.toUpperCase() !== 'INPUT') {
// Apply your tranform here:
var originalValue = this.el.innerText;
this.el.innerText = this.cPipe.transform(originalValue);
}
}
I'm creating a website at angular 6
In my project user can be 3 types: admin, company, customer.
In my header component i have 3 menus under ngIf which need to be shown according to your login details.
Somehow I cannot communicate between those two components and launch header's function in order to change the view. didn't work with the service I have either.
I'll post some of the code here and hope someone help me out :)
// header component:
export class HeaderComponent implements OnInit {
guestMenu: boolean = true;
adminMenu: boolean = false;
companyMenu: boolean = false;
customerMenu: boolean = false;
//change site view to admin
admin() {
this.adminMenu = true;
this.companyMenu = false;
this.customerMenu = false;
this.guestMenu = false;
}
//change site view to company
company() {
this.adminMenu = false;
this.companyMenu = true;
this.customerMenu = false;
this.guestMenu = false;
}
//change site view to customer
customer() {
this.adminMenu = false;
this.companyMenu = false;
this.customerMenu = true;
this.guestMenu = false;
}
constructor() {}
ngOnInit() {
}
}
// login component:
export class LoginComponent implements OnInit {
constructor(private dataService: DataService) {}
loginUser(username, password, type) {
console.log(username.value, password.value, type.value);
switch (type.value) {
case "ADMIN":
{
this.dataService.getLoginResponse(username.value, password.value,
type.value).subscribe(res => {})
}
break;
case "COMPANY":
{
this.dataService.getLoginResponse(username.value, password.value,
type.value).subscribe(res => {})
}
break;
case "CUSTOMER":
{
this.dataService.getLoginResponse(username.value, password.value,
type.value).subscribe(res => {})
}
break;
}
}
ngOnInit() {}
}
I would create an authentication service to act as a middle layer between the two components and perform communication using an rxjs/Subject.
import { Subject, Observable } from 'rxjs';
export class AuthenticationServce {
userType$: Observable<string>;
private userType: Subject<string>;
constructor() {
this.userType = new Subject<string>();
this.userType$ = this.userType.asObservable();
}
public updateUserType(userType: string): void {
this.userType.next(userType);
}
}
In your login.component:
constructor(
private dataService: DataService,
private authenticationService: AuthenticationService,
) { }
loginUser(username, password, type): void {
...
this.authenticationSubject.updateUserType(type.value);
...
}
And, lastly, in your header.component:
constructor(private authenticationService: AuthenticationService) {
this.authenticationService.userType$.subscribe(userType => {
switch (userType) {
case "ADMIN":
this.admin();
break;
// Other case statements
}
});
}
In my angular2 project I have a DataService class.
I want to have a DataService.await.get() and DataService.await.put() but I'm having trouble getting the correct 'this' inside those methods.
This is what I have now:
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { ReplaySubject } from 'rxjs/ReplaySubject';
#Injectable()
export class DataService {
public await = {
get(req): Observable<any> {
return this.getIt(req); // I need 'this' to be the DataService
},
put(req, data): boolean {
return this.putIt(req, data); // I need 'this' to be the DataService
}
constructor() {}
private getIt(req: string): Observable<any> {
return new ReplaySubject(1).AsObservable();
}
private putIt(req: string, data: any): boolean {
return true;
}
}
I have seen some examples using arrow functions for functions within functions, but not for functions within an object...
How do I get 'this' to be a reference to the class?
You could change your property to a function that returns an object and use a little trick like this:
public await() {
let that = this;
return {
get(req): Observable<any> {
return that.getIt(req);
},
put(req, data): boolean {
return that.putIt(req, data);
}
};
}
or you could initialize the await property in the constructor:
await: { get(req): Observable<any>, put(req, data): boolean };
constructor() {
let that = this;
this.await = {
get(req): Observable<any> {
return that.getIt(req);
},
put(req, data): boolean {
return that.putIt(req, data);
}
};
}
I managed to solve it using arrow after all, appearantly all this time I was trying with get= instead of get:
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { ReplaySubject } from 'rxjs/ReplaySubject';
#Injectable()
export class DataService {
public await = {
get: (req): Observable<any> => {
return this.getIt(req); // I need 'this' to be the DataService
},
put: (req, data): boolean => {
return this.putIt(req, data); // I need 'this' to be the DataService
}
constructor() {}
private getIt(req: string): Observable<any> {
return new ReplaySubject(1).AsObservable();
}
private putIt(req: string, data: any): boolean {
return true;
}
}
I'm fairly new to Angular 2 and I have a little problem.
I have a header component, in the header I want to use an ngIf, cause in the login-screen I will hide the header(navbar).
Furthermore, I want to hide some more things from the header, depending on the users-profile.
To store, if a user is logged in, I have a global service named variables.ts, which looks like this:
import { Injectable } from '#angular/core';
#Injectable()
export class Variables {
private url = "...";
private username;
private password;
private isLoggedIn = false;
constructor() {}
setUrl(val) {
this.url = val;
}
getUrl() {
return this.url;
}
setUsername(val) {
this.username = val;
}
getUsername() {
return this.username;
}
setPassword(val) {
this.password = val;
}
getPassword() {
return this.password;
}
setIsLoggedIn(val) {
this.isLoggedIn = val;
}
getIsLoggedIn() {
return this.isLoggedIn;
}
}
My header-component looks like this:
import { Component } from '#angular/core';
import { Router } from '#angular/router';
import { Variables } from '../../services/variables';
#Component({
selector: 'app-header',
moduleId: module.id,
templateUrl: 'header.component.html'
})
export class HeaderComponent {
constructor(private variables: Variables) {}
isLoggedIn() {
return this.variables.getIsLoggedIn();
}
console.log(loggedIn);
}
And last but not least, in the header.component.html I did this:
<nav class="navbar navbar-default navbar-static-top" *ngIf="isLoggedIn()">
My problem now is, that the header-component do not automatically update the var loggedIn, so the header is hidden if I'm logged in.
How can i make it functional?
I updated my original post, so that it is functional now ;)
Thanks for your help!
Solution: DonĀ“t bind it directly to a variable, but to a function and in the "ngIf" just ask the function ;)