shared information between components through service not working - javascript

Im having some trouble figuring this out, basically I have a headerTitleService which I want to be able to dynamically set the title in my header component but for some reason when I set the title nothing shows up? Im not getting any errors so I can seem to figure out what the problem is..
headerTitle.service.ts
import { Injectable } from '#angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
#Injectable()
export class HeaderTitleService {
title = new BehaviorSubject('');
constructor() { }
setTitle(title: string) {
this.title.next(title);
}
}
header.component.ts
import { Component, OnInit } from '#angular/core';
import { HeaderTitleService } from '../../../services/headerTitle.service'
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss'],
providers: [HeaderTitleService]
})
export class HeaderComponent implements OnInit {
title: string;
constructor(
private headerTitleService: HeaderTitleService
) { }
ngOnInit() {
this.headerTitleService.title.subscribe(updatedTitle => {
this.title = updatedTitle;
});
}
}
header.component.html
<h1>{{title}}</h1>
home.component.ts
import { Component, OnInit } from '#angular/core';
import { HeaderTitleService } from '../../services/headerTitle.service';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss'],
providers: [HeaderTitleService]
})
export class HomeComponent implements OnInit {
constructor(
private headerTitleService: HeaderTitleService
) { }
ngOnInit() {
this.headerTitleService.setTitle('hello');
}
}

The line providers: [HeaderTitleService] in each component means that they will be given one HeaderTitleService each, rather than one between them.
To fix this remove providers: [HeaderTitleService] from your components, and place it in your module definition instead:
#NgModule({
providers: [HeaderTitleService]
})

Move HeaderTitleService in providers of your module. With your implementation you receive new instance of the HeaderTitleService in each component.
Hope this helps.

Related

Input decorator is not working in Angular( Property 'name' has no initializer and is not definitely assigned in the constructor. )

I have added input decorator in child component ts file and I am trying to access it from app component(parent), but I am not getting it.Error : Property 'name' has no initializer and is not definitely assigned in the constructor.
Hellocomponent.ts
import { Component, Input, OnInit } from '#angular/core';
#Component({
selector: 'app-hello',
templateUrl: './hello.component.html',
styleUrls: ['./hello.component.scss']
})
export class HelloComponent implements OnInit {
#Input() name:string;
constructor() { }
ngOnInit(): void {
}
}
appcomponent.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
styles: [`
/* p{color: blue;}*/
`]
})
export class AppComponent {
title = 'Angular';
counter = 0;
}
App component.html
<h1>#Input</h1>
<app-hello [name]="title"></app-hello>

Confusing behavior of a BehaviorSubject in my Angular App

I recently ran into a problem and can't really figure out what's wrong with my code at this point, hopefully someone of you can help me.
All I am trying to do is changing the value of my BehaviorSubject with a function but it isn't working out.
chat.service.ts
import { Injectable } from '#angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
#Injectable()
export class ChatService {
chatId = new BehaviorSubject<number>(0);
constructor() {
this.chatId.next(1);
}
changeChatId(chatId: number) {
console.log(chatId);
this.chatId.next(chatId);
}
}
So the subscribers get the default as well as the changed chatId from the constructor. But as soon as I try to change it with the changeChatId function nothing happens at all. The right id's get passed into the function I already debugged that but the line this.chatId.next(chatId) doesn't seem to do anything.
ADD
These are the other components the service is currently used in.
chat-message-list
import { Component, OnInit, Input} from '#angular/core';
import { ChatService } from "../../../shared/services/chat.service";
#Component({
selector: 'app-chat-message-list',
templateUrl: './chat-message-list.component.html',
styleUrls: ['./chat-message-list.component.css'],
providers: [ChatService]
})
export class ChatMessageListComponent implements OnInit {
chatId: number;
constructor(private chat: ChatService) { }
ngOnInit() {
this.chat.chatId.subscribe(
chatId => this.updateMessageList(chatId)
);
}
}
chat-item
import { Component, OnInit, Input} from '#angular/core';
import { User } from '../../../shared/models/user.model';
import { ChatService } from '../../../shared/services/chat.service';
#Component({
selector: 'app-chat-list-item',
templateUrl: './chat-list-item.component.html',
styleUrls: ['./chat-list-item.component.css'],
providers: [ChatService]
})
export class ChatListItemComponent implements OnInit {
#Input()
user: User;
constructor(private chat: ChatService) { }
ngOnInit() {
}
onChatItemSelected(){
this.chat.changeChatId(this.user.id);
}
}
You need to make your ChatService a singleton (shared) service. Add it to the providers of your ngModule. This allows all the components that use the ChatService to share the same service instance.
#NgModule({
providers: [ChatService]
})
And remove it from your components providers. When you are adding it to your components providers, that component gets its own instance of ChatService which can not be used by other components.

Angular Firebase Database Querying

This is my .ts file
import { Component, OnInit } from '#angular/core';
import { AngularFireDatabase, FirebaseListObservable, FirebaseObjectObservable } from 'angularfire2/database';
#Component({
selector: 'app-candidate-reg-success',
templateUrl: './candidate-reg-success.component.html',
styleUrls: ['./candidate-reg-success.component.css']
})
export class CandidateRegSuccessComponent implements OnInit {
constructor() {
debugger;
const rootRef=firebase.database.ref();
const mail=rootRef.child('candidates_list').orderByChild('email').equalTo('pranavkeke#gmail.com');
console.log(mail);
}
ngOnInit() {
}
}
I am trying to query the user from candidates_list table which has the email address pranavkeke#gmail.com.
But I am unable to console it. It shows a error like
Property 'ref' does not exist on type 'typeof database'.
Any solution to query angular firebase database?
you need to inject the AngularFirebaseData in constructor and change the code and try again
import { Component, OnInit } from '#angular/core';
import { AngularFireDatabase, FirebaseListObservable,
FirebaseObjectObservable } from 'angularfire2/database';
#Component({
selector: 'app-candidate-reg-success',
templateUrl: './candidate-reg-success.component.html',
styleUrls: ['./candidate-reg-success.component.css']
})
export class CandidateRegSuccessComponent implements OnInit {
constructor(public db: AngularFireDatabase) {
debugger;
db.list('/candidates_list', ref => ref.orderByChild('email').equalTo('pranavkeke#gmail.com'));
}
ngOnInit() {
}}

How to inject document.body in Angular 2

I want to add some text in showlist.component.html. My code is given below, I am not aware how to use document.body in Angular 2.
import { Component, OnInit } from '#angular/core';
import { DOCUMENT } from '#angular/platform-browser';
#Component({
selector: 'app-showlist',
templateUrl: './showlist.component.html',
styleUrls: ['./showlist.component.css']
})
export class ShowlistComponent implements OnInit {
public myname = "saurabh";
constructor() { }
ngOnInit() {
//this.myname.appendTo(document.body);
document.body(this.myname);
//document.write(this.myname);
}
}
you do the following to access the document.body
import { Component, OnInit, Inject } from '#angular/core';
import { DOCUMENT } from '#angular/common';
#Component({
selector: 'app-showlist',
templateUrl: './showlist.component.html',
styleUrls: ['./showlist.component.css']
})
export class ShowlistComponent implements OnInit {
public myname = "saurabh";
constructor(#Inject(DOCUMENT) private document: Document) {}
ngOnInit() {
this.document.body.innerHTML = this.myname;
}
}

implement angular2-virtual-scroll with observable in angular4

I am trying to implement angular2-virtual-scroll in an angular4 project. Firstly, can anyone confirm if I would have a problem implementing it in NG4. I don't think I should and I haven't seen any notices to the contrary. Secondly I am using an observable instead of a promise shown in the NPM angular2-virtual-scroll docs. However, when I applied the virtual-scroll tag there is no change in my output...no scroll bar ..the data from the observable is displayed but no scrolling. The following are the relevant code segments:
Home.component.html
<h1 style="color: #76323f">
{{title}}
</h1>
<h4>
{{description}}
</h4>
<h2>Coming Soon....</h2>
<app-events-list [upcomingEvents]="upcomingEvents"></app-events-list>
home.component.ts
import {Component, OnInit,OnDestroy } from '#angular/core';
import {UpcomingEvent} from './../../interface/upcomingevent';
import {EventService} from './../../services/event.service';
import {Subscription} from 'rxjs/Subscription';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit, OnDestroy {
upcomingEvents: Array<UpcomingEvent>;
title = 'Welcome....';
description='Events promotions....';
eventServiceSub: Subscription;
constructor(private eventService: EventService){
this.upcomingEvents = [];
}
ngOnInit() {
this.eventServiceSub=this.eventService.getEvents().subscribe(upcomingEvents=>{this.upcomingEvents=upcomingEvents.slice(0,25);
});
}
ngOnDestroy(){
if (this.eventServiceSub){
this.eventServiceSub.unsubscribe();
}
}
}
event-list-component.html
<virtual-scroll [items]="items" (update)="upcomingEvents = $event"
(change)="onlistChange($event)">
<app-upcomingevent *ngFor="let upcomingEvent of upcomingEvents"[upcomingEvent]="upcomingEvent" [eventItemCss]="'event-item'"></app-upcomingevent>
<div *ngIf="loading" class="loader">Loading.....</div>
</virtual-scroll>
event-list-component.ts
import { Component, Input, OnDestroy, OnInit } from '#angular/core';
import { UpcomingEvent } from './../../interface/upcomingevent';
import { trigger,state,style,transition,animate,keyframes } from '#angular/animations';
import { ChangeEvent } from 'angular2-virtual-scroll';
import {EventService} from './../../services/event.service';
import {Subscription} from 'rxjs/Subscription';
#Component({
selector: 'app-events-list',
templateUrl: './events-list.component.html',
styleUrls: ['./events-list.component.css'],
animations: []
})
export class EventsListComponent implements OnInit, OnDestroy {
#Input()
upcomingEvents: Array<UpcomingEvent>;
items=this.upcomingEvents;
protected buffer: Array<UpcomingEvent> =[];
protected loading: boolean;
eventServiceSub: Subscription;
constructor(private eventService: EventService) {
this.upcomingEvents=[];
}
ngOnInit() {
}
ngOnDestroy(){
if (this.eventServiceSub){
this.eventServiceSub.unsubscribe();
}
}
protected onlistChange(event: ChangeEvent){
if (event.end !==this.buffer.length) return;
this.loading=true;
this.eventServiceSub=this.eventService.getEvents().subscribe(upcomingEvents=>{
this.buffer=upcomingEvents.slice(this.buffer.length,25);
this.loading=false;
}, ()=> this.loading=false);
}
}
eventService.ts
import { Injectable } from '#angular/core';
import {UpcomingEvent} from './../interface/upcomingevent'
import {Http} from '#angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
#Injectable()
export class EventService {
constructor(private http: Http) { }
getEvents(): Observable<UpcomingEvent[]>
{
return this.http
.get(`https://jsonplaceholder.typicode.com/posts`)
.map(response => response.json() as UpcomingEvent[]);
}
}
upcomingEvents.html
<md-card [ngClass]="'event-item'">
<h4 [ngClass]="'event-title'" [ngStyle]="{'color':'purple'}"> {{upcomingEvent.title}}</h4>
<md-card-actions>
<button md-button>LIKE</button>
<button md-button>SHARE</button>
</md-card-actions>
</md-card>
upcomingEvents.component.ts
import { Component, Input,OnInit } from '#angular/core';
import { UpcomingEvent } from './../../interface/upcomingevent';
#Component({
selector: 'app-upcomingevent',
templateUrl: './upcomingevent.component.html',
styleUrls: ['./upcomingevent.component.css']
})
export class UpcomingeventComponent implements OnInit {
#Input()
upcomingEvent: UpcomingEvent;
#Input()
eventItemCss: string;
constructor() { }
ngOnInit() {
if (!this.upcomingEvent) {
this.upcomingEvent=<UpcomingEvent> {};
}
}
}
The way it suppose to work is that the HomeComponent request data from the eventService via an observable..the data is then passed to the eventList component where it is iterated on and pass to the upcomingEvents component to present via HTML. 25 events are requested at first and if the user scroll to the end another 25 is requested from the eventService...this time by the upcomingEvents component. I am not sure this is the most efficient way to do it but in either case it doesn't work. The virtual-scroll seems to have no effect on the output....I would really appreciate someone showing me what I am doing wrong....Thanks
I think I see a problem in your code. When using virtual-scroll you need to keep two arrays - one for all loaded data, and one for currently rendered items. Looks like you kinda mixed them up.
Let's call all-items-array as items and render-array - upcomingEvents
First chunk of items will be passed from the parent component, hence:
Home.component.html
...
<app-events-list [items]="upcomingEvents"></app-events-list>
event-list-component.html looks good
event-list-component.ts
import { Component, Input, OnDestroy, OnInit } from '#angular/core';
import { UpcomingEvent } from './../../interface/upcomingevent';
import { trigger,state,style,transition,animate,keyframes } from '#angular/animations';
import { ChangeEvent } from 'angular2-virtual-scroll';
import {EventService} from './../../services/event.service';
import {Subscription} from 'rxjs/Subscription';
#Component({
selector: 'app-events-list',
templateUrl: './events-list.component.html',
styleUrls: ['./events-list.component.css'],
animations: []
})
export class EventsListComponent implements OnInit, OnDestroy {
#Input()
items: Array<UpcomingEvent> = [];
upcomingEvents: Array<UpcomingEvent>;
protected loading: boolean;
eventServiceSub: Subscription;
constructor(private eventService: EventService) {
this.upcomingEvents=[];
}
ngOnInit() {
}
ngOnDestroy(){
if (this.eventServiceSub){
this.eventServiceSub.unsubscribe();
}
}
protected onlistChange(event: ChangeEvent){
if (event.end !==this.items.length) return;
this.loading=true;
this.eventServiceSub=this.eventService.getEvents().subscribe(upcomingEvents=>{
this.items=upcomingEvents.slice(0, this.items.length + 25);
this.loading=false;
}, ()=> this.loading=false);
}
}
warning! code not tested, I simply edited your code.

Categories