How to pass json data to Class variable in Angular? - javascript

I have a class Projects
export class Projects {
project_id: number;
project_name: string;
category_id: number;
project_type: string;
start_date: Date;
completion_date: Date;
working_status: string;
project_info: string;
area: string;
address: string;
city: string;}
Its Service class is
#Injectable()
export class ProjectsService {
constructor(private http: HttpClient) {}
//http://localhost:9090/projectInfo
private apiUrl = 'http://localhost:9090/projectInfo';
public findAll() {
return this.http.get(this.apiUrl);
}
getProducts(): Observable<ProjectsModule[]> {
return this.http.get<ProjectsModule[]>(this.apiUrl);
}
Component is
import { Component, OnInit } from '#angular/core';
import { ProjectsService } from '../projects.service';
import{Projects} from '../projects';
import { plainToClass, Transform, Expose, Type, Exclude } from 'class-transformer';
#Component({
selector: 'app-project-list',
templateUrl: './project-list.component.html',
styleUrls: ['./project-list.component.css'],
providers: [ProjectsService]
})
export class ProjectListComponent implements OnInit {
private projects:Projects[]=[];
stringObject: any;
constructor(
private projectsService: ProjectsService) { }
vandana='rahul';
ngOnInit() {
this.getAllProjects();
}
getAllProjects() {
this.projectsService.getProducts().subscribe((data: Projects[])=> {
this.stringObject =JSON.stringify(data)
let newTodo = Object.assign(new Projects(), data);
this.projects= <Projects[]>this.stringObject;
console.log("data -"+ this.projects)
console.log("Array -"+ this.stringObject)
console.log("data -"+ this.projects[1].project_info)
},
err => {
console.log(err);
}
);
}
When i am trying to read newTodo.project_id (or any property of class Projects) it is undefined
but newtodo is returning jsondata
output is
Please help me in getting values newtodo.project_id, newtodo.project_name and so on

You're assigning a JSON string to this.projects.
The JSON string is [{"projectId": 1, ... }].
So:
this.projects[1] evaluates to { (i.e. the second character in the string)
"{".project_id evaluates to undefined
You should assign the data itself to this.projects:
this.projects = data;
And then keep in mind that arrays in JavaScript are zero-based. Since you only have one object in your array, you'd have to print the projectId as follows:
console.log(this.projects[0].projectId);
Also, the properties of your Projects class don't match your JSON at all. Furthermore, Projects should probably be named Project, and should be an interface instead of a class.

Related

Error returning an array of objects from an Angular function

Good afternoon, I have a problem when I want to return an array of objects from an external function.
I have declared an Object class with 2 properties, its constructor and one that works where I return an array with more than 50 objects for this example I only put 4 objects
export class Object {
formcontrolName: String;
formcontrolTraducido: String;
constructor(formcontrolName: String, formcontrolTraducido: String) {
this.formcontrolName = formcontrolName;
this.formcontrolTraducido = formcontrolTraducido;
}
getData() {
return [
{ formcontrolName: 'callId', formcontrolTraducido: 'CId' },
{ formcontrolName: 'collegeCareerId', formcontrolTraducido: 'Carrera' },
{
formcontrolName: 'collegeDepartmentId',
formcontrolTraducido: 'Nombre del Departamento/Centro',
},
{
formcontrolName: 'detailedAreaKnowledgeId',
formcontrolTraducido: 'Campo Detallado',
},
];
}
}
The problem is that I want to call from another component the getData function of the Object class, but when returning I get the following error:
Type '() => { formcontrolName: string; formcontrolTraducido: string; }[]' is missing the following properties from type 'Object[]': pop, push, concat, join
import { Component, OnInit } from '#angular/core';
import { Object } from './object';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
data: Object;
arrayData: Object[];
constructor() {}
ngOnInit() {
this.arrayData = this.data.getData;
console.log('arrayData: ' + this.arrayData);
}
}
stackblitz example code
I am new to angular and to working with arrays, I would like to know what I can do to solve my problem. Thank you very much
First of all the type for the property arrayData is not of type Object which is the class that you're using, so a more proper type would be the same as the one that is returned by the method getData.
You can get its return type by using the typescript helper type ReturnType, so a good way to type this would be like:
arrayData: ReturnType<Object['getData']>;
One recommendation that I have is not to use the name Object for a class, since it has the same name as Object a javascript builtin.
After that the problem that you have here:
ngOnInit() {
this.arrayData = this.data.getData();
console.log('arrayData: ' + this.arrayData);
}
Is that you are assigning a method to a variable that expects an array of something, that's why you get the error:
Type '() => { formcontrolName: string; formcontrolTraducido: string; }[]' is missing the following properties from type 'Object[]': pop, push, concat, join
You just need to call the method like:
this.arrayData = this.data.getData();
With that all in mind the final code would look like:
import { Component, OnInit } from '#angular/core';
import { Object } from './object';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
name = 'Angular';
data: Object;
arrayData: ReturnType<Object['getData']>;
constructor() {}
ngOnInit() {
this.arrayData = this.data.getData();
console.log('arrayData: ' + this.arrayData);
}
}

Why won't my array display correctly with Angular?

I'm trying to display data using a parent to child relationship with Angular, however I am having issues and am not sure why. I'm trying to display an array of Employee objects, but when I run the webpage on localhost, it displays it as:
[object Object]
[object Object]
[object Object]
[object Object]
[object Object]
The goal is to inject an Employee service into my EmployeeList componet (parent) and display it using DisplayEmployee (child) component. I can see the data I want being passed through in the console, but not on the webpage. How can I fix this issue, and why does it not recognize the data I'm trying to pass through?
Employee class:
export class Employee {
private _firstName: string;
private _lastName: string;
private _salary: number;
private _department: string;
constructor(firstName: string, lastName: string, salary: number, department: string) {
this._firstName = firstName;
this._lastName = lastName;
this._salary = salary;
this._department = department;
}
get firstName(): string {
return this._firstName;
}
get lastName(): string {
return this._lastName;
}
get salary(): number {
return this._salary;
}
get department(): string {
return this._department;
}
}
Employee Service:
import { Injectable } from '#angular/core';
import {Employee} from "./employee";
#Injectable({
providedIn: 'root'
})
export class EmployeeService {
private _employees: Employee[];
constructor() {
this._employees = [];
this.populateEmployees();
}
private populateEmployees(): void {
this._employees.push(new Employee("Kyle", "Ryan", 250_000, "Management"));
this._employees.push(new Employee("John", "Smith", 50_000, "Human Resources"));
this._employees.push(new Employee("Nicole", "Berg", 200_000, "Management"));
this._employees.push(new Employee("Bryan", "Jones", 90_000, "Customer Support"));
this._employees.push(new Employee("Sarah", "Little", 50_000, "Customer Support"));
}
get employees(): Employee[] {
return this._employees;
}
}
EmployeeList component (parent):
import { Component, OnInit } from '#angular/core';
import {EmployeeService} from "../services/employee.service";
#Component({
selector: 'app-employee-list',
templateUrl: './employee-list.component.html',
styleUrls: ['./employee-list.component.css']
})
export class EmployeeListComponent implements OnInit {
private _allEmployees: any;
constructor(private employeeService: EmployeeService) { }
ngOnInit(): void {
this._allEmployees = this.employeeService.employees;
}
get allEmployees(): any {
return this._allEmployees;
}
}
DisplayEmployee component (child):
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'app-display-employee',
templateUrl: './display-employee.component.html',
styleUrls: ['./display-employee.component.css']
})
export class DisplayEmployeeComponent implements OnInit {
#Input() list: any = "";
constructor() { }
ngOnInit(): void {
}
}
EmployeeList component template:
<app-display-employee [employeeList]=allEmployees></app-display-employee>
DisplayEmployee component template:
<div>
<table>
<tr *ngFor="let emp of employeeList;">
<td>{{ emp }}</td>
</tr>
</table>
</div>
You can display the employee objects using json pipe as following:
<td>{{ emp | json}}</td>

I am getting '[object Object]' from service to component using Angular

Please help on the below issue this is my model class. I tried all the possible ways using .pipe.map() import {map} from rxjs/operators method, but still giving [object Object]
export class AppProfilesDetailsDO {
envName?: string;
envDesc?: string;
envIpAddress?: string;
envProfileName?: string;
envCrDeployed?: string;
envUrl?: string;
envAdminConsoleUrl?: string;
envDbSchema?: string;
envDbUserId?: string;
envGisSchema?: string;
envPortNo?: number;
}
my component class
import { Component, OnInit } from '#angular/core';
import { ProfileserviceService } from './profileservice.service';
import { AppProfilesDetailsDO } from '../models/AppProfilesDetailsDO';
#Component({
selector: 'app-profiledetails',
templateUrl: './profiledetails.component.html',
styleUrls: ['./profiledetails.component.css']
})
export class ProfiledetailsComponent implements OnInit {
appProfileData: AppProfilesDetailsDO[];
constructor(private profileService: ProfileserviceService) { this.appProfileData = [] }
ngOnInit() {
console.log("In profiledetails component");
this.profileService.getProfileSetUpDetails().subscribe(
appProfileData => {
this.appProfileData = appProfileData;
}
);
console.log("Compenent Profile Data: "+this.appProfileData); ==> **in my console it is
printing as ==> [object Object] **
}
}
My service component
import { HttpClient } from "#angular/common/http";
import { Injectable } from "#angular/core";
import { Observable } from "rxjs";
import { AppProfilesDetailsDO } from "../models/AppProfilesDetailsDO";
#Injectable({
providedIn: 'root'
})
export class ProfileserviceService {
BASE_PATH:string = "http://localhost:8080/getProfileSetUpDetails";
constructor(private httpClient: HttpClient) {}
httpOptions = {
headers: new Headers ({
'Content-type': 'application/json'
})
}
appProfileData?: AppProfilesDetailsDO[];
getProfileSetUpDetails() : Observable<AppProfilesDetailsDO[]> {
return this.httpClient.get<AppProfilesDetailsDO[]>(this.BASE_PATH);
}
}
I am not sure where it is wrong. Please help on this issue.
Thanks.
The problem is this line console.log("Compenent Profile Data: "+this.appProfileData);. You are trying to concatenate an object with a string.
Simply change that line to console.log("Compenent Profile Data: ", this.appProfileData);
For more clarity look at this example:
var data = { a: "ali" };
console.log("Compenent Profile Data: " , data); console.log("Compenent Profile Data: " + data);
If you want to see the result it should be like this
console.log("Component Profile Data:", this.appProfileData);
other ways it will try to log the concatenated value of string with the result object which is impossible
You can not impose concatenation in between string and an array of object as you did like this:
console.log("Compenent Profile Data: "+this.appProfileData);
So, just use like this instead and problem will be gone:
console.log(this.appProfileData);

Angular 5 - HTTP Client - converting resp.body to Array

I am trying to get my JSON response from the HttpClient service into an array so that I can loop through using *ngFor in my html. I've tried using "this" to loop through but *ngFor will not accept it. Below is the code for my service.ts component and the main component.ts.
I just need some way to convert an array from "resp.body" into an exportable Array to be used for string interpolation in the html. Any help would be much appreciated!
races.component.ts
import { Component, OnInit } from '#angular/core';
import {Race, RacesService} from './races.service';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'dh-races',
templateUrl: './races.component.html',
providers: [ RacesService ],
styleUrls: ['./races.component.scss']
})
export class RacesComponent {
error: any;
headers: string[];
race: Race;
raceM: any[];
constructor(private racesService: RacesService) {
var raceM = [];
var raceArray = [];
this.racesService.getRaceResponse()
.subscribe(resp => {
raceArray.push(resp.body);
for (let obj of raceArray) {
for (let i in obj) {
raceM.push({
"ID": obj[i].id + ",",
"Date": obj[i].activityStartDate,
"RaceName": obj[i].assetName,
"Website": obj[i].website
})
}
console.log(raceM);
return raceM;
}
});
}
races.service.ts
#Injectable()
export class RacesService {
constructor(private httpClient: HttpClient) { }
getRace() {
return this.httpClient.get(activeApiURL).pipe(
retry(3),
catchError(this.handleError)
);
}
getRaceResponse(): Observable<HttpResponse<Race>> {
return this.httpClient.get<Race>(
activeApiURL, {
observe: 'response'
});
}
To fix the issue, you need to create an interface that matches the data you get from the server, I will call this interface IRace.
Then in the component I will create a variable named races, I will assign the returned value from the server response i.e. resp.body to the races variable.
I'd change the service to look like this:
export interface IRace {
// Your response from server object's properties here like so:
id: Number;
assetName: string;
...
}
export class RacesService {
constructor(private httpClient: HttpClient) { }
getRace() {
return this.httpClient.get(activeApiURL).pipe(
retry(3),
catchError(this.handleError)
);
}
getRaceResponse(): Observable<HttpResponse<Array<Race>>> {
return this.httpClient.get<Array<Race>>(
activeApiURL, {
observe: 'response'
});
}
}
Finally, I'd change the race component to this:
import { Component, OnInit } from '#angular/core';
import { Race, RacesService, IRace } from './races.service';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'dh-races',
templateUrl: './races.component.html',
providers: [ RacesService ],
styleUrls: ['./races.component.scss']
})
export class RacesComponent {
error: any;
headers: string[];
races: IRace[];
constructor(private racesService: RacesService) {
this.racesService.getRaceResponse()
.subscribe(resp => {
this.races = resp.body;
});
}
}
I hope this helps.

Angular 2 access parent routeparams from child component [duplicate]

How do I get the RouteParams from a parent component?
App.ts:
#Component({
...
})
#RouteConfig([
{path: '/', component: HomeComponent, as: 'Home'},
{path: '/:username/...', component: ParentComponent, as: 'Parent'}
])
export class HomeComponent {
...
}
And then, in the ParentComponent, I can easily get my username param and set the child routes.
Parent.ts:
#Component({
...
})
#RouteConfig([
{ path: '/child-1', component: ChildOneComponent, as: 'ChildOne' },
{ path: '/child-2', component: ChildTwoComponent, as: 'ChildTwo' }
])
export class ParentComponent {
public username: string;
constructor(
public params: RouteParams
) {
this.username = params.get('username');
}
...
}
But then, how can I get this same 'username' parameter in those child components? Doing the same trick as above, doesn't do it. Because those params are defined at the ProfileComponent or something??
#Component({
...
})
export class ChildOneComponent {
public username: string;
constructor(
public params: RouteParams
) {
this.username = params.get('username');
// returns null
}
...
}
UPDATE:
Now that Angular2 final was officially released, the correct way to do this is the following:
export class ChildComponent {
private sub: any;
private parentRouteId: number;
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.sub = this.route.parent.params.subscribe(params => {
this.parentRouteId = +params["id"];
});
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}
ORIGINAL:
Here is how i did it using the "#angular/router": "3.0.0-alpha.6" package:
export class ChildComponent {
private sub: any;
private parentRouteId: number;
constructor(
private router: Router,
private route: ActivatedRoute) {
}
ngOnInit() {
this.sub = this.router.routerState.parent(this.route).params.subscribe(params => {
this.parentRouteId = +params["id"];
});
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}
In this example the route has the following format: /parent/:id/child/:childid
export const routes: RouterConfig = [
{
path: '/parent/:id',
component: ParentComponent,
children: [
{ path: '/child/:childid', component: ChildComponent }]
}
];
You shouldn't try to use RouteParams in your ChildOneComponent.
Use RouteRegistry, instead!
#Component({
...
})
export class ChildOneComponent {
public username: string;
constructor(registry: RouteRegistry, location: Location) {
route_registry.recognize(location.path(), []).then((instruction) => {
console.log(instruction.component.params['username']);
})
}
...
}
UPDATE: As from this pull request (angular beta.9): https://github.com/angular/angular/pull/7163
You can now access to the current instruction without recognize(location.path(), []).
Example:
#Component({
...
})
export class ChildOneComponent {
public username: string;
constructor(_router: Router) {
let instruction = _router.currentInstruction();
this.username = instruction.component.params['username'];
}
...
}
I haven't tried it, yet
Further details here:
https://github.com/angular/angular/blob/master/CHANGELOG.md#200-beta9-2016-03-09
https://angular.io/docs/ts/latest/api/router/Router-class.html
UPDATE 2:
A small change as from angular 2.0.0.beta15:
Now currentInstruction is not a function anymore. Moreover, you have to load the root router. (thanks to #Lxrd-AJ for reporting)
#Component({
...
})
export class ChildOneComponent {
public username: string;
constructor(_router: Router) {
let instruction = _router.root.currentInstruction;
this.username = instruction.component.params['username'];
}
...
}
As mentioned by Günter Zöchbauer, I used the comment at https://github.com/angular/angular/issues/6204#issuecomment-173273143 to address my problem. I used the Injector class from angular2/core to fetch the routeparams of the parent. Turns out angular 2 does not handle deeply nested routes. Maybe they'll add that in the future.
constructor(private _issueService: IssueService,
private _injector: Injector) {}
getIssues() {
let id = this._injector.parent.parent.get(RouteParams).get('id');
this._issueService.getIssues(id).then(issues => this.issues = issues);
}
I found an ugly but working solution, by requesting the parent (precisely the 2nd ancestor) injector, and by getting the RouteParams from here.
Something like
#Component({
...
})
export class ChildOneComponent {
public username: string;
constructor(injector: Injector) {
let params = injector.parent.parent.get(RouteParams);
this.username = params.get('username');
}
}
RC5 + #angular/router": "3.0.0-rc.1 SOLUTION: It seems that this.router.routerState.queryParams has been deprecated. You can get the parent route params this way:
constructor(private activatedRoute: ActivatedRoute) {
}
this.activatedRoute.parent.params.subscribe(
(param: any) => {
let userId = param['userId'];
console.log(userId);
});
You can take component of parent route inside of child component from injector and then get any from child component. In you case like this
#Component({
...
})
export class ChildOneComponent {
public username: string;
constructor(
public params: RouteParams
private _injector: Injector
) {
var parentComponent = this._injector.get(ParentComponent)
this.username = parentComponent.username;
//or
this.username = parentComponent.params.get('username');
}
...
}
Passing Injector instance to constructor in child component may not be good if you want to write unit tests for your code.
The easiest way to work around this is to have a service class in the parent component, in which you save your required params.
#Component({
template: `<div><router-outlet></router-outlet></div>`,
directives: [RouterOutlet],
providers: [SomeServiceClass]
})
#RouteConfig([
{path: "/", name: "IssueList", component: IssueListComponent, useAsDefault: true}
])
class IssueMountComponent {
constructor(routeParams: RouteParams, someService: SomeServiceClass) {
someService.id = routeParams.get('id');
}
}
Then you just inject the same service to child components and access the params.
#Component({
template: `some template here`
})
class IssueListComponent implements OnInit {
issues: Issue[];
constructor(private someService: SomeServiceClass) {}
getIssues() {
let id = this.someService.id;
// do your magic here
}
ngOnInit() {
this.getIssues();
}
}
Note that you should scope such service to your parent component and its child components using "providers" in parent component decorator.
I recommend this article about DI and scopes in Angular 2: http://blog.thoughtram.io/angular/2015/08/20/host-and-visibility-in-angular-2-dependency-injection.html
In RC6, router 3.0.0-rc.2 (probably works in RC5 as well), you can take route params from the URL as a snapshot in case that params won't change, without observables with this one liner:
this.route.snapshot.parent.params['username'];
Don't forget to inject ActivatedRoute as follows:
constructor(private route: ActivatedRoute) {};
With RxJS's Observable.combineLatest, we can get something close to the idiomatic params handling:
import 'rxjs/add/operator/combineLatest';
import {Component} from '#angular/core';
import {ActivatedRoute, Params} from '#angular/router';
import {Observable} from 'rxjs/Observable';
#Component({ /* ... */ })
export class SomeChildComponent {
email: string;
id: string;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
Observable.combineLatest(this.route.params, this.route.parent.params)
.forEach((params: Params[]) => {
this.id = params[0]['id'];
this.email = params[1]['email'];
});
}
}
I ended up writing this kind of hack for Angular 2 rc.1
import { Router } from '#angular/router-deprecated';
import * as _ from 'lodash';
interface ParameterObject {
[key: string]: any[];
};
/**
* Traverse route.parent links until root router and check each level
* currentInstruction and group parameters to single object.
*
* e.g.
* {
* id: [314, 593],
* otherParam: [9]
* }
*/
export default function mergeRouteParams(router: Router): ParameterObject {
let mergedParameters: ParameterObject = {};
while (router) {
let currentInstruction = router.currentInstruction;
if (currentInstruction) {
let currentParams = currentInstruction.component.params;
_.each(currentParams, (value, key) => {
let valuesForKey = mergedParameters[key] || [];
valuesForKey.unshift(value);
mergedParameters[key] = valuesForKey;
});
}
router = router.parent;
}
return mergedParameters;
}
Now in view I collect parameters in view instead of reading RouteParams I just get them through router:
#Component({
...
})
export class ChildishComponent {
constructor(router: Router) {
let allParams = mergeRouteParams(router);
let parentRouteId = allParams['id'][0];
let childRouteId = allParams['id'][1];
let otherRandomParam = allParams.otherRandomParam[0];
}
...
}
In FINAL with little help of RXJS you can combine both maps (from child and parent):
(route) => Observable
.zip(route.params, route.parent.params)
.map(data => Object.assign({}, data[0], data[1]))
Other questions one might have:
Is it really a good idea to use above - because of coupling (couple child component with parent's param's - not on api level - hidden coupling),
Is it proper approach in term of RXJS (it would require hardcore RXJS user feedback ;)
You can do it on the snapshot with the following, but if it changes, your id property will not be updated.
This example also shows how you can subscribe to all ancestor parameter changes and look for the one you are interested in by merging all of the parameter observables. However, be careful with this method because there could be multiple ancestors that have the same parameter key/name.
import { Component } from '#angular/core';
import { ActivatedRoute, Params, ActivatedRouteSnapshot } from '#angular/router';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/observable/merge';
// This traverses the route, following ancestors, looking for the parameter.
function getParam(route: ActivatedRouteSnapshot, key: string): any {
if (route != null) {
let param = route.params[key];
if (param === undefined) {
return getParam(route.parent, key);
} else {
return param;
}
} else {
return undefined;
}
}
#Component({ /* ... */ })
export class SomeChildComponent {
id: string;
private _parameterSubscription: Subscription;
constructor(private route: ActivatedRoute) {
}
ngOnInit() {
// There is no need to do this if you subscribe to parameter changes like below.
this.id = getParam(this.route.snapshot, 'id');
let paramObservables: Observable<Params>[] =
this.route.pathFromRoot.map(route => route.params);
this._parametersSubscription =
Observable.merge(...paramObservables).subscribe((params: Params) => {
if ('id' in params) {
// If there are ancestor routes that have used
// the same parameter name, they will conflict!
this.id = params['id'];
}
});
}
ngOnDestroy() {
this._parameterSubscription.unsubscribe();
}
}
Getting RouteParams from parent component in Angular 8 -
I have a route http://localhost:4200/partner/student-profile/1234/info
Parent route - student-profile
Param - 1234 (student_id)
Child route - info
Accessing param in child route (info) -
Import
import { ActivatedRoute, Router, ParamMap } from '#angular/router';
Constructor
constructor(private activatedRoute: ActivatedRoute, private router: Router) { }
Accessing parent route params
this.activatedRoute.parent.paramMap.subscribe((params: ParamMap) => this.studentId = (params.get('student_id')));
Now, our variable studentId has the param value.

Categories