How to bind rowdata of ag-grid inside gridoption using a httpservice - angular6

I am using ag-grid license edition and want to bring record set to the grid using a service. I am using Ag-Grid gridoption property and initializing rowdata
in the constructor of the component.ts class. But the data is not rendering. No error either. Please have a look of my component.ts class.
Please note: the web api is returning the json data correctly and the service in Angular is tested sucessfully without Ag-Grid
import {Component, OnInit} from "#angular/core";
import {GridOptions} from "ag-grid";
import {RedComponentComponent} from "../red-component/red-component.component";
import { person } from "../Shared/models/person.model";
import {personservice} from '../service/person.service';
#Component({
selector: 'app-my-grid-application',
templateUrl: './my-grid-application.component.html'
})
export class MyGridApplicationComponent implements OnInit{
private gridOptions: GridOptions;
private persons: person[];
constructor(private personservice: personservice) {
this.gridOptions = <GridOptions>{};
this.gridOptions.columnDefs = [
{
headerName: "ID",
field: "PersonId",
width: 100
},
{
headerName: "Name",
field: "PersonNm",
cellRendererFramework: RedComponentComponent,
width: 100
},
{
headerName: "Email",
field: "PersonEmail",
cellRendererFramework: RedComponentComponent,
width: 100
}
];
this.gridOptions.rowData = this.persons
}
ngOnInit() {
this.personservice.findAll().subscribe(
persons => {
this.persons = persons
},
error => {
console.log(error);
}
)
}
}

Instead of providing columnDefs and rowData with gridOptions, try providing them directly like this.
<ag-grid-angular
[gridOptions]="gridOptions"
[rowData]="rowData"
[columnDefs]="columnDefs"
>
</ag-grid-angular>
Also, declare columnDefs and rowData as component variables, and then assign them after getting the response.
rows: any[] = [];
columnDefs: ColDef[];
constructor(private personservice: personservice) {
this.gridOptions = <GridOptions>{};
this.columnDefs = [
// your column definition goes here
];
}
ngOnInit() {
this.personservice.findAll().subscribe(
persons => {
this.rows = persons
},
error => console.log(error)
)
}
Let me know if you face any issue after this.

Related

Parsing JSON Data working only for template(HTML) but not for Component Class(Typescript)

I would like to parse a json file to use, and extract data.
I don't know why the data extracted from my code work only for my html, but is empty for my typescript code...
json file to parse :
[
{
"appleWatch": "generation_3",
"bracelets": ["model_1","model_2","model_3"]
},
{
"appleWatch": "generation_4",
"bracelets": ["model_1","model_4","model_5"]
}
]
Typescript of my component:
export class AppleKitComponent implements OnInit {
constructor(private httpService: HttpClient) {}
arrAppleWatch: AppleWatchModel[] = [];
selectedWatch: AppleWatchModel = null;
url = '../../assets/json/appleKit.json';
ngOnInit() {
this.arrAppleWatch = this.parseAppleWatchData();
console.log(this.arrAppleWatch.toString() + 'test');
}
parseAppleWatchData() {
this.httpService.get('../../assets/json/appleKit.json').subscribe(
data => {
this.arrAppleWatch = data as AppleWatchModel[]; // FILL THE ARRAY WITH DATA.
},
(err: HttpErrorResponse) => {
console.log(err.message);
}
);
return this.arrAppleWatch;
}
}
My appleWatch model :
export class AppleWatchModel {
constructor(
public watch: string,
public bracelets?: string[],
public bracelet?: string
) {
}
}
HTML:
{{arrAppleWatch |json }}
My log should output :
[ { "appleWatch": "generation_3", "bracelets": [ "model_1", "model_2", "model_3" ] }, { "appleWatch": "generation_4", "bracelets": [ "model_1", "model_4", "model_5" ] } ]
but it just prints an empty string.
My html work and show the array :
[ { "appleWatch": "generation_3", "bracelets": [ "model_1", "model_2", "model_3" ] }, { "appleWatch": "generation_4", "bracelets": [ "model_1", "model_4", "model_5" ] } ]
There are a few issues with your implementation.
The httpService.get call call would be an async call. So it won't give you the data instantly. But you're trying to access it instantly. Hence you're not getting it in the Component Class.
Give this a try:
import { Component } from '#angular/core';
import { HttpClient, HttpErrorResponse } from '#angular/common/http';
export interface AppleWatchModel {
watch: string;
bracelets?: string[];
bracelet?: string;
};
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(private httpService: HttpClient) {
}
arrAppleWatch: AppleWatchModel[] = [];
selectedWatch: AppleWatchModel = null;
ngOnInit() {
this.parseAppleWatchData()
.subscribe(res => {
this.arrAppleWatch = res;
console.log('test: ', this.arrAppleWatch);
});
}
parseAppleWatchData() {
return this.httpService.get<AppleWatchModel[]>('/assets/appleKit.json');
}
}
Here, we're returning an Observable<AppleWatchModel[]> from parseAppleWatchData. So we can subscribe to it in the ngOnInit to get the actual data.
Here's a Working Sample StackBlitz for your ref.
Your output is empty because you don't take the asynchronous nature of http requests into account. parseAppleWatchData is returned with the original arrAppleWatch value (which is []) before the http response is received. If you add some logs you will see B comes before A. You can also remove the return value.
export class AppleKitComponent implements OnInit {
constructor(private httpService: HttpClient) {
}
arrAppleWatch: AppleWatchModel [] = [];
selectedWatch: AppleWatchModel = null;
url = '../../assets/json/appleKit.json';
ngOnInit() {
this.parseAppleWatchData();
log('B', this.arrAppleWatch);
}
parseAppleWatchData() {
this.httpService.get('../../assets/json/appleKit.json').subscribe(
data => {
this.arrAppleWatch = data as AppleWatchModel []; // FILL THE ARRAY WITH DATA.
console.log('A', data);
},
(err: HttpErrorResponse) => {
console.log(err.message);
}
);
}

Angular: Parsing fetched data from firebase with 2 deep level

I'm trying to parse fetched data from firebase at Angular (Typescript).
My JSON data looks like this in firebase:
"customer" : {
"customerId1" : {
"documents" : {
"documentId1" : {
"documentName" : "file1.pdf",
"documentUrl" : "someUrl1"
},
"documentId2" : {
"documentName" : "file2.pdf",
"documentUrl" : "someUrl2"
}
},
"email" : "customet1#email.com",
"name" : "Customer 1",
},
"customerId2" : {
"documents" : {
"documentId3" : {
"documentName" : "file3.pdf",
"documentUrl" : "someUrl3"
},
"documentId4" : {
"documentName" : "file4.pdf",
"documentUrl" : "someUrl4"
}
},
"email" : "customer2#email.com",
"name" : "Customer 2",
}
}
As you can see, each customer has 3 properties, documents, email and name at the first level. At the second level, the document property has nested property documentName and documentUrl.
And for parsing customer data I used the following code.
customer.component.ts:
...
export class CustomerComponent implements OnInit {
customerObservable: Observable<any[]>;
customerList: Customer[];
constructor(db: AngularFireDatabase) {
// Listen to customer data
this.customerObservable.subscribe(data => {
this.customerList = data;
});
}
}
...
With this code I can fetch and iterate data with the ngFor directive at html with customerList variable. The question is, how can I achieve something like this?
// Variable that contains array of an array of customer's document array
documentList: Document[][];
// Or this
// Variable that holds customer's documents
customerDocuments: Document[];
// Where Document model looks like this
export class Document {
public documentName: string;
public documentUrl: string;
}
Thank you for the support.
Here is the service code:
import {Injectable} from '#angular/core';
import {AngularFireDatabase} from 'angularfire2/database';
//rxJS
import {Observable} from 'rxjs/Observable';
import 'rxjs/operator/switchMap';
#Injectable()
export class FirebaseService {
constructor(private angularFireDatabase: AngularFireDatabase) {}
onGetUserDocuments(customer: string) {
return this.angularFireDatabase.list(`customer/${customer}/documents`).valueChanges()
}
onGetUsersDocuments(){
return this.angularFireDatabase.list('customer').snapshotChanges()
.map((changes)=>{
return changes.map((data) => {
return data.payload.key
});
})
.switchMap((usersId: string[]) => {
return Observable.combineLatest( usersId.map((u)=>{
return this.onGetUserDocuments(u);
}))
})
}
}
Then in your component you can call:
import {Component, OnInit} from '#angular/core';
import {FirebaseService} from '../services/firebase.service';
#Component({
selector: 'new',
templateUrl: './new.component.html',
styleUrls: ['./new.component.css']
})
export class NewComponent implements OnInit {
constructor(private firebaseService: FirebaseService) {}
ngOnInit(){
this.firebaseService.onGetUsersDocuments().subscribe(data => console.log(data));
}
}
That will give you:
[Array(2), Array(2)]
0: Array(2)
0: {documentName: "file1.pdf", documentUrl: "someUrl1"}
1: {documentName: "file2.pdf", documentUrl: "someUrl2"}
1: Array(2)
0: {documentName: "file3.pdf", documentUrl: "someUrl3"}
1: {documentName: "file4.pdf", documentUrl: "someUrl4"}
So you can use it like so:
<div *ngFor="let docs of data">
<div *ngFor="let doc of docs">
<p>file name: {{doc.documentName}}</p>
<p>file url: {{doc.documentUrl}}</p>
</div>
</div>
Let me know if you will need any comments thought the code or will have any questions.
P.S. What you really have to now that nesting like this is not recommended by firebase, you should flaten you data. You can read about this here
new docs and here old docs

Send data with router link

I'm trying to passing the data from one page to another routing page using [queryParams]="{'usd':usd, 'count' :country, 'name' :name}" from the routing button. it's perfectly working but there is an error in my console.
ERROR in src/app/hairstylist-profile/hairstylist-profile.component.ts(18,40): error TS2339: Property 'value' does not exist on type 'Observable<Params>'.
src/app/hairstylist-profile/hairstylist-profile.component.ts(20,42): error TS2339: Property 'value' does not exist on type 'Observable<Params>'.
src/app/hairstylist-profile/hairstylist-profile.component.ts(22,41): error TS2339: Property 'value' does not exist on type 'Observable<Params>'.
this is my code:
import {Component, OnInit} from '#angular/core';
import {ActivatedRoute} from '#angular/router';
#Component({
selector: 'app-hairstylist-profile',
templateUrl: './hairstylist-profile.component.html',
styleUrls: ['./hairstylist-profile.component.css'],
})
export class HairstylistProfileComponent implements OnInit {
name;
usd;
count;
constructor(private route: ActivatedRoute) {
}
ngOnInit() {
const usd = this.route.queryParams.value.usd;
this.usd = usd;
const count = this.route.queryParams.value.count;
this.count = count;
const name = this.route.queryParams.value.name;
this.name = name;
}
}
there is an error in value keyword. So how can solve?
This may Help you
ngOnInit() {
this.route
.queryParams
.subscribe(params => {
// Defaults to 0 if no query param provided.
this.usd = params['usd'] || 0;
this.count = params['count'] || 0;
this.name = params['name'] || ';
});
}
You cannot use .value,you must subscribe query parmas
UPDATE 4.0.0
See Angular docs for more details https://angular.io/guide/router#fetch-data-before-navigating
ORIGINAL
Using a service is the way to go. In route params you should only pass data that you want to be reflected in the browser URL bar.
See also https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service
The router shipped with RC.4 re-introduces data
constructor(private route: ActivatedRoute) {}
and ..
const routes: RouterConfig = [
{path: '', redirectTo: '/heroes', pathMatch : 'full'},
{path : 'heroes', component : HeroDetailComponent, data : {some_data : 'some value'}}
];
and ..
class HeroDetailComponent {
ngOnInit() {
this.sub = this.route
.data
.subscribe(v => console.log(v));
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}
See also the Plunker at https://github.com/angular/angular/issues/9757#issuecomment-229847781

How to get values from JSON webservice with 2 objects in Angular 2

I'm new in Angular 2 and I'm quite lost. I have a JSON web service responding to /rest/alertsDashboard. It returns something like:
{
"total": {
"totalOperations": 2573,
"totalOperationsAlert": 254,
"totalOperationsRisk": 34
},
"alerts": [
{
codAlert: "L1",
description: "Alert 1",
value: 1
},
{
codAlert: "L2",
description: "Alert 2",
value: 2
},
...
]
}
So I defined a DashboardComponent component and a AlertDashboardService service. I would like, for example, to display totalOperations and totalOperationsAlert. I don't know if I'm doing it in a correct way.
In dashboard.component.ts I have:
...
#Component({
selector: 'app-dashboard',
template: `
<p>{{totalAlertsDashboard.totalOperations}}</p>
<p>{{totalAlertsDashboard.totalOperationsAlert}}</p>
...
`
})
export class DashboardComponent implements OnInit {
totalAlertsDashboard: TotalAlertsDashboard;
alertsDashboard: AlertDashboard[];
constructor(private alertsDashboardService: AlertsDashboardService) { }
ngOnInit() {
this.alertsDashboardService.get().then(
response => {
this.totalAlertsDashboard = response.totalAlertsDashboard;
this.alertsDashboard = response.alertsDashboard;
}
);
}
}
In alerts-dashboard.service.ts I have:
...
export class AlertsDashboard {
totalAlertsDashboard: TotalAlertsDashboard;
alertsDashboard: AlertDashboard[];
}
export class TotalAlertsDashboard {
totalOperations: number;
totalOperationsAlert: number;
totalOperationsRisk: number;
}
export class AlertDashboard {
codAlert: string;
description: string;
value: number;
}
#Injectable()
export class AlertsDashboardService {
private headers = new Headers({ 'Content-Type': 'application/json' });
private url = environment.urlAPI + '/rest/alertsDashboard';
constructor(private http: Http) { }
get(): Promise<AlertsDashboard> {
var vm = this;
let params = new URLSearchParams();
return vm.http.get(vm.url, { search: params })
.toPromise()
.then(response => {
var responseJson: AlertsDashboard = response.json() ;
console.log(responseJson); // it prints the JSON correctly
return responseJson;
});
}
}
I hope you can help me with that.
try this :
ngOnInit() {
this.alertsDashboardService.get().then(
response => {
this.totalAlertsDashboard = response.total;
this.alertsDashboard = response.alerts;
}
);
}
In alerts-dashboard.service.ts
export class AlertsDashboard {
total: TotalAlertsDashboard;
alerts: AlertDashboard[];
}
template :
<p>{{totalAlertsDashboard?.totalOperations}}</p>

How can I sanitize css properties to use in template given from a data service

I need to generate sanitized css property to use with my component template to set the background image of the div:
<div *ngFor="let Item of Items"
[style.background-image]="Item.imageStyle
(click)="gotoDetail(Item.iditems)">
</div>
using data obtained through a data service. The component is:
import { Component } from '#angular/core';
import { Router } from '#angular/router';
import { DomSanitizer } from '#angular/platform-browser';
import { OnInit } from '#angular/core';
import { Item } from '../models/Item';
import { CollectionDataService } from '../services/CollectionData.service';
#Component({
selector: 'mainpage',
templateUrl: 'app/mainpage/mainpage.component.html',
styleUrls: ['app/mainpage/mainpage.component.css']
})
export class MainpageComponent implements OnInit {
Items: Item[];
ngOnInit() {
this.collectionDataService.getItems().subscribe(
Items => this.Items = Items
);
// Generates and sanitizes image links
this.Items.map(
(LItem) => LItem.imageStyle = this.sanitizer.bypassSecurityTrustStyle("url(template/images/"+LItem.iditems+".jpg)")
)
}
constructor(
private router: Router,
private sanitizer: DomSanitizer,
private collectionDataService: CollectionDataService
) {
}
gotoDetail($iditems: number): void {
this.router.navigate(['/viewer', $iditems]);
}
}
But it doesn't work because the statement that generates the sanitized property
this.Items.map(
(LItem) => LItem.imageStyle = this.sanitizer.bypassSecurityTrustStyle("url(template/images/"+LItem.iditems+".jpg)")
)
doesn't find the loaded data. The error that I'm seeing in the browser console is:
core.umd.js:3070 EXCEPTION: Uncaught (in promise): Error: Error in ./MainpageComponent class MainpageComponent_Host - inline template:0:0 caused by: Cannot read property 'map' of undefined
TypeError: Cannot read property 'map' of undefined
The data service is:
import { Injectable } from '#angular/core'
import { Http } from '#angular/http'
import { Item } from '../models/Item';
import { DomSanitizer } from '#angular/platform-browser';
#Injectable()
export class CollectionDataService {
constructor(
private http: Http,
private sanitizer: DomSanitizer
) { }
getItems() {
return this.http.get('app/mocksdata/items.json').map(
response => <Item[]>response.json().items
)
}
}
And the provided items.json:
{
"items": [{
"iditems": 1,
"imageStyle": ""
}, {
"iditems": 2,
"imageStyle": ""
}]
}
If I set static data in the component, instead of using the data service, everything works:
export class MainpageComponent implements OnInit {
Items: Item[];
ngOnInit() {
this.Items = [{
"iditems": 1,
"imageStyle": ""
}, {
"iditems": 2,
"imageStyle": ""
}]
// Generates and sanitizes image links
this.Items.map(
(LItem) => LItem.imageStyle = this.sanitizer.bypassSecurityTrustStyle("url(template/images/"+LItem.iditems+".jpg)")
)
}
How can I force the sanitizer statement to wait that the async data are fully loaded? Alternatively how can I generate sanitized properties directly in the service?
EDIT
The best answer comes from PatrickJane below:
Items: Item[] = [];
ngOnInit() {
this.collectionDataService.getItems().subscribe(Items => {
this.Items = Items;
this.Items.map(LItem => LItem.imageStyle = this.sanitizer.bypassSecurityTrustStyle("url(template/images/"+LItem.iditems+".jpg)"))}
});
}
I also solved this problem working directly in the service method (credits), but it is more verbose:
return this.http.get('app/mocksdata/items.json')
.map( (responseData) => {
return responseData.json().items;
})
.map(
(iitems: Array<any>) => {
let result:Array<Item> = [];
if (iitems) {
iitems.forEach((iitem) => {
iitem.imageStyle = this.sanitizer.bypassSecurityTrustStyle("url(template/images/"+iitem.iditems+".jpg)");
result.push(<Item>iitem);
});
}
return result;
}
)
The subscribe function is async so your map function called before the subscribe function run. So in this phase the array is undefined because you doesn't set any initial value.
The solution is to do this inside the subscribe function and to initialize the Items with empty array.
Items: Item[] = [];
ngOnInit() {
this.collectionDataService.getItems().subscribe(Items => {
this.Items = Items;
this.Items.map(LItem => LItem.imageStyle = this.sanitizer.bypassSecurityTrustStyle("url(template/images/"+LItem.iditems+".jpg)"))}
});
}