I have an angular 2 app, with a service and a component.
The Service:
import { Injectable } from '#angular/core';
import { User } from '../dtos';
import { Http, Response } from '#angular/http';
#Injectable()
export class UserService {
public user: User;
constructor(private http: Http){}
public authenticate(username: string, email:string) {
var __this = this;
this.http.get('https://randomuser.me/api/')
.subscribe((response: Response) => {
__this.user = new User();
var respData = response.json();
var userResult = respData.results[0];
var seed = respData.info.seed;
__this.user.email = userResult.email;
__this.user.firstName = userResult.name.first;
__this.user.lastName = userResult.name.last;
__this.user.profilePicture = userResult.picure;
__this.user.id = seed;
})
}
}
The Component:
import { Component } from '#angular/core';
import { User } from '../../dtos';
import { UserService } from '../../services';
#Component ({
selector: 'navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.css']
})
export class NavbarComponent{
user: User;
constructor(private userService: UserService){}
ngOnInit(){
this.user = this.userService.user;
}
}
and the Component's html template:
<ul class="topnav">
<li><a routerLinkActive="active" routerLink="/home">Home</a></li>
<li><a routerLinkActive="active" routerLink="/about">About</a></li>
<li class="right" >{{user.userName}}</li>
</ul>
When the http.get call in UserService.authenticate returns with a valid user object, I update the local user property with the data. The Navbar Component does not register that the user object has been updated and never puts the data into the template.
Any ideas how to get the updated user data to display in the navbar component?
you may try below,
UserService
export class UserService {
private _user: Subject<User> = new Subject<User>;
public get user() : string
{
return this._user;
}
constructor(private http: Http){}
public authenticate(username: string, email:string) {
var __this = this;
this.http.get('https://randomuser.me/api/')
.subscribe((response: Response) => {
let tempUser = new User();
var respData = response.json();
var userResult = respData.results[0];
var seed = respData.info.seed;
tempUser .email = userResult.email;
tempUser .firstName = userResult.name.first;
tempUser .lastName = userResult.name.last;
tempUser .profilePicture = userResult.picure;
tempUser .id = seed;
this.user.next(tempUser);
})
}
}
Hope this helps!!
Related
hello every one I had a problem, I create my Ticketservice. this file and I try to add it to the home.ts file but it gives me an error
tickerServices.ts
import { Injectable } from '#angular/core';
#Injectable({
providedIn: 'root',
})
export class TicketService{
result:any;
constructor(public http: HttpClient) { }
getTicket(){
var CronJob = require('cron').CronJob;
var id=this.formulaire.id;
new CronJob('* * * * * *', function(){
const http = require('http');
console.log('You will see this message every second');
/* this.url+'/'*/
http.get('http://localhost:8888/'+id+'/notif', (resp) => {
let data = '';
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
data += chunk;
this.resulta=data;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
console.log(data);
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
}, null, true, 'America/Los_Angeles');
}
}
home.ts
import {Component} from "#angular/core";
import {NavController, PopoverController,NavParams} from "ionic-angular";
import { HttpClient } from '#angular/common/http';
import { TicketService } from '../services/ticketservice'
import 'rxjs/add/operator/map';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
public search = {
date: new Date().toISOString()
}
constructor(public nav: NavController,public http: HttpClient,public popoverCtrl: PopoverController ,public tikSer:TicketService) {
}}
when I test it, he gives me undefined ".. /services/ticketservice"
Add it like this
import { TicketService } from '../../services/ticketservice'
Array not passing from service to component:
In the test() function on the service.ts page, google calendar data is successfully being read and pushed to an array called response. All the data logs.
When lesson-summary.component.ts calls on the test() function, the response array data does not show up in the lesson-summary.component.html
Thanks for any help!
google-calendar.service.ts
import { Injectable, Directive } from "#angular/core";
import * as moment from "moment-timezone";
declare var gapi: any;
#Injectable({
providedIn: "root"
})
export class GoogleCalendarService {
private response = [];
constructor() { }
test() {
gapi.load("client", () => {
gapi.client.init({
apiKey: "API string here",
discoveryDocs: ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"]
}).then(() => {
var month = moment().month();
const firstOfMonth = moment().startOf("month").format("YYYY-MM-DD hh:mm");
const lastOfMonth = moment().endOf("month").format("YYYY-MM-DD hh:mm");
var firstOfMonthUTC = moment.tz(firstOfMonth, "America/Toronto").format();
var lastOfMonthUTC = moment.tz(lastOfMonth, "America/Toronto").format();
return gapi.client.calendar.events.list({
calendarId: "calendar id here",
timeMax: lastOfMonthUTC,
timeMin: firstOfMonthUTC,
singleEvents: true
});
})//end of .then
.then((data) => {
this.response.push.apply(this.response, data.result.items);
console.log(data.result.items, "data.result.items");
return this.response;
});//end of .then
});//end of .load
}//end of test
}//end of export
lesson-summary.component.ts
import { Component, OnInit } from "#angular/core";
import { Observable } from "rxjs";
import { GoogleCalendarService } from "../google-calendar.service";
declare var gapi: any;
#Component({
selector: "app-lesson-summary",
templateUrl: "./lesson-summary.component.html",
styleUrls: ["./lesson-summary.component.css"]
})
export class LessonSummaryComponent implements OnInit {
private response;
constructor(
private calendarService: GoogleCalendarService) {
this.response = this.calendarService.test();
}
ngOnInit() {
}
}
lesson-summary.component.html
<ul>
<li *ngFor = "let item of response">
{{ item.summary }}
</li>
</ul>
That's because you're mixing promises and sync functions in an incorrect way, so the test() function will not return anything.
Try adding a promise to your test():
test() {
return new Promise(resolve => { // <-- now test func return promise
gapi.load("client", () => {
gapi.client.init({
apiKey: "API string here",
discoveryDocs: ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"]
}).then(() => {
// code...
}).then((data) => {
// code...
resolve(this.response); // <-- when we have the response, we are resolving the promise
});
});
});
}
And then use this promise in the component:
this.calendarService.test().then(data => this.response = data);
Learn more about promises on MDN
I am learning a tutorial and an assignment on how to bind id's to http request. This is what i am currently trying to do. I want to bind the id captured in my url and when i trigger the function, it submits the id captured from the url to my service. I am have been able to capture the url but the function to send the captured id to the service is where i am having the issues. The id in the function parameter is Unused.
//Food Component
export class FoodComponent implements OnInit {
private food_id;
constructor(private httpService: HttpService, private route: ActivatedRoute) {
}
ngOnInit() {
this.route.params.subscribe(params => {
if (params['id']) {
this.food_id = params['id'];
}
})
}
//food model
foodModel = {
type: "",
location: ""
};
sendFood() {
this.httpService.send(this.food_id)
.subscribe(data => {
console.log(data);
})
}
//service
send(food: any) {
const body = JSON.stringify(food.value);
const headers = new Headers();
return this.http.post('http://localhost:8000/api/luncheons/v1/location/' + food.id + '/type', body, {
headers: headers
})
.map((data: Response) => data.json());
}
Try this,
import { foodModel } from './foodModel';
export class FoodComponent implements OnInit {
private model: foodModel; /// Make a new variable of foodModel.
ngOnInit() {
this.model = new foodModel(); // Initialize the Model
this.route.params.subscribe(params => {
if (params['id']) {
this.model.id = params['id']; ///set the parameter id to model.id
}
})
}
/// Removed the parameter food_id
sendFood() {
this.httpService.send(this.foodModel)
.subscribe(data => {
console.log(data);
})
}
//service
send(food: any) {
const body = JSON.stringify(food);
const headers = new Headers();
return this.http.post('http://localhost:8000/api/luncheons/v1/location/' + food.id + '/type', body, {
headers: headers
})
.map((data: Response) => data.json());
}
}
// Make a class file foodModel.ts and import foodModel in your component.
export class foodModel {
type: any;
location: any;
id: number = 0; /// new variable added
};
I am new to Angular (and Javascript for that matter). I've written an Angular service which returns an array of users. The data is retrieved from an HTTP call which returns the data in JSON format. When logging the JSON data returned from the HTTP call, I can see that this call is successful and the correct data is returned. I have a component which calls the service to get the users and an HTML page which displays the users. I cannot get the data from the service to the component. I suspect I am using the Observable incorrectly. Maybe I'm using subscribe incorrectly as well. If I comment out the getUsers call in the ngInit function and uncomment the getUsersMock call, everything works fine and I see the data displayed in the listbox in the HTML page. I'd like to convert the JSON data to an array or list of Users in the service, rather then returning JSON from the service and having the component convert it.
Data returned from HTTP call to get users:
[
{
"firstName": "Jane",
"lastName": "Doe"
},
{
"firstName": "John",
"lastName": "Doe"
}
]
user.ts
export class User {
firstName: string;
lastName: string;
}
user-service.ts
...
#Injectable
export class UserService {
private USERS: User[] = [
{
firstName: 'Jane',
lastName: 'Doe'
},
{
firstName: 'John',
lastName: 'Doe'
}
];
constructor (private http: Http) {}
getUsersMock(): User[] {
return this.USERS;
}
getUsers(): Observable<User[]> {
return Observable.create(observer => {
this.http.get('http://users.org').map(response => response.json();
})
}
...
user.component.ts
...
export class UserComponent implements OnInit {
users: User[] = {};
constructor(private userService: UserService) {}
ngOnInit(): void {
this.getUsers();
//this.getUsersMock();
}
getUsers(): void {
var userObservable = this.userService.getUsers();
this.userObservable.subscribe(users => { this.users = users });
}
getUsersMock(): void {
this.users = this.userService.getUsersMock();
}
}
...
user.component.html
...
<select disabled="disabled" name="Users" size="20">
<option *ngFor="let user of users">
{{user.firstName}}, {{user.lastName}}
</option>
</select>
...
!!! UPDATE !!!
I had been reading the "heroes" tutorial, but wasn't working for me so I went off and tried other things. I've re-implemented my code the way the heroes tutorial describes. However, when I log the value of this.users, it reports undefined.
Here is my revised user-service.ts
...
#Injectable
export class UserService {
private USERS: User[] = [
{
firstName: 'Jane',
lastName: 'Doe'
},
{
firstName: 'John',
lastName: 'Doe'
}
];
constructor (private http: Http) {}
getUsersMock(): User[] {
return this.USERS;
}
getUsers(): Promise<User[]> {
return this.http.get('http://users.org')
.toPromise()
.then(response => response.json().data as User[])
.catch(this.handleError);
}
...
Here is my revised user.component.ts
...
export class UserComponent implements OnInit {
users: User[] = {};
constructor(private userService: UserService) {}
ngOnInit(): void {
this.getUsers();
//this.getUsersMock();
}
getUsers(): void {
this.userService.getUsers()
.then(users => this.users = users);
console.log('this.users=' + this.users); // logs undefined
}
getUsersMock(): void {
this.users = this.userService.getUsersMock();
}
}
...
!!!!!!!!!! FINAL WORKING SOLUTION !!!!!!!!!!
This is all the files for the final working solution:
user.ts
export class User {
public firstName: string;
}
user.service.ts
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { User } from './user';
#Injectable()
export class UserService {
// Returns this JSON data:
// [{"firstName":"Jane"},{"firstName":"John"}]
private URL = 'http://users.org';
constructor (private http: Http) {}
getUsers(): Observable<User[]> {
return this.http.get(this.URL)
.map((response:Response) => response.json())
.catch((error:any) => Observable.throw(error.json().error || 'Server error'));
}
}
user.component.ts
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { User } from './user';
import { UserService } from './user.service';
#Component({
moduleId: module.id,
selector: 'users-list',
template: `
<select size="5">
<option *ngFor="let user of users">{{user.firstName}}</option>
</select>
`
})
export class UserComponent implements OnInit{
users: User[];
title = 'List Users';
constructor(private userService: UserService) {}
getUsers(): void {
this.userService.getUsers()
.subscribe(
users => {
this.users = users;
console.log('this.users=' + this.users);
console.log('this.users.length=' + this.users.length);
console.log('this.users[0].firstName=' + this.users[0].firstName);
}, //Bind to view
err => {
// Log errors if any
console.log(err);
})
}
ngOnInit(): void {
this.getUsers();
}
}
Take a look at your code :
getUsers(): Observable<User[]> {
return Observable.create(observer => {
this.http.get('http://users.org').map(response => response.json();
})
}
and code from https://angular.io/docs/ts/latest/tutorial/toh-pt6.html
(BTW. really good tutorial, you should check it out)
getHeroes(): Promise<Hero[]> {
return this.http.get(this.heroesUrl)
.toPromise()
.then(response => response.json().data as Hero[])
.catch(this.handleError);
}
The HttpService inside Angular2 already returns an observable, sou don't need to wrap another Observable around like you did here:
return Observable.create(observer => {
this.http.get('http://users.org').map(response => response.json()
Try to follow the guide in link that I provided. You should be just fine when you study it carefully.
---EDIT----
First of all WHERE you log the this.users variable? JavaScript isn't working that way. Your variable is undefined and it's fine, becuase of the code execution order!
Try to do it like this:
getUsers(): void {
this.userService.getUsers()
.then(users => {
this.users = users
console.log('this.users=' + this.users);
});
}
See where the console.log(...) is!
Try to resign from toPromise() it's seems to be just for ppl with no RxJs background.
Catch another link: https://scotch.io/tutorials/angular-2-http-requests-with-observables Build your service once again with RxJs observables.
I want to develop a file configuration of json and it is called with http get the constructor and return the value I want the config file to another component. But when return gives me value undefined.
My Config.json
[ {"urlServer": "http://localhost:56877"}]
My Config.Service
export class configService
{
url: string;
constructor(public _http: Http)
{
let injector = Injector.resolveAndCreate([loggerService]);
let logger = injector.get(loggerService);
try {
return this._http.get('/app/config.json',
{
headers: contentHeaders
})
.map((res: any) =>
{
let data = <configModel>res.json();
this.url = data.urlServer;
JSON.stringify(this.url);
});
}
catch (ex) {
logger.registarErros('configService', ex);
}
}
returnConfig()
{
return this.url;
}
Now my other Component
constructor(public _http: Http, public config: configService)
{
this.token = sessionStorage.getItem('token');
this.username = sessionStorage.getItem('username');
}
login(username: String, password: String)
{
let injector = Injector.resolveAndCreate([loggerService]);
let logger = injector.get(loggerService);
try
{
alert(this.config.url);
return this._http.post('http://localhost:56877/api/Login/EfectuaLogin', JSON.stringify({ username, password }),
{
headers: contentHeaders
})
.map((res: any) =>
{
let data = <authLoginModel>res.json();
this.token = data.token;
this.username = data.nome;
sessionStorage.setItem('token', this.token);
sessionStorage.setItem('username', this.username);
return Observable.of('authObservable');
});
}
catch (ex) {
logger.registarErros('authentication', ex);
}
}
I no longer know how to solve the problem, I need your help, I'm not very experienced with Angular 2.
Thanks very much.
The problem here is that the config is load asynchronously. You could use something like that leveraging the flatMap operator:
#Injectable()
export class ConfigService {
urlServer:string;
constructor(public _http: Http) {
}
getConfig() {
if (this.urlServer) {
return Observable.of(this.urlServer);
}
return this._http.get('/app/config.json', {
headers: contentHeaders
})
.map((res: any) => {
let data = <configModel>res.json();
return data.urlServer;
}).do(urlServer => {
this.urlServer = urlServer;
});
}
}
and in your component:
login(username: String, password: String) {
return this.configService.getConfig().flatMap(urlServer => {
this._http.post('http://localhost:56877/api/Login/EfectuaLogin',
JSON.stringify({ username, password }),
{
headers: contentHeaders
})
.map((res: any) =>
{
let data = <authLoginModel>res.json();
this.token = data.token;
this.username = data.nome;
sessionStorage.setItem('token', this.token);
sessionStorage.setItem('username', this.username);
return data; // or something else
});
}
});
}
Another approach would be boostrap asynchronously after having loaded the configuration:
var app = platform(BROWSER_PROVIDERS)
.application([BROWSER_APP_PROVIDERS, appProviders]);
service.getConfig().flatMap((url) => {
var configProvider = new Provider('urlServer', { useValue: urlServer});
return app.bootstrap(appComponentType, [ configProvider ]);
}).toPromise();
See this question for the second approach:
angular2 bootstrap with data from ajax call(s)
You can go further by mixing the last approach with a CustomRequestOptions:
import {BaseRequestOptions, RequestOptions, RequestOptionsArgs} from 'angular2/http';
export class CustomRequestOptions extends BaseRequestOptions {
merge(options?:RequestOptionsArgs):RequestOptions {
options.url = 'http://10.7.18.21:8080/api' + options.url;
return super.merge(options);
}
}
See this question:
Angular 2 - global variable for all components