Is there any way to bind jsonpath dynamically in angular 6 - json

I am creating a reusable component in which I can pass any dynamic json so he'll able to handle that
what I tried is
mycomponent.html:
<div *ngFor="let Node of items">
{{ Node[getPath()]}}<br>
</div>
mycomponent.ts:
#Input()
path:any;
#Input()
items:any;
getData(){
var String="";
var data=this.path.split('.');
for(var i=0;i<data.length;i++){
if(i==0){
String+="'"+data[i]+"']";
}else if(i+1==data.length){
String+="['"+data[i]+"'";
}
else{
String+="['"+data[i]+"']";
}
}
return String;
}
The output of getData() function is like
'related']['name'
because the reasone is
in mycomponent.html i am using
{{Node[getData()]}}
so basically im trying to do is
{{Node['related']['name']}}
MainComponent.html:
<my-component path="related.name" items={{items}}></my-component>
Input Array
[
{
"related": [
{
"name": "first"
}
]
},
{
"related": [
{
"name": "second"
}
]
}
]
my expected output is like
first
second
I want to create that component as resuable so i can use anywhere in my project so give any suggestion to do that :(

When you create a dynamic component to handle the input JSON.
You could do two ways
Create the component.
mycomponent.html:
mycomponent.ts
mycomponent
#Input()
items:any;
When you integrate the component as any child then you could do as
<mycomponent [items]="items"></mycomponent>
or when you want to invoke as popup
then
let ngModelRef : NgbModalRef = this.ngbModalService.open(mycomponent );
ngModelRef.componentInstance.items= items;
return ngModelRef;

Related

How to add array items to imported model(interface) in Angular

Below is my model and I want to create a request as shown below.
export interface IItemFlow
{
itemId : number;
itemName:string;
}
export class ISaveItemFlowRequest {
itemFlowRequest:IItemFlow[];
userId:number;
}
Imported model in component.ts
import { ISaveItemFlowRequest, IItemFlow} from "../item/model/Iitemflowfile"
Save button click adding items into model by using push() .
this._saveItemFlowRequest.itemFlowRequest.push({itemId:101;itemName:'ABC'});
Error: Cannot read property 'itemFlowRequest' of undefined
My request should generate as follows.
{
"itemFlowRequest": [
{
"itemId": 1,"itemName":"ABC"
},
{
"itemId": 2,"itemName":"xyz"
}
],
"userId": 22
}
You need to initialize the this._saveItemFlowRequest;
this._saveItemFlowRequest: ISaveItemFlowRequest = {itemFlowRequest : [], userId: null}
this._saveItemFlowRequest.itemFlowRequest.push({itemId:101;itemName:'ABC'});
Another aproach is create a class with a constructor that implements ISaveItemFlowRequest

Replace an Url from Json with a button that gives URL to another function

I’m trying to implement a function in my web application, that can discover URLs in a loaded Json via Regular Expressions using angular. Afterwards the URLs get replaced with buttons and when the button gets clicked the exact URL who got replaced gets handed in another function in another component which loads the given URL.
Until now I’m at the point that I can replace the URL of the loaded JSON with a button. I’m using a pipe for that named transform-url.pipe:
import {
Pipe,
PipeTransform,
Input,
Component
} from '#angular/core';
import {
DomSanitizer
} from "#angular/platform-browser";
#Pipe({
name: 'transformUrl',
pure: false
})
export class TransformUrlPipe implements PipeTransform {
constructor(protected sanitizer: DomSanitizer) {}
transform(value: any, ): any {
if (value.match === 0) {
return value;
}
return this.sanitizer.bypassSecurityTrustHtml(
value.replace(/"url:\/\/.*\/.*\/.*"/g, "<button type='button' >Run</button>")
);
}
}
Hmtl:
<h3>Unrecognized JSON data:</h3>
<pre [innerHTML] = "genericJson | transformUrl"></pre>
Sample of Json:
"documentVersion": "1.0",
"documentType": "Urls",
"name": {
"request": {
"version": "1.0",
"abc": [
{
"productUrl": "url://awrtwtgsfgshsfh/sfg/v1/document/jsfhljhl564356lhgljhsljh5895hj",
"attributes": [
{
"attributeSet": {
"attributes": {
"426824828246824828282468248": {
"value": "1"
},
"647474373748648248282824": {
"value": "true"
}
}
}
}
]
},
"productUrl": "url://adgagjfjfjfjhf/sfg/v1/document/adfah5ahfah5jahlkhaliohßjkjlaß73-3",
"attributes": [
{
"attributeSet": {
"attributes": {
"426824828246824828282468248": {
"value": "1"
},
"647474373748648248282824": {
"value": "true"
}
}
}
}
]
},
I found nothing on google on how to do this specific task. Is a pipe even the best solution for this? I tried to implement functions in the pipe but it didnt work.
Another thing that i cant figure out is how i can make every button unique so the application knows which excat URL it should take when the button is clicked? And how can I select the URL and give it in another function in another component?
First of all rather than using pipe, I have created solution in Component only.
Stringify JSON which needs to be get values from. genericJson
Remove first and last ", which is matched in regex.
Using *ngFor, create buttons and pass separate link to click function.
Demo (check console for button click)
EDIT: NEW DEMO.
import { Component } from "#angular/core";
#Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
name = "Angular";
genericJson = { ... some json ... }
formatedOutput: (string | boolean)[] = [];
ngOnInit() {
// adding formatting to make regex search easier
const jsonFormattedString = JSON.stringify(this.genericJson, null, 4);
this.formatedOutput = jsonFormattedString.split('\n');
}
onClick(out: string) {
// do whatever operation on link
const link = out.match(/url:\/\/.*\/.*\/.*/)[0];
console.log(link);
}
urlFound(out: string): boolean {
const match = out.match(/"url:\/\/.*\/.*\/.*"/);
if (match !== undefined && match !== null && match.length > 0) {
return true;
}
return false;
}
}
Use matched links in HTML template,
<div>
<div *ngFor="let out of formatedOutput">
<ng-container *ngIf="urlFound(out); else simple_json"><pre>{{out}}<button (click)="onClick(out)">Link</button></pre></ng-container>
<ng-template #simple_json><pre>{{out}}</pre></ng-template>
</div>
</div>
I think, you should do it like this instead of using pipe:
.html
<button (click)="goTo(genericJson.url)">Run</button>
.ts
genericJson = {
url: "www.google.com"
};
goTo(url: string) {
if (url) {
if (!url.includes("https")) {
url = "https://" + url;
}
window.open(url, "_blank");
}
}

How can I pass json variable to array of objects

im currently working on this project and im facing this error when I try to pass a variable (this.arrayObj) into the composals array.
ngOnInit() {
this.apiService.getComposals().subscribe((res) => {
console.log(res.tpoCampos);
this.arrayObj = res.tpoCampos;
});
}
Im getting the Json content from a Web Service.
export class AppComponent {
title = 'Form';
arrayObj: any;
composals: Composal[] = [
this.arrayObj,
];
}
This is the content from the webservice
{
"m_iPatientID":2,
"tpoCampos":[
{
"m_cColor":"#000000",
"m_cType":"combo",
"m_cOptions":[
"Sim",
"N\u00e3o"
],
"m_cQuestion":"",
"m_cAnswer":"2",
"m_eIdComposant":4443
},
{
"m_cColor":"#000000",
"m_cType":"combo",
"m_cOptions":[
"Sim",
"N\u00e3o"
],
"m_cQuestion":"",
"m_cAnswer":"2",
"m_eIdComposant":4448
}
]
}
How can I pass the json to the composal object inside the variable this.arrayObj?
I think this.arrayObj is already an array of objects, so it could be written like this
composals: Composal[] = this.arrayObj;
export class AppComponent {
title = 'Form';
arrayObj: any;
composals: Composal[] = this.arrayObj;
}

How can I display last property in a JSON object first in the UI

I have a JSON of following format:
[
{Details: [{name: "WII", type:"Video Games", id:"lint"}]
]
however on the UI in a table, I want to display ID first in the first column followed by the others.
Let's assume this is your JS data structure:
let list = [
{ Details: [{ name: "WII", type: "Video Games", id: "lint" }] }
];
Then in your Angular component template:
<table>
<tr *ngFor="let item of list" >
<td>{{item.Details[0].id}}</td>
<td>{{item.Details[0].name}}</td>
<td>{{item.Details[0].type}}</td>
</tr>
</table>
Of course, this is not ideal but to give you a better answer/solution you should provide more information.
You can make use of Pipe to get the keys and reverse it.
import { PipeTransform, Pipe } from '#angular/core';
#Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
transform(value, args:string[]) : any {
let keys = [];
for (let key in value) {
keys.push(key);
}
return keys.reverse();
}
}
STACKBLITZ DEMO

fail reading object type of json

i have an Object type of json that I cant read...
this is my json:
body: {
"111": {
"name": "name1",
"status": 10000
},
"222": {
"name": "name2",
"status": 20000
},
"333": {
"name": "name3",
"status": 30000
}
}
and I want to know how to present it in my html?
this is my attempt:
<md-content>
<h1 align="center">{{title}}</h1>
<h2>list of items:</h2>
<div class="list-bg" *ngFor="#item of items | async">
ID: {{item.name}} <p></p> Number of Items: {{item.status}}
</div>
</md-content>
not only that it dosent work, im trying to figure out how to read each line the object id's(those: 111, 222, 333)
this is my model:
export interface MyModel {
name: string;
status: number;
}
this is my component:
export class MyCmp implements OnInit {
retJson: Observable<MyModel[]>
constructor(private _myService: MyService) {};
public showData(): void {
this.retJson = this._myService.getData();
}
}
thanks!
You haven't included how you load your json, so I'll write a more general example:
interface MyModel {
name: string;
status: number;
}
interface MyResponse {
body: { [id: string]: MyModel }
}
let response: MyResponse = JSON.parse(RESPONSE_STRING);
Object.keys(response.body).forEach(id => {
let model = response.body[id];
console.log(`id: ${ id }, name: ${ model.name }, status: ${ model.status }`);
});
What's missing here is the RESPONSE_STRING, which I'm not sure how you get.
As for the template, I'm not an angular developer but as far as I understand ngFor is used for arrays, and you don't have an array in your json structure.
ngFor loop only will work for array. Your body json is key value object, so it wouldn't work.
If you want to make it work, it's either:
you use an additional pipe to convert key value object to array using pipe, solution discussed here: Iterate over TypeScript Dictionary in Angular 2, then you can use
*ngFor="let item of items | async | mapToIterable"
Or process it in your ts file, instead of
this.retJson = this._myService.getData();, use this._myService.getData().subscribe(x => this.retJson = processToArray(x))