data in router is undefined in angular 7 - angular7-router

I have a route like below:
{ path: 'contact-us', component: ContactUsComponent , data: {isPrivate: false}},
When I try to get the above isPrivate value on ngOnInit() of ContactUsComponent.ts, it gives undefined:
constructor(private route: ActivatedRoute) {}
..
ngOnInit() {
this._private = this.route.snapshot.data['isPrivate'];
}

check this out
constructor(router:Router, route: ActivatedRoute) {
router.events
.filter(e => e instanceof NavigationEnd)
.forEach(e => {
this.title = route.root.firstChild.snapshot.data['PageName'];
});
}

Maybe try something like:-
constructor(private route: ActivatedRoute) {}
OnInit() {
this.route.data.subscribe(private => this._private = private);
}

Try getting the property right in the constructor:
constructor(private route: ActivatedRoute) {
this._private = this.route.snapshot.data['isPrivate'];
}

Related

Print Json Data in HTML with Ionic/Angular

I'm building an app with IONIC Angular, and I'm trying to print the result in HTML.
From console.log it works correctly, but from the view I can't get the data printed
json api
{
"matches1": {
"homeTeam": "Barcellona",
"awayTeam": "Real Madrid",
},
"matches2": {
"homeTeam": "PSG",
"awayTeam": "Lione",
}
}
home.page.ts
export class HomePage {
matches1: any;
homeTeam1: any;
awayTeam1: any;
result1: any;
private apiurl = 'https://myapi.xxx';
constructor(private httpService: HttpClient) {
this.getdata();
}
getdata() {
this.httpService.get(this.apiurl).subscribe(res => {
this.item = res['matches1']['homeTeam'];
console.log(this.item); <-- this work in console log
}, (err: HttpErrorResponse) => {
console.log (err.message);
}
);
}
}
home.page html
<ion-item *ngFor="let item of items">
{{item.homeTeam}}
</ion-item>
thanks!
This should do the work :
export class HomePage {
matches1: any;
homeTeam1: any;
awayTeam1: any;
result1: any;
items: any;
private apiurl = 'https://myapi.xxx';
constructor(private httpService: HttpClient) {
this.getdata();
}
getdata() {
this.httpService.get(this.apiurl).subscribe(res => {
this.items = Object.keys(res).map(function(key, index) {
return res[key];
});
}, (err: HttpErrorResponse) => {
console.log (err.message);
}
);
}
}
I like to use the json pipe (https://angular.io/api/common/JsonPipe), try this:
<pre>{{ items | json }}</pre>
Edit:
In your case, it might be item | json. Also, Hala Madrid !
You need to declare item in your Controller, and you can't use ngFor if your item is not a list. Right now your json is NOT returning an array, so if you can, it would be best to make it into a list of matches.
Your Json would look better if it was something like this:
{
"matches": [
{
"homeTeam": "Barcellona",
"awayTeam": "Real Madrid",
},
{
"homeTeam": "PSG",
"awayTeam": "Lione",
}
]
}
This way you can easily iterate through your list of matches in your controller
export class HomePage {
matches1: any;
homeTeam1: any;
awayTeam1: any;
result1: any;
item: string[]:
private apiurl = 'https://myapi.xxx';
constructor(private httpService: HttpClient) {
this.getdata();
}
getdata() {
this.httpService.get(this.apiurl).subscribe(res => {
res["matches"].forEach(match => this.item.push(match["homeTeam"]));
}, (err: HttpErrorResponse) => {
console.log (err.message);
}
);
}
}

Angular 8: Send Form data as a Service to Another Component

How do I sent all the Formgroup data as a Service in Angular to Another Component? I am looking for alternative to ControlValueAccessor. So anytime someone writes something on a form, the receiver will get the value data.
Trying to edit the code below to work.
Address Sender Form:
export class AddressFormComponent implements OnInit {
editAddressForm: FormGroup;
constructor(private formBuilder: FormBuilder) {
this.editAddressForm = this.formBuilder.group({
'streetName' : [null, Validators.required, Validators.maxLength(64)],
'city' : [null, Validators.required, Validators.maxLength(32)],
'state' : [null, Validators.required, Validators.maxLength(16)],
'postalCode' : [null, Validators.required, Validators.maxLength(16)]
});
}
ngOnInit() {
}
// What should I write as Event Code??
}
Service:
export class AddressService {
private messageSource = new Subject();
currentMessage = this.messageSource.asObservable();
constructor() { }
changeMessage(currentMessage) {
this.messageSource.next(currentMessage);
}
}
Receiver:
export class AddressCombinedReceiverComponent implements OnInit {
message: any;
constructor(private readonly addressService: AddressService) {
this.addressService.currentMessage.subscribe(currentMessage => this.message = currentMessage);
}
ngOnInit() {
}
}
Related question: Angular 2 - formControlName inside component
This doesnt look far away from what you need, in your AddressFormComponent try the following. Ensure to clean up the subscription when needed, added below.
public subs = new Subscription();
public editAddressForm: FormGroup;
constructor(addressService: AddressService){}
public ngOnInit(): void {
this.editAddressForm = this.formBuilder.group({
'streetName' : [null, Validators.required, Validators.maxLength(64)],
'city' : [null, Validators.required, Validators.maxLength(32)],
'state' : [null, Validators.required, Validators.maxLength(16)],
'postalCode' : [null, Validators.required, Validators.maxLength(16)]
});
this.subs.add(this.editAddressForm.valueChanges.subscribe(data =>
{
this.addressService.changeMessage(this.editAddressForm);
}));
}
public ngOnDestroy(): void
{
this.subs.unsubscribe();
}
That should in turn push the data to the subject you have an in turn cause the subscribers of that subject to receive the data. To confirm try the following
export class AddressCombinedReceiverComponent implements OnInit {
public message: any;
constructor(private readonly addressService: AddressService) {}
public ngOnInit() {
this.addressService.currentMessage.subscribe(currentMessage => {
this.message = currentMessage;
console.log(this.message); // should be the form coming through
});
}
}
You don't need to respond to an event. FormGroups already have an observable that streams the changes.
Example
// address-form.component.ts
export class AppComponent implements OnDestroy {
editAddressForm: FormGroup;
ngOnDestroy() {
// cleanup
this.addressService.formValues$ = null;
}
constructor(private addressService: AddressService) {
this.editAddressForm = new FormGroup({
streetName: new FormControl(null, { validators: [Validators.required, Validators.maxLength(64)]}),
city: new FormControl(null, { validators: [Validators.required, Validators.maxLength(32)]}),
state: new FormControl(null, { validators: [Validators.required, Validators.maxLength(16)]}),
postalCode: new FormControl(null, { validators: [Validators.required, Validators.maxLength(16)]}),
});
this.addressService.formValues$ = this.editAddressForm.valueChanges;
}
}
// address.service.ts
export class AddressService {
formValues$: Observable<any>;
constructor() { }
}
In regards to the receiver, if the intention is to show the form changes in the template, then I recommend using the async pipe for that, so that you only subscribe when it's defined, like:
// address-combined-receiver.component.ts
export class SimpleComponent implements OnInit {
addressValues$: Observable<any>;
constructor(private addressService: AddressService) {
this.addressValues$ = this.addressService.formValues$;
}
ngOnInit() {
}
}
<!-- address-combined-receiver.component.html -->
<ng-container *ngIf="addressValues$ | async as addressValues">
<pre>{{ addressValues | json }}</pre>
</ng-container>

Angular HTTP GET

I have a server running on "localhost:3000". It displays data as JSON at e.g. "localhost:300/locations".
My "data.service.ts" includes this code:
path: string = 'http://localhost:3000'
constructor(private http: HttpClient) { }
// Locations
getAllLocations(): Observable<Location[]> {
let location = null;
this.http.get(this.path + '/locations')
.map((res => location = res))
.catch((error: any) => Observable.throw(console.log(error)));
return location;
}
In my result.component.ts I'm running this code:
constuctor(private dataservice: DataService) { }
ngOnInit() {
console.info(this.dataservice.getAllLocations());
}
I'm expecting to get as output all Locations as JSON, instead of this the output is "null".
Does anyone have a suggestion on how to make this work properly?
UPDATE:
Also tried this for the HTTP call:
getAllLocations(): Observable<Location[]> {
this.http.get<Location[]>(this.path + '/locations')
.pipe(
tap(items => console.info('fetched items'))
);
}
The output for this code is unfortunately: "Object { _isScalar: false, source: {...}, operator: {...} }"
Did you know that HttpClient#get returns an Observable? You can just return the get method in your method.
Secondly, you can set an interface to the method so that it'll return the JSON as typed.
Lastly, you can use template literals in your API URL.
/**
* Retrieves a list of locations.
* (TODO: Add better documentation here)
*/
getAllLocations(): Observable<Location[]> {
return this.http.get<Location[]>(`${this.path}/locations`);
}
You can then handle this in the actual component that calls this method:
constuctor(private dataservice: DataService) { }
ngOnInit() {
this.dataservice.getAllLocations().subscribe(result => {
console.log(result);
});
}
You have to return Observable from the service:
path: string = 'http://localhost:3000'
constructor(private http: HttpClient) { }
// Locations
getAllLocations(): Observable<Locations[]> {
return this.http.get(this.path + '/locations').pipe(
map((res => location = res)),
catch((error: any) => Observable.throw(console.log(error))));
}
And subscribe to it in the component.
constructor(private dataservice: DataService) { }
ngOnInit() {
this.dataservice.getAllLocations().subscribe(result => {
console.log(result);
})
}

ngAfterViewInit local variables undefined angular 6

I am getting this.objectsCount is undefined in addcomponent function
what am I doing wrong? if I debug this has only "div,el,sidenav,subscription".
export class SidenavComponent implements OnInit {
subscription: Subscription;
tog: { compact: boolean, tag: string };
objectsCount: { tag: any, ctrl: Object }[];
compact: boolean;
tag: string;
#ViewChild('sidebar') div;
objects: any;
constructor(private sidenav: SidenavService, private el: ElementRef) {
}
ngOnInit() {
this.subscription = this.sidenav.onToggle().subscribe((toggle) => {
this.tog = toggle;
if (toggle.tag) {
let nav = this.el.nativeElement;
//nav.attributes.
}
});
}
addcomponent(elem) {
this.objectsCount.push({ tag: elem.nativeElement("tag").value, ctrl:
elem.nativeElement });
}
ngAfterViewInit() {
this.addcomponent(this.div);
}
}
You never initialize the objectsCount Array, set it in the OnInit function
this.objectsCount = [];

Cannot read property of undefined Angular 4 Typescript

I have been trying to sort this out for a while now and could definitely use some help.
I am trying to display the question I got from the server and stored locally. But When i try to display the question that i got it gives me the following error:
Cannot read property 'question' of undefined
Here's my HTML
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Questionnaire</title>
</head>
<body>
<div class="container" id="Question" align="center">
<h2 [innerHTML] = "q.question"></h2>
</div>
</body>
</html>
Here's typescript that is for sure returning values because i can log them and so I checked:
#Component({
selector: 'app-new-questionnaire',
templateUrl: './new-questionnaire.component.html',
styleUrls: ['./new-questionnaire.component.css'],
providers: [NewServerRequestsService]
})
export class NewQuestionnaireComponent implements OnInit {
q: any;
sub: any;
id: number;
cQuestion: number;
score: number;
qNumber: number;
constructor(private serverService: NewServerRequestsService, private
route: ActivatedRoute, private router: Router){}
static questionTime = performance.now();
onload()
{
console.log(NewQuestionnaireComponent.questionTime);
// this.ButtonClicks();
}
ngOnInit() {
this.sub = this.route.params.subscribe(params => {
// (+) converts string 'id' to a number
// fetch the file and get next Question
this.id = +params['id'];
if (localStorage.getItem('q') !== null) {
var data = JSON.parse(localStorage.getItem('q'))
this.qNumber = parseInt(localStorage.getItem('qNumber'))
this.q = data.results[this.id - 1]
} else {
this.serverService.getQuestion()
var data = JSON.parse(localStorage.getItem('q'))
this.qNumber = parseInt(localStorage.getItem('qNumber'))
this.q = data.results[this.id - 1]
}
});
}
}
}
Here's the service:
#Injectable()
export class NewServerRequestsService {
constructor(private http: Http) { }
getQuestion()
{
return this.http.get("https://opentdb.com/api.php?amount=30")
.map(res => res.json()).subscribe(
data => {
// shuffle questions
for (var i = 0; i < data.results.length - 1; i++) {
var j = i + Math.floor(Math.random() * (data.results.length -
i));
var temp = data.results[j];
data[j] = data.results[i];
data[j].incorrect_answers.push(data[j].correct_answer)
data[i] = temp;
}
localStorage.setItem("q", JSON.stringify(data))
localStorage.setItem("qNumber", JSON.stringify(data.length))
},
err => console.error(err)
)
}
}
Here's where the data gets fetched:
#Component({
selector: 'home',
templateUrl: 'home.component.html',
providers: [NewServerRequestsService]
})
export class HomeComponent implements OnInit, OnDestroy {
constructor(private QuizService: NewServerRequestsService, private route:
ActivatedRoute, private router: Router) {
}
ngOnInit() {
this.QuizService.getQuestion();
}
ngOnDestroy() { }
}
this error occurs because q is undefined when rendering the view , try using safe navigation by using ? :
<h2 [innerHTML] = "q?.question"></h2>
initialize q: any = {} if it's an object, [] if array ;)
tell me now what console.log(q) show
Check q in your ts or on your html <h2 *ngIf="q" ...