I have a variable in my app.component.ts file that is passed in from a controller via my services.ts file.
As far as I can see, the Object property passed to the Component via the Subject is working, because I can console.log(this.selectedContact.name)
and It will log to the console perfectly, which would mean that it is correctly being stored into the variable selectedContact: any;
. But I cannot seem to bind this to my HTML and I am curious as to what I may be missing.
Here is my app.component.ts file for the view I'm attempting to bind to:
import { Component, OnInit } from '@angular/core';
import { ContactsListComponent } from '../contacts-list/contacts-list.component';
import { ApiService } from '../api.service';
@Component({
selector: 'app-contact-details',
templateUrl: './contact-details.component.html',
styleUrls: ['./contact-details.component.scss']
})
export class ContactDetailsComponent implements OnInit {
selectedContact: any;
constructor(private _apiService: ApiService) { }
ngOnInit() { this.showContact()}
showContact() {
this._apiService.newContactSubject.subscribe(
contact => {
this.selectedContact = contact;
console.log(this.selectedContact.name);
});
}
}
Here is my HTML file (The view I am attempting to bind to.:
<div id= 'contact-card' >
<header>
<button routerLink='/home'>< Contacts</button>
</header>
<section id= card-container>
<img id ="largeContactPhoto" onerror="onerror=null;src='../assets/User Large/User — Large.png';"
src={{selectedContact.largeImageURL}} />
<h1> {{selectedContact.name}} </h1>
<h2> {{selectedContact.companyName}} </h2>
<ul>
<hr>
<li class="contact-data">
<h3> Phone: </h3>
{{selectedContact.phone.home}}
<hr>
</li>
<li class="contact-data">
<h3> Phone: </h3>
{{selectedContact.phone.mobile}}
<hr>
</li>
<li class="contact-data">
<h3> Phone: </h3>
{{selectedContact.phone.work}}
<hr>
</li>
<li class="contact-data">
<h3> Address: </h3>
{{selectedContact.address.street}}<br>
{{selectedContact.address.city}},{{selectedContact.address.state}} {{selectedContact.address.zipcode}}
<hr>
</li>
<li class="contact-data">
<h3> Birthdate: </h3>
{{selectedContact.birthdate}}
<hr>
</li>
<li class="contact-data">
<h3> Email: </h3>
{{selectedContact.email}}
<hr>
</li>
</ul>
</section>
</div>
app.service.ts (where the click event data is being passed to app.component.ts:
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/map';
@Injectable()
export class ApiService {
//API URL
private url: string = 'assets/api/contacts.json';
public newContactSubject = new Subject<any>();
//Initialize HttpClient for request
constructor(private _http: Http) { }
//Pull JSON data from REST API
getContacts(): Observable<any> {
return this._http.get(this.url)
.map((response: Response) => response.json());
}
openSelectedContact(data) {
this.newContactSubject.next(data);
}
}
Sibling Component THIS IS WHERE THE CLICK EVENT HAPPENS* :
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { ApiService } from '../api.service';
@Component({
selector: 'app-contacts-list',
templateUrl: './contacts-list.component.html',
styleUrls: ['./contacts-list.component.scss']
})
export class ContactsListComponent implements OnInit {
title : string = 'Contacts';
sortedFavorites: any[] = [];
sortedContacts: any[] = [];
errorMessage: string;
constructor (private _apiService: ApiService, private router: Router) {}
ngOnInit(){ this.getContacts()}
getContacts() {
this._apiService.getContacts()
.subscribe(
(contacts) => {
//Sort JSON Object Alphabetically
contacts.sort((a , b) => {
if (a.name > b.name) {return 1};
if (a.name < b.name) {return -1};
return 0;
})
//Build new Sorted Arrays
contacts.forEach( (item) => {
if (item.isFavorite) {
this.sortedFavorites.push(item);
} else {
this.sortedContacts.push(item);
}
});
});
}
openFavorite($event, i) { <--Click event coming in from HTML template
let selectedFavorite = this.sortedFavorites[i];
this._apiService.openSelectedContact(selectedFavorite); <--Routing this data to services.ts file
this.router.navigate(['/details']); <--Navigate to detailed view to see selected contact.
};
}
This binding will work with any other test variables that i put into my app.component.ts file and they get bounded to the page. I feel like this is the right syntax for it to be properly binding the object.properties, but it doesn't seem to be working.
What might I be missing on this? Thanks a lot in advance!!
EDIT One: I feel like I should also add that this exact same code was working before when I had my component routed to this component. It was only when I moved my files to a new component and created a different new that this started happening. Maybe it is isn’t imported correctly somewhere?
EDIT TWO: I have refactored the code in the original post and corrected my TypeScript declarations and removed this
from my html template. I have placed my console.log(this.selectedContact.name)
function inside my showContact()
method and it does log the correct name once the name in the contacts list is clicked along side this error: ERROR TypeError: Cannot read property 'largeImageURL' of undefined
. So it is logging this.selectedContact.name
correctly and that variable isn't defined anywhere else in my application. I have added my app.service.ts file as well as my sibling component.ts file just to put this in context where the click event happens. I want the click event data to go from Sibling component --> Api Service.ts file --> Sibling component on a click event. This is very confusing to me why this isn't happening.
EDIT THREE One other issue that I have noticed is that whenever I attempt to use the safe navigation operator to resolve this, my highlighting changes in my html template, making me think that it is breaking it.
versus this:
Notice the change in the </h1
> highlighting? This has subsiquently made every open and closing tag show up in grey instead of the red now. I have never attempted to use the safe navigation operator, so I am unsure as to whether this is normal. I have tried it with different spacing around the {{
and }}
and still no luck.