I am trying to retrieve data from the Statbureau inflation api- https://www.statbureau.org/en/inflation-api using Angular 2. I am starting off just testing out my api and making sure it outputs a success message in the console. It appears that the api I'm using is JSONP, because of the JSON address that I'm using http://www.statbureau.org/calculate-inflation-price-jsonp?jsoncallback=? On the website they provide a JS fiddle that makes a succesful call to the api using jquery. When I try to make the same call in Angular 2 I get the following errors:
TypeScript error: C:/Users/Rennie/projects/inflator/app/pages/home/home.ts(22,13): Error TS
2322: Type 'Observable<any>' is not assignable to type 'HomePage'.
Property 'jsonp' is missing in type 'Observable<any>'.
TypeScript error: C:/Users/Rennie/projects/inflator/app/pages/home/home.ts(22,13): Error TS
2409: Return type of constructor signature must be assignable to the instance type of the c
Here is my code
import {Component} from '#angular/core';
import {NavController} from 'ionic-angular';
import {Jsonp, URLSearchParams } from '#angular/http';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/map';
#Component({
templateUrl: 'build/pages/home/home.html'
})
export class HomePage {
constructor(private jsonp: Jsonp) {
this.jsonp=jsonp;
let cpiUrl = "https://www.statbureau.org/calculate-inflation-price-jsonp?jsoncallback"
let params = new URLSearchParams();
params.set('country', 'united-states');
params.set('amount', '102');
params.set('start', '1968/1/1');
params.set('finish', '2016/1/1');
// TODO: Add error handling
return this.jsonp
.get(cpiUrl, { search: params }).map(function(response){ return response.json(); })
}
}
My code differs from the call in the jsfiddle because I hard coded the api parameters just to quickly see a result.
1) A constructor typically (always?) does not have a return statement. Removing the return statment should handle type 'Observable<any>' is not assignable to type 'HomePage'.
2) There does not seem to be a method get on the Jsonp class in Angular 2 check the docs.
3) An observable sequence/pipeline will not be executed until subscription (they are lazy), so even if that code did compile the request would not be executed.
4) I think you should take a look at this similiar question.
Good luck.
Related
I'm trying to inject some dependency with tsyringe delay function but the typescript are warning me with the follow error:
Type 'string' is not assignable to type 'constructor<any>'.ts(2322)
lazy-helpers.d.ts(9, 54): The expected type comes from the return type of this signature.
I need this delay because TypeORM take some time to establish a connection with the database, and if my injection refers to an Database provider, it throw an Exception case the TypeORM don't establish the connection yet.
The code below works, but i thought that is something wrong as typescript is given me the error message, there is a way to resolve that?
Code sample
import { delay, inject, injectable } from "tsyringe";
import { IRandomProvider } from "#shared/container/providers/IRandomProvider";
#injectable()
class RandomClass {
constructor(
#inject(delay(() => "RandomProvider"))
private randomProvider: IRandomProvider
) {}
Tsyringe delay helper function doc: https://github.com/microsoft/tsyringe#the-delay-helper-function
tsyringe version: 4.6.0
I'm getting strange TypeScript errors and I'm having difficulty deciphering what is wrong. My code runs fine but the PHPStorm IDE is throwing the following errors:
TS2345 Argument of Type 'UnaryFunction<Observable<{}>, Observable<{}>>' is not assignable to parameter of type 'OperatorFunction<Object, {}>'.
That error is on the tap function on the code below.
// Get Search Results
getSearchResults(payload: object): Observable<SearchResult[]> {
let sbRef = this.snackBar.openFromComponent(SmallSpinnerComponent);
let preparedPayload = this.addPayloadIdentifiers(payload);
return this.http.post(environment.searchUrl, preparedPayload, {responseType: 'json'}).pipe(
tap(res => console.log(res)),
map(res => {
sbRef.dismiss();
return this.translateJSONResultSetV1(res);
}),
catchError(this.errorHandler.handleError(`getSearchResults error`))
);
}
If I comment the tap operator out completely, I get the following error on the map operator:
TS2345 Argument of Type 'UnaryFunction<Observable<{}>,
Observable<SearchResult[]>>' is not assignable to parameter of type
'OperatorFunction<Object, {}>'.
Types of parameters 'source' and 'source' are incompatible.
Type 'Observable<Object>' is not assignable to type 'Observable<{}>'
I'm tempted to think the error is really quite simple but I can't seem to figure out what is causing it. Additionally, the JSON payload being received from the RESTful requires quite a bit of processing on the client-side. This is unavoidable so I am using a helper function translateJSONResultSetV1 in the map operator to return the right object types. Is this incorrect to use a function inside a map operator? Could this be causing the errors?
I want to stress that the code runs fine. However, if I'm working with the Observables incorrectly, I want to fix it so this code doesn't end up breaking with future updates.
EDIT: RxJS Version 5.5.2
Imports:
import { Injectable } from '#angular/core';
import { HttpClient} from '#angular/common/http';
import { environment } from "../../../environments/environment";
import { catchError, map, tap} from "rxjs/operators";
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/fromEvent';
import 'rxjs/add/observable/merge';
import { ErrorHandlerService } from "./error-handler.service";
import { SearchFilterDropdown } from "../../classes/search-filter-dropdown";
import { SessionService } from "./session.service";
import { BusinessRule } from "../../classes/business-rule";
import { SearchResult } from "../../classes/search-result";
import { SectionHeading } from "../../classes/section-heading";
import { SmallSpinnerComponent } from "../../shared/small-spinner/small-spinner.component";
import { MatSnackBar } from "#angular/material";
My money is on your use of the catchError operator. The statement this.errorHandler.handleError('getSearchResults error') will need to return a method that returns an observable.
catchError is like a switchMap when the source observable errors and could then infer a different type. This edge case operator has the ability to produce an error that "is really quite simple but I can't seem to figure out what is causing it."
I'm using ionic and have created a custom pipe that takes an object representing image data and returns a URL to that image.
The pipe file looks like this...
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'eventImageLink',
})
export class EventImageLinkPipe implements PipeTransform {
/**
* Takes a value and makes it lowercase.
*/
transform(value: string, ...args) {
if(value){
return `//res.cloudinary.com/***/image/upload/w_${window.screen.width},d_item_placeholder_e0lign.jpg/${value.image_version}/${args[0]}/${value.original_image_name}`;
}
}
}
I have created a pipes.module.ts file in the pipes folder that imports my pipes...
import { NgModule } from '#angular/core';
import { EventImageLinkPipe } from './event-image-link/event-image-link';
#NgModule({
declarations: [
EventImageLinkPipe
],
imports: [
],
exports: [
EventImageLinkPipe
]
})
export class PipesModule {}
Now before I even import the PipesModule into a component for use I am getting the following error...
Typescript Error
Property 'image_version' does not exist on type 'string'.
I can't understand why this error is coming up when I haven't even attempted to use it yet and it's quite annoying really. Can someone explain why the pipe is being executed and how I can prevent this error from throwing when I haven't passed any data into the pipe yet?
Well, you declared input value: string which means that you will pass object of type string in it's place in the future. Type of string does not have property of an image_version as the error says, that is an error and your code simply won't work. You're trying to call value.image_version as part of your return result, you will need to change value to be of a proper type, not sure which it is in your case.
You could probably have a custom class for it:
export class MyImage {
image_version: string;
original_image_name: string;
}
You can then declare a value: MyImage as type of MyImage class and Typescript will be fine with it since it contains both properties, image_version and original_image_name unlike string type.
Also, nothing is being executed really, it's just the TypeScript's static-type checking, which prevents you from doing stupid mistakes like this. If you don't want to use static-type checking features, you could also just set it as value with no type specified. That way you can pass whatever you want and it will crash at runtime if it's a wrong type of an object instead.
I've been stuck on an error that I'm not completely sure how to solve.
My application is made in Angular2 and runs completely in a webworker largely based on this tutorial http://www.syntaxsuccess.com/viewarticle/web-workers-in-angular-2.0
My first feature was an implementation of socket.io which is working perfectly(also with observables etc..) but now I want to use the Http service of Angular2 and I get the following error:
My code of the service is like this and the error arrises when I call validateAccessToken (I have to add the .js on my imports otherwise I get a 404 on the files within the webworker):
import { Injectable } from '#angular/core';
import { Http, Headers, RequestOptions, Response } from "#angular/http";
import { environment } from "../../../environments/environment.js";
import { Observable } from "rxjs/Observable.js";
import 'rxjs/add/operator/toPromise.js';
import 'rxjs/add/operator/map.js';
#Injectable()
export class AuthService {
headers: Headers;
options: RequestOptions;
url: string;
constructor(private http:Http) {
this.url = environment.authServerUrl;
}
validateAccessToken(token) {
return this.http.get(this.url)
.map(this.extractData)
.catch(this.handleError);
};
extractData(response: Response) {...}
handleError(error: any) {...}
}
I know the question is quite vague but with the information I get from the error it's not really clear what's going wrong for me.
The CookieXSRFStrategy is default enabled by Angular2 and used by http.
The webworker does not have DOM access to get the cookie to insert in the http headers. And thus throws the error Uncaught not implemented.
You should implement your own CookieXSRFStrategy strategy which at least does not throw this error ;)
I am working on the front end of a file upload service. I am currently ignoring the service path with respect to the backend. I have run into a strange problem. I have a few generated components that sit within the app component. When I end the serve from console and do ng serve again, it errors out. It says:
The only way I have found to get rid of this is to erase my uploader service injection, save the file, then re-insert the injection. This is how it is supposed to look:
The only way to get ng serve to work is to by erasing the line private service: UploaderService
Any idea why this is happening? Am I missing something with my injection? My UploaderService is marked as Injectable() and the components that use it are under Directives.
Update:
What I found out is that it is unrelated to the UploaderService. I have a component that does not inject the UploaderService. I fix it the same way I fix the other components that inject the UploaderService. By deleting the parameters of the constructor, saving, and then putting the parameters back. Then it will serve
Update2:
The generated componenet, upload.component.t, has a spec file that is generated with it, upload.component.spec.ts
It has a error that asks for parameters like so:
My UploadComponent constructor has a parameter in it, where i inject the UploaderService. In the spec.ts file, a new UploadCompent is created, but does not contain any arguments. I am guessing this is where I am going wrong. How do I work around this?
Here is my UploaderService:
import { Injectable } from '#angular/core';
import {Http, Response, HTTP_PROVIDERS, Headers, HTTP_BINDINGS, RequestOptions} from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';
import { ItemEntryComponent } from './item-entry';
import { Query } from './Query';
#Injectable()
export class UploaderService {
public URL: string;
private query: Query;
public filesSelected: Array<ItemEntryComponent> = [];
progress$: any;
progress: any;
progressObserver: any;
//CONSTRUCTOR
constructor(private http: Http) {
//***SET URL***
this.URL = 'http://localhost:7547/api/picker';
//Create Query for url
this.query = new Query(this.URL);
//Create progress attribute
this.progress$ = Observable.create(observer => {
this.progressObserver = observer
}).share();
}
}
Problem solved!
I had not realized the generated files included a spec testing file, in my example it was upload.component.spec.ts. Getting rid of those files gets rid of the errors that ask for parameters to be filled in inside the test files and now ng serve works.