Angular 2 - JSON.stringify() object to show in ag-grid - json

I have ag-grid and from service I get data that i show in grid like this:
My ts code looks like this:
constructor( private codeService: CodeService ) {
this.columnDefs = [
{ headerName: "Name", field: "name"},
{ headerName: "Property", field: "properties", editable: true },
];
}
ngOnInit() {
this.codeService.getCodeType( this.name ).subscribe(
response => { this.handleSuccess( response ); },
error => { console.error( error ); });
}
handleSuccess( aaTypes ) {
var data = [];
aaTypes.forEach( ( aaType ) => {
var entriesForType = [];
entriesForType.push( aaType );
if ( entriesForType.length > 0 ) {
entriesForType.forEach( entry => data.push( entry ) );
this.data = data;
if(this.gridOptions.api !== null){
this.gridOptions.api.setRowData( data );
}
}
});
}
As you can see... properties are actually object and it shows like that in grid on picture one ...My question is, is there any way for me to stringify that "properties" so it will show like string and not object.. Im ok if it shows something like "{location: 0, color; 255}".

Add a valueFormatter to your columnDefs and create the formatter:
constructor( private codeService: CodeService ) {
this.columnDefs = [
{ headerName: "Name", field: "name"},
{ headerName: "Property", field: "properties", valueFormatter: jsonFormatter, editable: true },
];
}
function jsonFormatter(d) {
return JSON.stringify(d);
}

Related

How to show antd multiple select component on this Simple Schema

I have this JSON schema, I tried to populate multiple select component with the uniform autoform.
(() => {
const ajv = new Ajv({ allErrors: true, useDefaults: true, keywords: ["uniforms"] });
const schema = {
title: 'Address',
type: 'object',
properties: {
city: {
type: 'string',
uniforms: {
options: [
{ label: 'New York', value: 'new york' },
{ label: 'Nashville', value: 'nashville' },
],
},
},
}
};
function createValidator(schema) {
const validator = ajv.compile(schema);
return (model) => {
validator(model);
if (validator.errors && validator.errors.length) {
return { details: validator.errors };
}
};
}
const schemaValidator = createValidator(schema);
return new JSONSchemaBridge(schema, schemaValidator);
})()
And the result look like this
Rendered component with this JSON schema
The multiselect component example from antd
could I render multiselect component instead select component (which default from uniform)?
Can I select new york and nashville at the same time?

Recursive rendering of JSON tree with HTML elements (Input, Radio, etc.)

I am quite new to React and working with JSON structures. I am trying to construct a recursive render of a JSON tree structure that dynamically renders individual HTML elements (e.g. radio buttons, dropdown menus, etc.) from the tree. I have seen other implementations, but they do not have nested HTML elements that differ from li, ul, etc. They also do not typically have different naming conventions further down the tree (e.g. attributes, options).
The tree looks like this:
{
"id": "1",
"name": "Animals",
"color": "#e37939",
"shape": "bounding_box",
"attributes": [
{
"id": "1.1",
"name": "Type",
"type": "radio",
"required": false,
"options": [
{
"id": "1.1.1",
"optionName": "Cats",
"optionValue": "cats",
"options": [.... and so on
};
What I ultimately what to achieve is to get to a format where one clicks the 'Animals button', which then renders the nested radio button, and if one selects the 'cats' option value it'd render the next dropdown menu. I have set up an initial set of methods, but I can't quite figure out how to dynamically render the next set of nested options when an option is clicked. I have created a React fiddle here: https://codesandbox.io/s/vigilant-grothendieck-jknym
The biggest challenge is to get the nested recursive options embedded in an options group. I haven't been able to figure out how to do that yet.
I have created a datastructure for what you want to achieve , altho i have tweaked it a bit as there are parts of it redundant but you can still keep both data structure and convert between them.it goes recursively as deep as you want it to go.
const prodList = [
{
id: "1",
name: "Animals",
options: [
{
id: "1.1",
name: "Type",
inputType: "radio",
options: [
{
id: "1.1.1",
name: "Cats",
value: "Cats",
inputType: "select",
options: [
{ id: "1.1.1.1", name: "Siamese Grey", value: "Siamese Grey" },
{ id: "1.1.1.2", name: "Siamese Black", value: "Siamese Black" },
{ id: "1.1.1.3", name: "Siamese Cute", value: "Siamese Cute" },
{ id: "1.1.1.4", name: "House Cat", value: "House Cat" },
{ id: "1.1.1.5", name: "House Cat", value: "House Cat" }
]
},
{ id: "1.1.2", name: "Dogs", value: "Dogs" },
{ id: "1.1.3", name: "Cows", value: "Cows" }
]
}
]
}
];
above is the data structure where you have "inputType" property that helps determining what component to show. we will have a basic component , a radio component and a select component of each type which can render each other inside them.
export default class ProductsPage extends Component {
render() {
let prodItems = prodList.map(p => {
return <MainContentManager data={p} key={p.id} />;
});
return <div>{prodItems}</div>;
}
}
class MainContentManager extends Component {
render() {
let renderObj = null;
renderObj = basicMethod(renderObj, this.props.data);
return (
<div>
<h6> {this.props.data.name}</h6>
{renderObj}
</div>
);
}
}
class RadioButtonManager extends Component {
constructor(props) {
super(props);
this.state = {
activeOptionIndex: 0
};
this.handleInputClick = this.handleInputClick.bind(this);
}
handleInputClick(index) {
this.setState({
activeOptionIndex: index
});
}
render() {
let renderObj = null;
let renderDat = null;
renderDat = this.props.data.options.map((op, index) => {
return (
<label key={op.id}>
<input
type="radio"
onChange={e => {
this.handleInputClick(index);
}}
checked={index == this.state.activeOptionIndex ? true : false}
/>
{op.name}
</label>
);
});
renderObj = basicMethod(renderObj, {
options: [this.props.data.options[this.state.activeOptionIndex]]
});
return (
<div>
<h6> {this.props.data.name}</h6>
{renderDat}
{renderObj}
</div>
);
}
}
class SelectManager extends Component {
constructor(props) {
super(props);
this.state = { value: "", activeOptionIndex: 0 };
this.handleInputClick = this.handleInputClick.bind(this);
}
handleInputClick(value) {
let activeOptionIndex = this.state.activeOptionIndex;
if (this.props.data.options) {
for (let i = 0; i < this.props.data.options.length; i++) {
if (this.props.data.options[i].value == value) {
activeOptionIndex = i;
}
}
}
this.setState({
value: value,
activeOptionIndex: activeOptionIndex
});
}
render() {
let renderObj = null;
let selectOptions = this.props.data.options.map((op, index) => {
return (
<option key={op.value} value={op.value}>
{op.name}
</option>
);
});
renderObj = basicMethod(renderObj, {
options: [this.props.data.options[this.state.activeOptionIndex]]
});
return (
<div>
<select
onChange={e => {
this.handleInputClick(e.target.value);
}}
>
{selectOptions}
</select>
{renderObj}
</div>
);
}
}
function basicMethod(renderObj, data) {
if (data && data.options) {
renderObj = data.options.map(op => {
!op && console.log(data);
let comp = null;
if (op.inputType == "radio") {
comp = <RadioButtonManager data={op} key={op.id} />;
} else if (op.inputType == "select") {
comp = <SelectManager data={op} key={op.id} />;
} else {
comp = <MainContentManager data={op} key={op.id} />;
}
return comp;
});
}
return renderObj;
}
ask anything if it is unclear or you want it a bit different.

Map JSON for Chartjs with Angular 7

Im trying to map JSON Data to show it in a Bar-Chart. The final Array I need has to look like this:[883, 5925, 17119, 27114, 2758].
Actually, the Array I want to use to set the barChartData (dringlichkeitenValues[])seems to be empty. Sorry for my bad coding skills. Can anyone show me how to solve this Problem?
JSON:
[{
"id": 1,
"value": 883
},
{
"id": 2,
"value": 5925
},
{
"id": 3,
"value": 17119
},
{
"id": 4,
"value": 27144
},
{
"id": 5,
"value": 2758
}]
api.service.ts
getDringlichkeiten(): Observable<IDringlichkeit[]> {
return this.http.get<IDringlichkeit[]>(this.ROOT_URL + '/aufenthalte/dringlichkeit');}
dringlichkeit.ts
export interface IDringlichkeit {
id: number;
value: number;
}
bar-chart.component.ts
export class BarChartComponent implements OnInit {
public dringlichkeitValues:number[] = [];
public dringlichkeiten: IDringlichkeit[];
public barChartLabels:String[] = ["1", "2", "3", "4", "5"];
public barChartData:number[] = this.dringlichkeitValues;
public barChartType:string = 'bar';
constructor(private aufenthaltService: AufenthaltService) {
}
ngOnInit() {
this.loadData();
this.getDringlichkeitValues();
}
loadData(){
this.aufenthaltService.getDringlichkeiten()
.subscribe( data => this.dringlichkeiten = data);
}
getDringlichkeitValues(){
let dringlichkeitValues:number[]=[];
this.dringlichkeiten.forEach(dringlichkeit=>{
dringlichkeitValues.push(dringlichkeit.value)
this.dringlichkeitValues = dringlichkeitValues;
});
return this.dringlichkeitValues;
}
}
UPDATE:
I updated my component but now my Array is still empty after subscribing to the Observable.
bar-chart.component.ts
chart: Chart;
dringlichkeiten: IDringlichkeit[] = [];
constructor(private aufenthaltService: AufenthaltService) {
}
ngOnInit() {
this.aufenthaltService.getDringlichkeiten()
.subscribe( data => {
this.dringlichkeiten = data;
//dringlichkeiten-Array full
console.log(this.dringlichkeiten);
});
//dringlichkeiten-Array empty
console.log(this.dringlichkeiten);
this.chart = new Chart('canvas', {
type: 'bar',
data: {
labels: this.dringlichkeiten.map(x => x.id),
datasets: [
{
label: 'Dringlichkeiten',
data: this.dringlichkeiten.map(x => x.value),
backgroundColor: ['#FF6384', '#4BC0C0', '#FFCE56', '#E7E9ED', '#36A2EB']
}
]
},
});
}
To get the "values" from your JSON array, you can use:
dringlichkeiten.map(x => x.value)
This will get you an array you require, i.e.:
[883, 5925, 17119, 27114, 2758]
You can then pass this array to chartJS for it to render you a chart like so:
this.chart = new Chart('canvas', {
type: 'bar',
data: {
labels: dringlichkeiten.map(x => x.id),
datasets: [
{
label: 'My Bar Chart',
data: dringlichkeiten.map(x => x.value),
backgroundColor: ['red', 'green', 'yellow', 'blue', 'orange']
}
]
},
});
Take a look at this simplified working SlackBlitz example.
Hope this helps!

Set nested JSON Response as rowdata to ag-grid in Angular4

I am new to angular and doing a sample project in which I want to show some JSON data in a grid.
I'm using ag-grid for the same.
I have the following Json response that I'm getting from a rest API :-
[
{
"id": 64,
"name": "Utopia",
"language": "English",
"genres": [
"Drama",
"Science-Fiction",
"Thriller"
],
"status": "Ended",
"image": {
"medium": "http://static.tvmaze.com/uploads/images/medium_portrait/0/474.jpg",
"original": "http://static.tvmaze.com/uploads/images/original_untouched/0/474.jpg"
}
},
{
"id": 65,
"name": "Bones",
"language": "English",
"genres": [
"Drama",
"Crime",
"Medical"
],
"status": "Ended",
"image": {
"medium": "http://static.tvmaze.com/uploads/images/medium_portrait/80/201202.jpg",
"original": "http://static.tvmaze.com/uploads/images/original_untouched/80/201202.jpg"
}
}
]
I was able to successfully bind the data for the simple keys like id, name, language etc. but when it comes to binding the nested object I'm not able to do it.
If you look at the above json response, The 'image' field is an object. How can I get the value of 'medium' or 'original' key from it and just show the image in my row ?
Some help is appreciated, as this is the point I'm getting stuck at.
Below is my component code :-
shows.component.ts
#Component({
selector: 'app-shows',
templateUrl: './shows.component.html',
styleUrls: ['./shows.component.css']
})
export class ShowsComponent implements OnInit {
public gridOptions: GridOptions;
public tvShowsColumnDefs = new ShowColumn;
public showMetaData: any;
constructor(private _contentService: ContentService, private _router: Router,
private _route: ActivatedRoute) {
// GridOptions Initialized
this.gridOptions = <GridOptions>{};
this.gridOptions.columnDefs = this.tvShowsColumnDefs.columnDefs;
}
ngOnInit() {
// Prepare Grid Row Data
this.prepareRowData();
}
prepareRowData() {
// API Call for getting TV-Shows
this._contentService.getAllShows()
.subscribe(response => {
const shows = response;
console.log('TVShows-API Response ', shows);
// Setting Grid RowData using api response
this.gridOptions.api.setRowData(shows);
});
}
show.columnDef.ts
export class ShowColumn {
public columnDefs = [
{ field: 'id', headerName: '', width: 50 },
{ field: 'image', headerName: '', width: 50, cellRendererFramework: null},
{ field: 'name', headerName: '', width: 250},
{ field: 'language', headerName: 'Language', width: 100},
{ field: 'genres', headerName: 'Genres', width: 250},
{ field: 'status', headerName: 'Status', width: 145 }
];
constructor() { }
}
The nested properties are accessible by the dot notation (.), e.g.:
{ field: 'image.medium', headerName: '', width: 50}
For the nested arrays, a value-getter will most likely do the job:
function genreValueGetter(params) {
const arr = params.data.genres as Array<string>;
return arr.join(', ');
}
{ headerName: 'Genres', valueGetter: genreValueGetter, width: 250},
First let me build classes:
export class myShow {
image: myImage;
id: number;
...
constructor(obj: any) {
this.document = new myImage(obj.image);
this.id = obj.id;
...
}
}
export class myImage {
medium: string;
original: string;
constructor(obj?: any) {
if(obj){
this.medium = obj.medium;
this.original = obj.original;
}
}
}
Then you can use .map operator
allShows: myShow[] = [];
prepareRowData(){
this._contentService.getAllShows().map((shows: myShow[])=> {
return shows.map((show: myShow)=>{
return new myShow(show);
})
}).subscribe((allShows)=> {
this.allShows = allShows;
});
}

Getting json object data with react

I am attempting to pull data out of json like this, which is imported as "values"
{
"content": {
"person": [
{
"name": "Test"
"age" : "24:
}
]
}
}
I am using .map like below but getting the error .default.map is not a function I believe it is because i have objects not arrays, i've tried a bunch of stuff including object.keys but i'm getting errors all over the place, any direction would be appreciated.
import values from './sample.json'
const vals = values.map((myval, index) => {
const items = person.items.map((item, i) => {
return (
<div>{item.name}</div>
)
})
return (
<div>{items}</div>
)
})
I think your data and code have some errors. But after fixing those and also changing the name from 'person' to 'people' if that's what you are after, here's the code that does what you are trying to do:
var data = {
content: {
people: [
{
name: "Test",
age: 24,
},
{
name: "Foo",
age: 25,
},
],
},
};
var App = React.createClass({
render: function () {
var people = data.content.people.map(function (person) {
return <div>{person.name}</div>;
});
return <div>{people}</div>;
},
});
ReactDOM.render(<App />, document.getElementById("app"));
And here's the JSBin for that: https://jsbin.com/coyalec/2/edit?html,js,output
Update: I'm updating the answer with more detailed example. It now deals with data more generically, like it doesn't assume what are the entries of 'contents' and such, but it knows that each type like 'people' or 'pets' are an array.
var data = {
content: {
people: [
{
name: "Test",
age: 24,
},
{
name: "Foo",
age: 25,
},
],
pets: [
{
name: "Sweety",
age: 3,
},
{
name: "Kitty",
age: 5,
},
],
},
};
var App = React.createClass({
render: function () {
// Get the keys in data.content. This will return ['people', 'pets']
var contentKeys = Object.keys(data.content);
// Now start iterating through these keys and use those keys to
// retrieve the underlying arrays and then extract the name field
var allNames = contentKeys.map((t) =>
data.content[t].map((e) => <div>{e.name}</div>)
);
return <div>{allNames}</div>;
},
});
ReactDOM.render(<App />, document.getElementById("app"));
And here's the latest JSBin: https://jsbin.com/coyalec/4/edit?html,js,output