I have an IONIC APP with CORDOVA. I Just want to GET a JSON from an URL.
I Created a service call rest.service.ts
rest.service.ts
import { Injectable } from '#angular/core';
import { HTTP } from '#ionic-native/http/ngx';
#Injectable({
providedIn: 'root'
})
export class RestService {
BASE_URL = 'http://whatever.....';
constructor(public http: HTTP) {}
getProjects() {
const URL = this.BASE_URL + 'getProjects';
this.http.get(URL, {}, { 'Content-Type': 'application/json' })
.then(answer => {
return JSON.parse(answer.data);
})
.catch(error => {
console.log(error.status);
console.log(error.error); // error message as string
console.log(error.headers);
});
}
}
Here in this file I can see the info. If I insert something like...
console.log(JSON.parse(answer.data));
I can see the results in JSON just as I Want.
The problem is when I try to use this methods in other files...
otherpage.page.ts
import { Platform } from '#ionic/angular';
import { RestService } from './../rest.service';
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-otherpage',
templateUrl: './otheropage .page.html',
styleUrls: ['./otherpage .page.scss']
})
export class OtherPage implements OnInit {
projects;
constructor(
public platform: Platform,
public rest: RestService,
) {
this.projects = this.rest.getProjects();
console.log(this.projects); // UNDEFINED
}
ngOnInit() { }
}
Here... this.projects... is undefined... ¿What is happening? I tried platform.ready, insert in ngOnInit... nothing works.
You need to modify the service and subscribe this service your page.
BASE_URL = 'http://whatever.....';
getProjects() {
const URL = this.BASE_URL + 'getProjects';
return this.http.get(URL, {}, { 'Content-Type': 'application/json' });
}
Subscribe this service observable in your page.ts file.
this.rest.getProjects().subscribe((answer)=>{
this.projects = JSON.parse(answer.data);
console.log(this.projects); // here you get the json
},error=>{
consoole.log(error)
});
Note:
console.log(this.projects); // UNDEFINED
Because this line executes before the http observable send the response, you need to subscribe that http observable to get the json.
Related
I am working on an angular project for learning. I want to find a way to change the routing based on the routing code that I receive. See my code below for my service.ts file. We were not able to get the toke api set up so I am just looking to switch routing based on 200 status code.
import { Injectable } from '#angular/core';
import {HttpClient} from '#angular/common/http';
import { Observable, throwError, catchError } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class LoginService {
token:string = ""
// Login Logic
login(userName:string, password:string):Observable<any>{
return this.http.post('https://vanquish-p2.azurewebsites.net/api/UserC/Authenticate?UserName=' + userName +'&password=' + password,
// We need to add headers to specify content type
{headers: {'Content-Type':'application/json'}}
)
.pipe(
catchError((e) =>{
return throwError(e)
}
))
}
// Inject HttpClient into our service
constructor(private http:HttpClient) { }
}
This right here is my login component
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { LoginService } from '../login.service';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
// Adding in defaults to store info
userName:string = "";
password:string = "";
error:boolean = false;
// Create onsubmit to handle submissions
onSubmit():void{
console.log(this.userName, this.password)
this.loginService.login(this.userName, this.password)
.subscribe((data) =>{
console.log(data)
// Let's store the data in our service's string
this.loginService.token = data.token;
console.log(this.loginService.token)
// If we successfully login, let's redirect to the home page
this.router.navigate(['home'])
},
(error) =>{
console.log(error)
// Makes error message appear through ngIf
this.error = true;
})
}
//Inject login service to component to use methods
// Inject router for navigation
constructor(private loginService:LoginService, private router:Router) { }
ngOnInit(): void {
}
This question already has an answer here:
Updating Data in Firebase using React and Axios
(1 answer)
Closed 2 years ago.
i'm creating a Deckbuilder, i have this decks of cards and a data-storage.service to store and fetch the decks in Firebase.
i have a component deck-details that shows the details of a selected deck and allows to remove or add cards to the deck.
i'm trying to store the modified cards in the selected deck in firebase
this is the data-storage service
#Injectable({ providedIn: "root" })
export class DataStorageService {
constructor(private http: HttpClient, private deckService: DeckService) {}
storeDecks() {
const decks = this.deckService.getDecks();
this.http
.put("https://ang-cards.firebaseio.com/decks.json", decks)
.subscribe((response) => {
console.log(response);
console.log("stored");
});
}
fetchDecks() {
return this.http
.get<Deck[]>("https://ang-cards.firebaseio.com/decks.json")
.subscribe((decks) => {
decks
? this.deckService.setDecks(decks)
: this.deckService.setDecks([]);
console.log("fetching", decks);
});
}
storeCards(i: number, cards: Card[]){
this.http
.put("https://ang-cards.firebaseio.com/decks/" + i + "/deckCards", cards)
.subscribe((response) => {
console.log(response);
console.log("cards stored");
});
}
}
storeDecks and fetchDecks work, but i have a problem with storeCards function called in the deck-details component in the onCardsEdit() function.
this is the deck-detail component
import { Card } from "./../../card/card.model";
import { Deck } from "./../../deck/deck.model";
import { Component, OnInit, Input } from "#angular/core";
import { DeckService } from "src/app/deck/deck.service";
import { ActivatedRoute, Params, Router } from "#angular/router";
import { Subscription } from "rxjs";
import { DataStorageService } from 'src/app/shared/data-storage.service';
#Component({
selector: "app-deck-details",
templateUrl: "./deck-details.component.html",
styleUrls: ["./deck-details.component.scss"],
})
export class DeckDetailsComponent implements OnInit {
paramsSubscription: Subscription;
id: number;
decks: Deck[];
deck: Deck;
constructor(
private deckService: DeckService,
private route: ActivatedRoute,
private dataStorageService: DataStorageService
) {}
ngOnInit() {
this.decks = this.deckService.getDecks();
this.id = this.route.snapshot.params["id"];
this.paramsSubscription = this.route.params.subscribe((params: Params) => {
this.id = params["id"];
this.deck = this.decks.find((deck) => deck.id === this.id);
});
}
onDeleteCard(i){
this.deckService.deleteCard(this.deck, this.deck.deckCards[i])
}
onCardsEdit(){
this.dataStorageService.storeCards(this.decks.indexOf(this.deck), this.deck.deckCards)
}
ngOnDestroy() {
this.paramsSubscription.unsubscribe();
}
}
when i try to store the cards i get these 3 errors:
Access to XMLHttpRequest at 'https://ang-cards.firebaseio.com/decks/1/deckCards' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
PUT https://ang-cards.firebaseio.com/decks/1/deckCards net::ERR_FAILED
core.js:5882 ERROR HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: "https://ang-cards.firebaseio.com/decks/1/deckCards", ok: false, …}
To interact with the REST API of the Firebase Realtime Database, your URLs must end with .json. Without that, you're trying to access the Firebase console, which returns a cross-origin error when you do.
So the code should look something like:
this.http
.put("https://ang-cards.firebaseio.com/decks/" + i + "/deckCards.json", cards)
...
I'm having trouble converting RSS to JSON using the rrs2json API with Ionic 3. If I execute the code it gives me the error --> Response {_body: "{" status ":" error "," message ":" rss_url parameter is required."} ", Status: 422, ok: false, statusText:" Unprocessable Entity "}
Code:
noticies.ts
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { RssProvider } from '../../providers/rss/rss';
#IonicPage()
#Component({
selector: 'page-noticies',
templateUrl: 'noticies.html',
})
export class NoticiesPage {
rssDataArray: any = [];
constructor(public navCtrl: NavController, public navParams: NavParams, public rssProvider: RssProvider) {
}
ionViewDidLoad() {
console.log('ionViewDidLoad NoticiesPage');
this.Get_RSS_Data()
}
Get_RSS_Data(){
this.rssProvider.GetRSS().subscribe(
data => {
this.rssDataArray = data;
console.log(data);
}
);
}
}
providers --> rss --> rss.ts
import { Injectable } from '#angular/core';
import {Http} from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class RssProvider {
constructor(public http: Http) {
console.log('Hello RssProvider Provider');
}
GetRSS(){
const RSS_URL: any='http://rss.cnn.com/rss/edition.rss';
const API: any='XXXXXXXXXXXXXX';
const count: any =20;
const API_URL: any ='https://api.rss2json.com/v1/api.json';
const response = this.http.post(API_URL, {'rss_url': RSS_URL,'api_key': API, 'count': count}).map(res => res.json());
return response;
}
}
Error -->
Error
Alright. I registered myself with the rss2json service and made sure this solution actually works (you can see the data in console).
The issue you have is that you are not using a proper way to form http request with HttpParams.
Here is working stackblitz that uses my key: https://stackblitz.com/edit/ionic-jdwqjg
now some details:
when you configure a URL using rss2json it basically adds parameters to the original URL, example:
https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Ftechcrunch.com%2Ffeed%2F&api_key=q5ijkolkdjk3urzrcfaehxeoimxr3tdu5ieiqcrq&order_by=pubDate&order_dir=asc&count=20
So in Angular/Ionic you need to leverage Angular's HttpParams to properly form request, here is your provider code with HttpParams:
provider code:
import { Injectable } from '#angular/core';
import { HttpClient, HttpParams } from '#angular/common/http';
#Injectable()
export class RssProvider {
private API_URL: string;
constructor(public http: HttpClient) {
this.API_URL = "https://api.rss2json.com/v1/api.json";
}
GetRSS() {
const params = { params: new HttpParams().set('rss_url', 'http://rss.cnn.com/rss/edition.rss').set('api_key','q5ijkolkdjk3urzrcfaehxeoimxr3tdu5ieiqcrq').set('order_by', 'pubDate').set('order_dir', 'asc')
}
return this.http.get(this.API_URL, params);
}
}
I'm creating an Angular6 crud app and I have a list of users in my database. I am able to retrieve my list when I call getAllUsers but it does not display in the UI. The only time I see a row being displayed in the table is when I manually enter a new User but it does not display the data previous to my entry. What am I doing wrong?
import { Component, OnInit } from '#angular/core';
import { UserDataService } from './user-data.service';
import { User } from './user';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [UserDataService]
})
export class AppComponent implements OnInit{
users: User[]=[];
constructor(private userDataService: UserDataService) {}
public ngOnInit() {
debugger
this.userDataService
.getAllUsers()
.subscribe(
(users) => {
this.users = users;
}
);
}
onAddUser(user) {
this.userDataService
.addUser(user)
.subscribe(
(newUser) => {
this.users = this.users.concat(newUser);
}
)
}
onRemoveUser(user){
this.userDataService
.deleteUserById(user.id)
.subscribe(
(_) => {
this.users = this.users.filter((u) => u.id !== user.id);
}
);
}
getUser() {
return this.userDataService.getAllUsers();
}
}
APP COMPONENT HTML
<app-user-list-header (add)="onAddUser($event)"></app-user-list-header>
<table>
<th>ID</th>
<th>NAME</th>
<tr *ngFor = "let user of users">
<td>{{user.id}}</td>
<td>{{user.userName}}</td>
</tr>
</table>
USER DATA SERVICE
import { Injectable } from '#angular/core';
import { User } from './user';
import { ApiService } from './api.service';
import { Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class UserDataService {
constructor(private api: ApiService) { }
addUser(user: User): Observable<User> {
return this.api.createUser(user);
}
getAllUsers(): Observable<User[]> {
return this.api.getAllUsers();
}
updateUser(user: User): Observable<User> {
return this.api.updateUser(user);
}
getUserById(userId: number): Observable<User> {
return this.api.getUserById(userId);
}
deleteUserById(userId: number): Observable<User> {
return this.api.deleteUserById(userId);
}
}
USER LIST HEADER
import { Component, OnInit, Output, EventEmitter } from '#angular/core';
import { User } from '../user';
#Component({
selector: 'app-user-list-header',
templateUrl: './user-list-header.component.html',
styleUrls: ['./user-list-header.component.css']
})
export class UserListHeaderComponent implements OnInit {
newUser: User = new User();
#Output()
add: EventEmitter<User> = new EventEmitter();
constructor() { }
ngOnInit() {
}
addUser() {
this.add.emit(this.newUser);
this.newUser = new User();
}
}
USER LIST HEADER HTML
<header class="userHeader">
<h1>Users</h1>
<input class="new-user" placeholder="Enter User" autofocus="" [(ngModel)]="newUser.userName" (keyup.enter)="addUser()">
</header>
API SERVICE
import { Injectable } from '#angular/core';
import { environment } from '../environments/environment';
import { User } from './user';
import { Http } from '#angular/http';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '#angular/common/http';
import { Observable } from 'rxjs';
import { map, catchError } from "rxjs/operators";
const API_URL = environment.apiUrl;
#Injectable({
providedIn: 'root'
})
export class ApiService {
constructor(private http: HttpClient) {
}
public createUser(user: User): Observable<User> {
const headers = {headers: new HttpHeaders({
'Content-Type': 'application/json'
})};
return this.http
.post(API_URL + '/users', user).pipe(
map(response => {
return new User(response);
}), catchError(this.handleError)
)
}
public getAllUsers(): Observable<User[]> {
return this.http
.get(API_URL + '/users').pipe(
map(response => {
var users = [response];
return users.map((user)=> new User(user));
}), catchError(this.handleError))
}
The issue is, you don't need to subcribe a new user to the observable here in the AppComponent again after you have done it before:
.subscribe(
(newUser) => {
this.users = this.users.concat(newUser);
}
)
because it is already added to the user array by this mean: this.userDataService.addUser(user), that says you inserted the same value twice to the observer.
So what you need to do is, in the userdata service, plug an observer to the rest api that fetches data regularily to the adapter getAllUsers like this:
getAllUsers(): Observable<user[]> {
// some intermediate post call happens here
this.api.getAllUsers().subscribe((users) => users.map((user)=>this.users.push(user)));
return of(this.users);
}
This will update the state of users whenever a new value added to the users base, or piped from the rest call, so you do never have to subcribe the same value more than once from the same observer, this will cause duplication of data.
I couldn't find an online api that allows post calls, so you could find your ease figuring that I said above using your own tools, but for a same-domain GET api service, I made an example in this term visible to your eyes here:
https://stackblitz.com/edit/angular-rndqsd.
Taking countries as users for sake of vocabulary-allowance.
I want to get data from Riot API and display it in html view.
However, i can not "hold" this data in my variable. Console log show empty array.
I can see json data only in function scope.
I guess, i didn`t use observable function corretly, am i wrong?
Here is my component.
import { Component, OnInit } from '#angular/core';
import { FRIEND } from '../../services/_friends/mock-friends';
import { APIKEY } from '../../services/_lolapi/apikey';
import { Http, Response } from '#angular/http';
import { KeysPipe } from '../../pipes/key';
import { JsonPipe } from '#angular/common';
import 'rxjs/add/operator/map';
import { Observable } from 'rxjs/Observable';
#Component({
selector: 'app-friends',
templateUrl: './friends.component.html',
styleUrls: ['./friends.component.css']
})
export class FriendsComponent implements OnInit {
friends = FRIEND;
apikey = APIKEY;
nick: string[];
query: string;
private apiUrl =
'https://eun1.api.riotgames.com/lol/summoner/v3/summoners/by-name/';
data: Array<string> = [];
constructor(private http: Http) {
}
getFriendData(query) {
return this.http.get(query)
.map((res: Response) => res.json());
}
getContacts() {
this.getFriendData(this.query).subscribe(data => {
this.data = data;
console.log(this.data);
});
}
ngOnInit() {
for (let i of this.friends) {
this.query = `${this.apiUrl}${i.nick}${this.apikey}`;
this.getFriendData(this.query);
this.getContacts();
console.log(i.nick);
}
}
}
You don't need this.getFriendData(this.query) in ngOnInit as in the next line you call getContacts that wraps getFriendData.
Now, your API returns SummonerDTO - a complex object and you are trying to store it as an Array? That doesn't seem right.
Additionally, it think you want to store every result in an array, right?
In that case you should rather use:
this.data.push(data);