Cannot read queryParams in Angular - html

I am trying to fetch queryParams from url with window.location but query params are not being grabbed.
Example my url is www.abc.com?accountId=123#
I am looking for a way to grab accountId=123 as a queryParam or atleast the entire url.
When I used window.location I am getting www.abc.com/#/ instead of www.abc.com?accountId=123#
Why am I not able to read the query params?
Why am I not able to read the query params?

according to the angular documentation you can fetch the query parameters with the activatedRoute in Angular.
In the below example we grab a query parameter "name".
constructor(
private route: ActivatedRoute,
) {}
ngOnInit() {
this.route.queryParams.subscribe(params => {
this.name = params['name'];
});
}

Related

Angular: How to get async data for template

I have the following problem:
I want to make a table with entries (Obj). And some of them have a file attribute.
If they have a file attribute (entry.file) I want to make a backend call to get the url of that file:
public getFileURL(archiveID: string, documentID: string, sysID: string){
const request: FileRequest = {
archiveID: archiveID,
documentID: documentID,
sysID: sysID
};
this.fileService.file(request).subscribe(response => {
if (response) {
return response;
}
})
}
This is called like: getFileURL(entry.file.archiveID, entry.file.documentID, entry.file.sysID)
And it should return an Observable, so I can check if i got a backend response.
<tr *ngFor="let entry of period.claims; let i = index">
...
<td>
<div *ngIf="entry.file">
<div *ngIf="fileClientService.getFileURL(entry.file.archiveID, entry.file.documentID, entry.file.sysID) | async as file; else loading">
<a target="about:blank" class="download" (click)="clickLink(file)"></a>
</div>
<ng-template #loading let-file>loading..</ng-template>
</div>
</td>
All I want is to display "loading" until the url is loaded and then display the a-tag.
Also, the url parameter coming back from the backend could be empty. So i also need to display nothing if the url is empty ("").
At the moment it fires hundred of backend calls for 2 objects with the entry.file property :(
I am not that good with Observables and I hope someone can help me with that.
Thank you so far :)
You need to return Observable directly from your method and map your period.claims into one Observable:
// add proper type
entries: Observable<...> = getEntries();
getEntries() {
// we map every claim to Observable returned from getFileURL method
const entries = period.claims.map(entry =>
getFileURL(...).pipe(
// we use map to return whole entry from Observable - not only url
map(url => ({
...entry,
url,
}))
));
// forkJoin will return one Observable with value array when each Observable is completed
return forkJoin(...entries);
}
public getFileURL(archiveID: string, documentID: string, sysID: string): Observable<...> {
const request: FileRequest = {
archiveID: archiveID,
documentID: documentID,
sysID: sysID
};
return this.fileService.file(request).pipe(filter(Boolean));
}
If you want not to pass to template empty response you could use filter operator and pass Boolean as callback. It will return only truthy values. You can read more about it: https://www.learnrxjs.io/learn-rxjs/operators/filtering/filter
You can read also more about forkJoin: https://www.learnrxjs.io/learn-rxjs/operators/combination/forkjoin
Note that adding proper type to method would tell you what you're doing wrong ;)

Object users in Observable Angular 8

I created a service and I try call API method (HTTP GET) and I put my data in Observable, I don't understand why I don't see all data(object) from API GET.
angular-component.ts
public allUsers$: Observable<User[]>;
constructor(private usersService: UsersService) { }
ngOnInit() {
this.allUsers$ = this.getAllUsers();
console.log(this.allUsers$)
}
private getAllUsers(): Observable<User[]> {
return this.usersService.getUsers();
}
In console I have this message:
users.service.ts
public getUsers(): Observable<User[]> {
return this.apiService.get(this.type) as Observable<User[]>;
}
api.service.ts
public get(url: string): Observable<any> {
return this.http.get(environment.apiUrl + `/${url}`);
}
nodejs-route.js
app.get("/", async (req, res) => {
const getAllUsers = await User.find().populate("orders.order_id");
res.status(200).send(getAllUsers);
});
Always keep in mind that an Observable does nothing.
As the lead RxJS developer, Ben Lesh, once said:
Observables themselves are enert. They don't stream anything or do
anything. They are templates for streaming/actions/observations that
will be set up on a subscription.
And there are two basic ways to subscribe:
With an async pipe.
Using the subscribe method.
The async pipe in a template AUTOMATICALLY subscribes and unsubscribes for you.
So in your template, you'd have something like this:
<div class="card"
*ngIf="allUsers$ | async as users">
Then you will be able to access users in your template, such as in an *ngFor.
However, using an async pipe makes it a bit more difficult to access the data in your component code. So you can NOT just do this to see your data:
console.log(this.allUsers$)
All that will give you is information on the Observable, as you saw.
The other option is to subscribe in your component:
sub: Subscription
users: User[]
ngOnInit() {
this.sub = this.getAllUsers().subscribe(
users => {
this.users = users;
console.log(users);
);
}
The subscribe() method returns a Subscription that you can then use to manually unsubscribe.
You will then have an array of users User[], NOT an Observable<User[]> as your component property. Your template can then bind to this array.
The first technique (async pipe) is normally the recommended approach.

ANGULAR 6 http get JSON

I am having trouble getting information from certain json file.
case 1 (works):
service:
private xmlToJson: string = 'https://rss2json.com/api.json?rss_url=';
getImg(Url: string) {
return this.http.get(this.xmlToJson + Url);
}
component:
private url='https://api.flickr.com/services/feeds/photos_public.gne';
public images: any = [];
this.imgDataService.getImg(this.url)
.subscribe(data => this.images = data);
HTML:
<h1>{{images.feed.title}}</h1>
case 2 (does not work):
service:
getImg(Url: string) {
return this.http.get(Url);
}
component:
private url = 'https://api.flickr.com/services/feeds/photos_public.gne?format=json&nojsoncallback=1';
public images: any = [];
this.imgDataService.getImg(this.url)
.subscribe(data => this.images = data);
HTML:
<h1>{{images.title}}</h1>
Any idea why case 2 doesn't work? I ran both JSONs here: https://jsonlint.com/ and they came out valid.
You have a CORS error.
Here is a StackBlitz showing the two calls and what is returned from the server. The call for the Flickr URL fails because the Flickr API doesn't (at least on this service) return headers for Access-Control-Allow-Origin to enable public access.
Ironically, you'll be able to call the web service from any code that is not running in a web browser.
Since you probably won't be able to convince them otherwise (others have tried), I would suggest you give up on Flickr.
A final note: You would be able to see the error if you opened your browser's developer tools and checked the console. That should be your first stop for any weird behaviour you encounter in web development.
Change the public images: any = []
to public images: any = {}
Images data isn't an array.
Instead of this.imgDataService.getImg(this.url) type this.imgDataService.getImg(this.url2)
you can try this approach if you know what kind of json response is expected then probably you can create class like
Example:
export class ImageModel{
name:string;
title:string;
src:string;
}
where name,title and src are json keys
then in you can do:
constructor(private httpService:HttpService){}
getImg(Url: string) {
return this.httpService.get<ImageModel>(
(image:ImageModel) => {return image}
}
new HttpService should automatically map your json data to the javascript class/Interface
and then you can read the image to get the json data.

getting json data in realtime angular

I have a URL with data in json format and I get it with the HttpClient and it works good.
I binded the function
showConfig()
to get the data to a button and when pressed I get the newest data.
BUT: I have to click again to get the newest data.
Can I make it refresh automatically, like with Firebase?
url = myURL;
constructor(private http: HttpClient) { }
getConfig() {
return this.http.get(this.url);
}
showConfig(){
this.getConfig().subscribe(data => console.log(data))
}
an

Receiving JSON-Data via http: empty response

I'm new to Angular2 and somehow it's really hard to me to understand how http works in Angular2. I made a simple component which should display a json response. It doesn't work and I have no idea why. I checked many tutorials and tried it with promises as well as observables. Doesn't work. I just can't get the data of the response.
My code:
private doAction() {
this.doHttpRequest().subscribe(
data => this.content = data
);
this.content = JSON.stringify(this.content);
}
private doHttpRequest() {
return this.http.get('http://jsonplaceholder.typicode.com/posts/1')
.catch(this.handleError);
}
this.content is bind to my template. When I click a button to start doAction() for a second I see "" in the template, after another second [object Object]
What is the problem here?
That's the expected behavior
private doAction() {
// schedule HTTP call to server and subscribe to get notified when data arrives
this.doHttpRequest().subscribe(
// gets called by the observable when the response from the server aarives
data => this.content = data
);
// execute immediately before the call to the server was even sent
this.content = JSON.stringify(this.content);
}
To fix it change it to
private doAction() {
this.doHttpRequest().subscribe(
data => {
//this.content = data;
this.content = data.json());
});
);
}
If you want code to be executed after data arrived, then you need to move it inside the subscribe(...) callback.
Since http requests are asynchron you have to put all your logic depending on the results of the http call in the subscribe() callback like this:
private doAction() {
this.doHttpRequest().subscribe(
data => {
this.content = data;
// any more logic must sit in here
}
);
}
private doHttpRequest() {
return this.http.get('http://jsonplaceholder.typicode.com/posts/1')
.map(res => res.json());
.catch(this.handleError);
}
Http call is returning data since it shows "[object Object]" in template. If you want to see the json data in template you can use the json pipe as below.
{{content | json}}
PS: No need of "this.content = JSON.stringify(this.content);" in your code.