angular getting Observable<HttpEvent<any[]>> inside my html from ts file - html

I have started working on angular again after almost 2 years and i thought i could grasp from my previous knowledge but i am kind of stuck over here and cannot really understand what i can do.
I am using efc for getting data and in services i have the following method
shared-service.ts
getHotelDetails(val:any){
return this.http.get<any>(this.APIUrl+'Hotels/GetHotel/',val);
}
In ts i am getting the correct data by using the below code
mycomponent.ts
hotel$!:Observable<HttpEvent<any[]>>;
constructor(private service:SharedService, private _route:ActivatedRoute) {
}
ngOnInit(): void {
var Id = this._route.snapshot.params['id'];
this.hotel$ = this.service.getHotelDetails(Id);
console.log(this.hotel$);
}
mycomponent.html
I am trying to use the hotel object in html but cannot iterate or find the attributes inside. The api call is giving a json like the below for api:
https://localhost:44372/api/Hotels/GetHotel/1
{
"hotelId": 1,
"name": "pizza",
"addresses": [],
"comments": [],
"hotelFoods": []
}
I just need the code in which i can fetch the name from hotel$ attribute.
I tried ngfor and directly accessing hotel$.id

What you get back from the service is an Observable, you need to subscribe to it in order to access the data. The easiest way to do this in a html template is to use the async pipe.
You need something like this:
{{ (this.hotel$ | async).hotelId }}

Related

Trying to get some position of JSON using Observables

Sorry for the question, but I'm newer in Typescript and Ionic and Im a bit confused about how should I proceed.
I have a JSON file with 150 entries based on an interface I'm declared quite simple:
export interface ReverseWords {
id: number;
todo: string;
solution: string;}
On the other hand, I have a service which reads the json file and returns an Observable of this type (ReverseWords)
getReverseWords() {
return this.http.get<ReverseWords>('/assets/data/reves.json');}
On .ts file, I call the service and I have all the content of the JSON file. What I want to do (and Im not able to do) is get only one entry based on a random position.
On .ts file:
reverseWords: Observable<ReverseWords>; // All the JSON content
reverseWordsSelected: Observable<ReverseWords>; // I would like to get one entry here
On ngOnInit():
this.reverseWords = this.dataservice.getReverseWords();
Everything is fine until here, I've got all the content and I can log it in console. I'm using Observables so I need to subscribe to it to get the information. And I use rxjs/operators pipe and filter to try it, but nothing is showing in the chrome developer console (not even an error).
const reverseWordSelectedByPosition = this.reverseWords.pipe(filter(reverseWord => reverseWord.id === randomPosition));
reverseWordSelectedByPosition.subscribe(console.log);
Could anybody help me and tell me what I'm doing wrong?
Other thing I've tested is to do the following in the service:
getReverseWords() {
return this.http.get<ReverseWords[]>('/assets/data/reves.json');}
And then in the .ts file:
reverseWords: Observable<ReverseWords[]>;
But I have the same problem.
Finally, the most weird thing is that if I write in the .ts file this simple test:
const test = from([
{
id: 1,
todo: 'chapter',
solution: 'r-e-t-p-a-h-c'
},
{
id: 2,
todo: 'claustrofobia',
solution: 'a-i-b-o-f-o-r-t-s-u-a-l-c'
},
{
id: 3,
todo: 'keyboard',
solution: 'd-r-a-o-b-y-e-k'
}
]);
Everything is fine and I can see on the log only 1 entry if I choose 2, for example.
Any help or advice??
Thanks and sorry for the long approach!!
As TotallyNewb suggested, I show an example of the JSON file, with only 3 entries:
[
{
"id": 1,
"todo": "chapter",
"solution": "r-e-t-p-a-h-c"
},
{
"id": 2,
"todo": "claustrofobia",
"solution": "a-i-b-o-f-o-r-t-s-u-a-l-c"
},
{
"id": 3,
"todo": "keyboard",
"solution": "d-r-a-o-b-y-e-k"
}
]
Since you are getting the whole array you can use map
this.reverseWords.pipe(
map((items) => items[Math.floor(Math.random() * items.length)]), // Creates a random index based on the array length
)
.subscribe(console.info);
If you want to pass the result to reverseWordsSelected, you can change it to a Subject and pass the value to it from the subscription of reverseWords with .next().
You can check out this stackblitz for a working example

How to save a JSON-object and use it in another request?

i'm currently trying to set up some JMeter testplans. I am pretty new to this (started a week ago) and don't have much programming experience either, so i hope you could help me in this case.
I already set up some http requests and have some simple JSON Extractor post processors to save some of the variables and use them with the "${variable}" notation.
But now i need to save and modify an object from a response to use that in the next http request.
My respose is a extremely big JSON object and the part im interested in looks something like this:
{
"payload": {
"workspace": {
"resultInstance": [
[{"part": "1"...}],
[{"part": "2"...}],
...
[{"part": "20"...}]
]
}
}
}
Note that for whatever reason these objects {"part":"1"...} are inside a nested array. And they are also pretty big.
I would like to safe those objects in a variable to use them in my next http request which should looks like this:
{
"instanceChange": {
"functionChecks": [
{"part": "1"...},
{"part": "2"...},
...
{"part": "20"...}
]
}
}
So what im really trying to find is a way to save all of the possible objects inside the nested array "resultInstance" and put them inside the non nested array "functionChecks".
I already looked inside the JMeter documentation but because of my poor programming background i cant find a way to realize this.
I think i need something like the JSR223 PostProcessor and "simply go through the resultInstance-array and use smth. like an getObject() on these", but i cant figure out the code i need and if its even possible to safe objects in variables in Jmeter.
Im pretty thankful for every bit of help or advice :).
Thanks in advance,
aiksn
Add JSR223 PostProcessor as a child of the request which returns the JSON response
Put the following code into "Script" area:
def response = new groovy.json.JsonSlurper().parse(prev.getResponseData())
def request = ['instanceChange': ['functionChecks': response.payload.workspace.resultInstance]]
vars.put('request', new groovy.json.JsonBuilder(request).toPrettyString())
That's it, you should be able to refer the generated request body as ${request} where required
More information:
Apache Groovy - Parsing and producing JSON
Apache Groovy - Why and How You Should Use It
let response ={
"payload": {
"workspace": {
"resultInstance": [
[{"part": "1"...}],
[{"part": "2"...}],
...
[{"part": "20"...}]
]
}
}
};
let requestObj={
"instanceChange": {
"functionChecks": [
]
}
};
response.payload.workspace.resultInstance.forEach(myFunction);
myFunction(item, index) {
requestObj.instance.functionsCheck.push(item[0]);
}

Angular 4 dynamic component loading using a json schema

I am in process on creating a small poc to try whether is it possible to load components according to a given json data structure. json will provide and array of component selectors. I tried a small example according to the reference materials i found via online. I used the "componentFactoryResolver" which is recommended way by Angular
I basically create couple of components and registered it with the entrycomponent decorator as follow in my module
entryComponents: [PersonalDetailsComponent, ContactDetailsComponent],
and in my app component i use the following code
#ViewChild('dynamicInsert', { read: ViewContainerRef }) dynamicInsert: ViewContainerRef;
constructor(private componentFactoryResolver: ComponentFactoryResolver) {
}
ngAfterViewInit() {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(PersonalDetailsComponent );
const componentFactory2 = this.componentFactoryResolver.resolveComponentFactory(ContactDetailsComponent);
this.dynamicInsert.clear();
this.dynamicInsert.createComponent(componentFactory);
this.dynamicInsert.createComponent(componentFactory2);
}
and as you see i have to create component for each and every component i use. but having this an inside a loop might not be the best way to do it. i would much appreciate if any one could give me some heads up to do it in a proper way.
my actual json would look like something like this
{
"step":"1",
"viewed":false,
"stepDependant":{
"parentComponent":null,
"childComponent":null,
"varMap":null
},
"widgets":[
{
"Component":"shipper",
"inputs":[
{
"ServiceLine":"Export"
}
],
"outputs":[
],
"name":"Shipper Details"
},
{
"Component":"shipper",
"inputs":[
{
"ServiceLine":"Export"
}
],
"outputs":[
],
"name":"Consignee Details"
},
{
"Component":"status-of-shipment",
"inputs":[
],
"outputs":[
],
"name":"Status of Shipment"
}
]
}
much appreciate your inputs
As you have already found the componentFactoryResolver is the correct way to create components dynamically from code.
With this approach what I would do in your case is create a map or service that maps the component selectors to component types. This way you can then quickly lookup the type when you are creating the dynamic components from the JSON data. From the types you then resolve the factory and then add the components like in your sample.
If you have a predefined set of components that are known another alternative would be to define them all as <ng-template> in the parent component like this:
<ng-template #shipper><shipper ></shipper></ng-template>
<ng-template #statusOfShippment><status-of-shipment ></status-of-shipment></ng-template>
Then you can get the templates in the component by using the #ViewChild decorator.
#ViewChild('shipper')
shipperTemplate: TemplateRef<any>;
#ViewChild('statusOfShippment')
statusOfShippmentTemplate: TemplateRef<any>;
And then you can create the components in a simmilar fashion than with the factory.
this.dynamicInsert.createEmbeddedView(shipper);
this.dynamicInsert.createEmbeddedView(statusOfShippment);
What is good about this approach is that you can still have classic template binding and send a different context object to every template.
<ng-template #shipper><shipper [ServiceLine]="ServiceLine"></shipper></ng-template>
this.dynamicInsert.createEmbeddedView(shipper, {ServiceLine:"Export"});
This way you could directly send an object created from your JSON and configure the component bindings. If you use the component factory you need to set everything from code manually.

TypeScript / Angular 2 creating a dynamic object deserializer

So I am coming from a background of C# where I can do things in a dynamic and reflective way and I am trying to apply that to a TypeScript class I am working on writing.
Some background, I am converting an application to a web app and the backend developer doesn't want to change the backend at all to accommodate Json very well. So he is going to be sending me back Json that looks like so:
{
Columns: [
{
"ColumnName": "ClientPK",
"Label": "Client",
"DataType": "int",
"Length": 0,
"AllowNull": true,
"Format": "",
"IsReadOnly": true,
"IsDateOnly": null
}
],
Rows:[
0
]
}
I am looking to write an Angular class that extends Response that will have a special method called JsonMinimal which will understand this data and return an object for me.
import { Response } from "#angular/http";
export class ServerSource
{
SourceName: string;
MoreItems: boolean;
Error: string;
ExtendedProperties: ExtendedProperty[];
Columns: Column[];
}
export class ServerSourceResponse extends Response
{
JsonMinimal() : any
{
return null; //Something that will be a blank any type that when returned I can perform `object as FinalObject` syntax
}
}
I know StackOverflow isn't for asking for complete solutions to problems so I am only asking what is one example taking this example data and creating a dynamic response that TypeScript isn't going to yell at me for. I don't know what to do here, this developer has thousands of server-side methods and all of them return strings, in the form of a JSON or XML output. I am basically looking for a way to take his column data and combine it with the proper row data and then have a bigger object that holds a bunch of these combined object.
A usage case here after that data has been mapped to a basic object would be something like this.
Example:
var data = result.JsonMinimal() as LoginResponse; <-- Which will map to this object correctly if all the data is there in a base object.
var pk = data.ClientPK.Value;
I'm not exactly sure I understand, but you may want to try a simple approach first. Angular's http get method returns an observable that can automatically map the response to an object or an array of objects. It is also powerful enough to perform some custom mapping/transformation. You may want to look at that first.
Here is an example:
getProducts(): Observable<IProduct[]> {
return this._http.get(this._productUrl)
.map((response: Response) => <IProduct[]> response.json())
.do(data => console.log('All: ' + JSON.stringify(data)))
.catch(this.handleError);
}
Here I'm mapping a json response to an array of Product objects I've defined with an IProduct interface. Since this is just a "lambda" type function, I could add any amount of code here to transform data.

Angular 2 parsing JSON objects into angular classes [duplicate]

This question already has answers here:
How do I initialize a TypeScript Object with a JSON-Object?
(18 answers)
Closed 6 years ago.
I've been following the Angular2 getting started documentation to get my own app off the ground, I've been successful in retrieving JSON objects from a local file and displaying them in angular2 templates. However currently it relies on the angular classes exactly matching the structure of the objects in my JSON file.
Eventually I'll need my app to work with JSON-LD, which has property names such as "#id". I've done some googling and it seems that RxJS might have the functionality I'm looking for but I'm not sure where to start to interupt the automatic binding from some JSON data straight into my angular2 classes, and instead be able to look up something that's labeled as "#id" in the json and set the value of SomeClass.id
Current code that automatically produces an array of a Person class:
getPeople(){
return this._http.get(this._peopleUrl)
.map(response => <Person[]> response.json().data)
.do(data => console.log(data)) //debug to console
.catch(this.handleError);
}
Fine for JSON like this:
[
{
"id":"1",
"name":"tessa"
},
{
"id":"2",
"name":"jacob"
}
]
But it would obviously fail for JSON like this:
[
{
"#id":"1",
"name":"tessa"
},
{
"#id":"2",
"name":"jacob"
}
]
My class is simple (at the moment :-) )
export class Person {
constructor(
public id:number,
public name:string,
){}
}
Can anyone point me in the right direction for some documentation/examples of mapping complex/tricky json to the classes in angular2?
I found the answer in Option 4 of the answer given here: How do I initialize a typescript object with a JSON object
Hope this helps if anyone lands on this page looking for the same thing!