I'm receiving JSON data using promises and it works. But now I want to implement a button who call again API (any time that you call API you get different values) how can I do it?
quotes-provider.ts
import { Injectable } from "#angular/core";
import { Http } from '#angular/http';
import { Quote } from './quote.model';
import 'rxjs/add/operator/map';
import { resolve } from "path";
import { reject } from "q";
#Injectable()
export class QuotesProvider {
private quote: Quote;
constructor(private http: Http) {
}
public getQuote(): Quote {
return this.quote;
}
load() {
console.log("loading data...");
return new Promise((resolve, reject) => {
this.http
.get('http://quotes.stormconsultancy.co.uk/random.json')
.map(res => res.json())
.subscribe(response => {
this.quote = response;
console.log("loading complete");
resolve(true);
})
})
}
}
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule, APP_INITIALIZER } from '#angular/core';
import { AppComponent } from './app.component';
import { QuoteBoxComponent } from './quote-box/quote-box.component';
import { QuotesProvider } from './quote-box/quotes-provider';
import { HttpModule } from '#angular/http';
export function quotesProviderFactory(provider: QuotesProvider) {
return () => provider.load();
}
#NgModule({
declarations: [
AppComponent,
QuoteBoxComponent
],
imports: [
BrowserModule,
HttpModule
],
providers: [
QuotesProvider,
{ provide: APP_INITIALIZER, useFactory: quotesProviderFactory, deps: [QuotesProvider], multi: true }
],
bootstrap: [AppComponent]
})
export class AppModule { }
quote-box.component.ts
#Component({
selector: 'app-quote-box',
templateUrl: './quote-box.component.html',
styleUrls: ['./quote-box.component.css']
})
export class QuoteBoxComponent implements OnInit {
// #HostBinding('class.quote-box') quoteBox = true;
// http://quotes.stormconsultancy.co.uk/random.json
quote: Quote;
constructor(public quotesProvider: QuotesProvider) {
this.quote = quotesProvider.getQuote();
}
ngOnInit() {
console.log(this.quote.author);
}
// here I want to call API again
newQuote() {
}
}
I'm following this tutorial to do this https://devblog.dymel.pl/2017/10/17/angular-preload/
I dont know what exactly you want to do but if i understeand it right I dont know why are u doing this in that way. I would just create service and then inject to your components and use it on button click. Maybe tutorial is a little bit outdated.
quotes.service.ts
import { Injectable } from '#angular/core';
import { HttpHeaders, HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
#Injectable()
export class QuotesService {
constructor(private http: HttpClient) { }
getQuotes() {
return this.http.get('http://quotes.stormconsultancy.co.uk/random.json',
httpOptions);
}
}
Then in your component in method called on button click
Constructor
constructor(private quotesService : QuotesService) { }
In method called on button click
this.quotesService.getQuotes().subscribe(quotes => {
// do what you want with your qoutes
});
Related
I have a web api (.NET Core 3.1) that returns a json like the following:
[
{
"counterparty": "Santander",
"tradeDate": "2020-05-23T10:03:12",
"isin": "DOL110",
"typology": 0
},
{
"counterparty": "Jordan Banks",
"tradeDate": "2020-06-11T11:23:22",
"isin": "LIT250",
"typology": 0
},
{
"counterparty": "Santander",
"tradeDate": "2020-06-11T11:24:08",
"isin": "LIT300",
"typology": 0
}
]
I consume this web api with the component and angular service below. So far, I return the counterparty field of all objects.
operations.component.ts:
import { Component, OnInit } from '#angular/core';
import { OperationsService } from "./operations.service";
#Component({
selector: 'app-operations',
templateUrl: './operations.component.html',
styleUrls: ['./operations.component.css']
})
export class OperationsComponent implements OnInit {
data: any;
constructor(private operationsService: OperationsService) { }
ngOnInit(): void {
this.loadOperations();
}
loadOperations() {
return this.operationsService.getOperations().subscribe(source => this.data = source);
}
}
operations.component.html:
<div *ngFor="let item of data">
<div>{{item.counterparty}}</div>
</div>
operations.service.ts:
import { Injectable, Inject } from "#angular/core";
import { HttpClient } from "#angular/common/http";
#Injectable({
providedIn: "root"
})
export class OperationsService {
constructor(private http: HttpClient) { }
public getOperations() {
return this.http.get("https://localhost:44329/api/operations");
}
}
app.module.ts:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { HttpClientModule, HTTP_INTERCEPTORS } from '#angular/common/http';
import { RouterModule } from '#angular/router';
import { AppComponent } from './app.component';
import { NavMenuComponent } from './nav-menu/nav-menu.component';
import { HomeComponent } from './home/home.component';
import { LoginComponent } from './user/login/login.component';
import { OperationsComponent } from './operations/operations/operations.component';
#NgModule({
declarations: [
AppComponent,
NavMenuComponent,
HomeComponent,
LoginComponent,
OperationsComponent
],
imports: [
BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
HttpClientModule,
FormsModule,
RouterModule.forRoot([
{ path: '', component: HomeComponent, pathMatch: 'full' },
{ path: 'api/operations', component: OperationsComponent }
])
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
what i need now is to apply a filter in the counterparty field to return only the distinct values, that is, without repetitions of equal values. I'm trying with ng-repeat, but i have the error:
Uncaught Error: Template parse errors:
The pipe 'unique' could not be found ("]item of data | unique: item.counterparty">
{{item.counterparty}}
")
So, how can I get the distinct values of the array? Can I do it only in component.html or do I also have to change component.ts?
I think it's best to make your this.data array unique in component.ts, then just display it in component.html.
You can use another function with promise to make data array unique, based on 'counterparty'.
// make data array unique
codeToMakeItUnique = dataArr => {
return new Promise((resolve, reject) => {
const UniArr = []
const map = new Map()
for (const item of dataArr) {
if (!map.has(item.counterparty)) {
map.set(item.counterparty, true) // set any value to Map
UniArr.push(item)
}
}
resolve(UniArr)
})
}
so altogether your component.ts will look like:
import { Component, OnInit } from '#angular/core';
import { OperationsService } from "./operations.service";
#Component({
selector: 'app-operations',
templateUrl: './operations.component.html',
styleUrls: ['./operations.component.css']
})
export class OperationsComponent implements OnInit {
data: any;
constructor(private operationsService: OperationsService) { }
ngOnInit(): void {
this.loadOperations();
}
loadOperations() {
return this.operationsService.getOperations().subscribe(async source => {
this.data = await this.codeToMakeItUnique(source)
});
// make data array unique
codeToMakeItUnique = dataArr => {
return new Promise((resolve, reject) => {
const UniArr = []
const map = new Map()
for (const item of dataArr) {
if (!map.has(item.counterparty)) {
map.set(item.counterparty, true) // set any value to Map
UniArr.push(item)
}
}
resolve(UniArr)
})
}
}
}
In your component.html you can simply call your data array itself
<div *ngFor="let item of data">
<div>{{item.counterparty}}</div>
</div>
Hope this helps.
The question isnt clear but if you want to remove duplicated value from your array, cast it as a set then back to an array. That is if the array doesnt contains complex objects
loadOperations() {
return this.operationsService.getOperations().subscribe(source => this.data = Array.from(new Set(source.map((item: any) => item.counterparty))));
}
This is going to give you [ "Santander", "Jordan Banks" ]
Hello i am trying to migrate from Ionic Cordova 3 to 5.
I want to put a call a php function to get results. PHP works fine.
this is what i did to call the results.
home.ts
allMediaSet(){
console.log('dddd1');
this.offset = 0;
this.userData.allMedias(this.offset)
.map(res => res.json())
.subscribe(data => {
if (data.success) {
this.allMedia = data.mediaFeed;
}
});
}
user-data.ts function
allMedias(offset: number) {
console.log('ddd');
let url = this.appData.getApiUrl() + 'allMedia';
let data = this.jsonToURLEncoded({
api_signature: this.api_signature,
offset: offset
});
return this.http.post(url, data, this.options);
}
this is the error i am getting
core.js:6014 ERROR Error: Uncaught (in promise): NullInjectorError: StaticInjectorError(AppModule)[Platform]:
StaticInjectorError(Platform: core)[Platform]:
NullInjectorError: No provider for Platform!
NullInjectorError: StaticInjectorError(AppModule)[Platform]:
StaticInjectorError(Platform: core)[Platform]:
NullInjectorError: No provider for Platform!
app.module.ts
import { HttpClientModule } from '#angular/common/http';
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { InAppBrowser } from '#ionic-native/in-app-browser/ngx';
import { SplashScreen } from '#ionic-native/splash-screen/ngx';
import { StatusBar } from '#ionic-native/status-bar/ngx';
import { IonicModule } from '#ionic/angular';
import { IonicStorageModule } from '#ionic/storage';
import { Platform} from 'ionic-angular';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ServiceWorkerModule } from '#angular/service-worker';
import { environment } from '../environments/environment';
import { FormsModule } from '#angular/forms';
#NgModule({
imports: [
BrowserModule,
AppRoutingModule,
Platform,
HttpClientModule,
FormsModule,
IonicModule.forRoot(),
IonicStorageModule.forRoot(),
ServiceWorkerModule.register('ngsw-worker.js', {
enabled: environment.production
})
],
declarations: [AppComponent],
providers: [InAppBrowser, SplashScreen, StatusBar],
bootstrap: [AppComponent]
})
export class AppModule {}
login.ts (has the results i want to return)
import { Component } from '#angular/core';
import { NgForm } from '#angular/forms';
import { Router } from '#angular/router';
import { UserData } from '../../providers/user-data/user-data';
import { UserOptions } from '../../interfaces/user-options';
#Component({
selector: 'page-login',
templateUrl: 'login.html',
styleUrls: ['./login.scss'],
})
export class LoginPage {
resposeData: any;
loginData: any = {};
allMedia:any =[];
mediaType:string = '';
offset: number = 0;
login: UserOptions = { username: '', password: '' };
submitted = false;
constructor(
public userData: UserData,
public router: Router,
)
{
this.allMediaSet();
}
allMediaSet(){
console.log('dddd1');
this.offset = 0;
this.userData.allMedias(this.offset)
.subscribe(data => {
console.log(data);
});
}
onLogin(form: NgForm) {
this.submitted = true;
if (form.valid) {
this.userData.login(this.login.username);
this.router.navigateByUrl('/app/tabs/schedule');
}
}
}
any help?
Your question seems like not Ionic specific but it is about Angular. Since good old Ionic 3 / Angular 4 days, Angular moved on from Http to HttpClient.
Please see here: https://angular.io/guide/http#setup
You need to ensure you migrate your Angular code to use the latest HttpClientModule:
https://devops.datenkollektiv.de/migrating-from-angular-httpmodule-to-new-angular-43-httpclientmodule.html
In short:
replace 'Http' with 'HttpClient':
import {Http} from '#angular/http';
becomes
import { HttpClient } from '#angular/common/http';
Remove manual extraction of JSON via map operator:
this.userData.allMedias(this.offset).map(res => res.json())
becomes
this.userData.allMedias(this.offset)
how to Logout From website if user does not do any move in our web from 15 minutes?
In Your angular app
npm install --save #ng-idle/core #ng-idle/keepalive angular2-moment
Set up your application module
Open src/app/app.module.ts and import the Ng2IdleModule using
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { NgIdleKeepaliveModule } from '#ng-idle/keepalive'; // this includes the core NgIdleModule but includes keepalive providers for easy wireup
import { MomentModule } from 'angular2-moment'; // optional, provides moment-style pipes for date formatting
import { AppComponent } from './app.component';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
MomentModule,
NgIdleKeepaliveModule.forRoot()
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Extend your Main component
import { Component, OnInit } from '#angular/core';
import { Router, NavigationStart } from '#angular/router';
import { Idle, DEFAULT_INTERRUPTSOURCES } from '#ng-idle/core';
import { Keepalive } from '#ng-idle/keepalive';
#Component({
selector: 'app-theme',
templateUrl: './theme.component.html',
styleUrls: ['./theme.component.css']
})
export class AppComponent implements OnInit {
lastPing?: Date = null;
constructor(private route: Router, private idle: Idle, private keepalive: Keepalive) {
idle.setIdle(5);
idle.setTimeout(900);
idle.setInterrupts(DEFAULT_INTERRUPTSOURCES);
idle.onIdleEnd.subscribe(() => { });
idle.onTimeout.subscribe(() => {
this.logout();
});
idle.onIdleStart.subscribe(() => {
});
idle.onTimeoutWarning.subscribe((countdown) => {
});
keepalive.interval(5);
keepalive.onPing.subscribe(() => this.lastPing = new Date());
this.reset();
}
ngOnInit() {
}
reset() {
this.idle.watch();
}
logout() {
//--
// LogoutCode
//---
}
}
I have a Angular 6 application, I would like to connect some rest api data into my application. I have written a service for this. The rest api is: https://demo1049220.mockable.io/api/incident. Which takes in data from a results object. So far I have the following code but it does not work as the data is not showing in the table:
Also error in console is: Uncaught TypeError: Cannot read property 'ngOriginalError' of undefined
Service.ts
import { Injectable } from '#angular/core';
import { HttpClient, HttpEventType, HttpHeaders, HttpRequest, HttpResponse, HttpErrorResponse } from '#angular/common/http';
import { Observable, of, throwError } from 'rxjs';
import { catchError, retry } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class nowService {
serviceApiUrl: string = 'https://demo1049220.mockable.io/api/incident';
constructor(
private http: HttpClient,
) { }
getAll(): Observable<any> {
return this.http.get<any>(this.serviceApiUrl)
.pipe(
catchError(this.handleError)
);
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
console.log(error.error.message)
} else {
console.log(error.status)
}
return throwError(
console.log('Something has happened; Api is not working!!'));
};
}
Component.ts
import { Component, OnInit } from '#angular/core';
import { HttpClient, HttpEventType, HttpHeaders, HttpRequest, HttpResponse } from '#angular/common/http';
// Services
import { nowService } from '../../services/servicenow.service';
#Component({
selector: 'app-service-incident',
templateUrl: './service-incident.component.html',
styleUrls: ['./service-incident.component.scss']
})
export class ServiceIncidentComponent implements OnInit {
public incidents: any;
public loading = true;
public errorApi = false;
constructor(private service: nowService) {
}
ngOnInit() {
this.service.getAll().subscribe((data) => {
this.loading = true;
this.incidents = data;
this.loading = false;
console.log('Result - ', data);
console.log('data is received');
})
}
}
Table in html to list the data
<tbody>
<tr class="" *ngFor="let incident of incidents">
<td><input type="radio" name="gender">
<i class="form-icon mr-5"></i>{{incident.u_serial_number}}</td>
<td>{{incident.u_product_name}}</td>
<td>{{incident.u_address_floor}}</td>
<td>{{incident.u_address_line_1}}</td>
<td>{{incident.u_address_post_code}}</td>
</tr>
</tbody>
You have to import your HttpClientModule in your app module, code:
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import { HttpClient, HttpClientModule } from '#angular/common/http';
import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';
#NgModule({
imports: [ BrowserModule, FormsModule, HttpClientModule ],
providers: [HttpClient, ],
declarations: [ AppComponent, HelloComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
and use data.result in your ngFor loop, check this:
ngOnInit() {
this.service.getAll().subscribe((data) => {
this.loading = true;
this.incidents = data.result;
this.loading = false;
console.log('Result - ', data.result);
console.log('data is recieved');
})
}
Can you check if the console is displaying some error ? (Ctrl+Shift+I on Google Chrome, then click on Console)
I am following the tutorial here: https://coursetro.com/posts/code/154/Angular-6-Tutorial---Learn-Angular-6-in-this-Crash-Course
I currently have the code up to the section titled Fetching More Data from the API working. In short this is supposed to make a page with a bunch of users accessed through a toy API. The users are listed on a page with some personal information, and each one links to a very basic profile page displaying their details. Up to the section I mentioned above, I am successfully interfacing with the API, getting the users and displaying them and some personal information on the main page.
However, the code in this section is intended to collect an individual user's details and display them on a linked page. In trying to follow the example, my code does produce a page with the right outlines, but the value of the variable user$ and its fields like user$.name don't seem to be loaded by the details component. Where those values are supposed to show up, it's blank.
The app files:
app-routing.module.ts
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { UsersComponent } from './users/users.component';
import { DetailsComponent } from './details/details.component';
import { PostsComponent } from './posts/posts.component';
const routes: Routes = [
{
path: '',
component: UsersComponent
},
{
path: 'details/:id',
component: DetailsComponent
},
{
path: 'posts',
component: PostsComponent
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
app.component.html
<div id="container">
<app-sidebar></app-sidebar>
<div id="content">
<router-outlet></router-outlet>
</div>
</div>
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { SidebarComponent } from './sidebar/sidebar.component';
import { PostsComponent } from './posts/posts.component';
import { UsersComponent } from './users/users.component';
import { DetailsComponent } from './details/details.component';
import { HttpClientModule } from '#angular/common/http';
#NgModule({
declarations: [
AppComponent,
SidebarComponent,
PostsComponent,
UsersComponent,
DetailsComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
data.service.ts
import { Injectable } from '#angular/core';
import {HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class DataService {
constructor(private http: HttpClient) { }
getUsers() {
return this.http.get('https://jsonplaceholder.typicode.com/users')
}
getUser(userId) {
return this.http.get('https://jsonplaceholder.typicode.com/users'+userId)
}
getPosts() {
return this.http.get('https://jsonplaceholder.typicode.com/posts')
}
}
users files:
users.component.html
<h1>Users</h1>
<ul>
<li *ngFor="let user of users$">
{{user.name}}
<ul>
<li>{{user.email}}</li>
<li>{{user.website}}</li>
</ul>
</li>
</ul>
users.component.ts
import { Component, OnInit } from '#angular/core';
import { DataService } from '../data.service';
import { Observable } from 'rxjs';
#Component({
selector: 'app-users',
templateUrl: './users.component.html',
styleUrls: ['./users.component.scss']
})
export class UsersComponent implements OnInit {
users$: Object;
constructor(private data: DataService) { }
ngOnInit() {
this.data.getUsers().subscribe(
data => this.users$ = data
);
}
}
details files:
details.component.html
<h1>{{ user$.name }}</h1>
<ul>
<li><strong>Username: </strong> {{user$.username}}</li>
<li><strong>Email: </strong> {{user$.email}}</li>
<li><strong>Phone: </strong> {{user$.phone}}</li>
</ul>
details.component.ts
import { Component, OnInit } from '#angular/core';
import { DataService } from '../data.service';
import { Observable } from 'rxjs';
import { ActivatedRoute } from '#angular/router';
#Component({
selector: 'app-details',
templateUrl: './details.component.html',
styleUrls: ['./details.component.scss']
})
export class DetailsComponent implements OnInit {
user$: Object;
constructor(private data: DataService, private route: ActivatedRoute) {
this.route.params.subscribe( params => this.user$ = params.id );
console.log(this.route.params);
}
ngOnInit() {
this.data.getUser(this.user$).subscribe(
data => this.user$ = data
);
}
}
I tried logging values to the console, but I don't fully understand how TypeScript works so I don't fully know what I really should expect from these logs. In any case, in the log that I made in the details TypeScript file, it showed an object with no apparent loading errors.
this.route.params is a Observable. I am not sure what you can get by logging it.
I would suggest you add a log when subscribing to a observable and see what kind of data you really get. Like.
this.data.getUser(this.user$).subscribe(
data => {console.log(data);this.user$ = data}
);
#Adem, As Haijin comment, you must "work" a bit in subscribe parameter. The idea is that you subscribe to get the parameter, and, when you have the parameter, you ask about the user. But you need to make in the same step using switchMap
ngOnInit()
{
//You subscribe the param. When you have ask for the user
this.route.params.subscribe( params =>
{
this.user$ = params.id;
//In subscribe you ask for the user
this.data.getUser(this.user$).subscribe(
data => this.user$ = data
)
});
}
Well, really In Angular is better don't subscribe two times else using Rjxs and switchMap
ngOnInit()
{
//You subscribe the params, but you don't want the param
this.route.params.pipe(
switchMap(params =>
{ //you want return the user
return this.data.getUser(params.id)
})
).subscribe(data => this.user$ = data)
}