I have an array coming from #input like this:
export interface XXModel {
id: number;
category: string;
serialNumber: string;
description: string;
}
#Input() assets: XXModel[];
I created another array to get the Id and description from the previous array to use this array to provide data to a component in the html
public _assets:{key:number, value:string}[];
How can I fill the _assets array with the id and description from the assets array to populate a component in HTML and receive data from the _assets array?
I tried this approach, but I get undefined and it's not working:
#Input() assets: XXModel[];
public _assets:{key:number, value:string}[];
ngOnInit() {
this.assets.map(item => {
if(item){
const {id, description} = item;
this._assets.push({key:id, value:description});
}
});
console.log(this._assets)
}
also I tried this way :
#Input()
get assets(): XXModel [] {
return this._assets as any
}
set assets(value: XXModel []) {
value.map(asset=>{
this._assets.push({key:asset.id,value:asset.description})
})
}
public _assets: {key:number, value:string}[];
In angular #Input properties don't have a value if accessed inside ngOnInit hook. They would have a value first in ngOnChanges() hook.
You can just udpdate your code to:
class Component implements OnChanges {
#Input() assets: XXModel[];
public _assets:{key:number, value:string}[];
public ngOnChanges(changes: SimpleChanges) {
const { assets } = changes;
if(assets.firstChange) return
this._assets = this.assets.map(({ id, description }) => ({ key: id, value: description }))
}
}
Related
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.
t.budget.budgetGroup.name here it has above error. I cannot recreate this error. But Sentry shows it as a runtime exception. Is this possible? Since I have initialized the new Budget() and new BudgetGroup(). So how can I fix this?
data: DtoBudgetGroup;
constructor(){}
init() {
this.data = this.navParams.get('data');
}
let filteredTransactions: Transaction[] = filter(this.data.transactions, (t:
Transaction) => { return t.budget.budgetGroup.name == this.data.budget.budgetGroup.name; });
export class Transaction {
id: string;
budget: Budget = new Budget();
}
export class Budget {
id: string;
budgetGroup: BudgetGroup = new BudgetGroup();
}
export class BudgetGroup {
id: string;
name: string;
}
export class DtoBudgetGroup {
budget: Budget;
budgetGroup: BudgetGroup;
budgetTotal: number;
transactionTotal: number;
transactions: Transaction[];
isTransactionOver: boolean = false;
}
this.data = this.navParams.get('data');
The problem in your code is that when you type
class MyClass {
prop: stirng;
}
You are only declaring a set of properties and their type.
However, you don't initialise them. To initialise you need a constructor.
You have two ways of declaring class' props
export class BudgetGroup {
constructor(
public id?: string,
public name?: string
) {
}
}
and
export class BudgetGroup {
id: string;
name: string;
constructor(
id: string,
name: string
) {
this.id = id;
this.name = name;
}
}
The example you can see here
There is no prop initialisation therefore calling new BudgetGroup results in empty object. To initialise them you should use either constructor where you pass props or declare these props values right in class.
Update. Specially for Randy Casburn
I want to pass the value from select list - ListComponentComponent to sibling component - DisplayComponentComponent and display the value in the template of DisplayComponentComponent. I want to use shared service for that. I created service and I am passing the value on change. However when I want to console.log this value in my display component I can't see anything. Here is my code.
Display component
export class DisplayComponentComponent implements OnInit {
val: any;
constructor(private myService: MyServiceService) { }
ngOnInit() {
this.myService.val.subscribe(result => {
this.val = result
});
}
}
List
export class ListComponentComponent implements OnInit {
list: any;
selected: string;
constructor(private myService: MyServiceService) { }
ngOnInit() {
this.list = [
{
text: 'test1',
value: 'test1'
},
{
text: 'test2',
value: 'test2'
},
{
text: 'test3',
value: 'test3'
}
]
this.selected = this.list[0].value;
this.myService.update(this.selected);
}
getSelected(val) {
this.selected = val;
this.myService.update(this.selected);
}
}
Service
#Injectable()
export class MyServiceService {
public source = new Subject<any>();
val = this.source.asObservable();
update(input: any) {
this.source.next(input);
}
constructor() { }
}
The value should be displayed here:
<p>
{{result}}
</p>
https://stackblitz.com/edit/angular-7lhn9j?file=src%2Fapp%2Fmy-service.service.ts
If you wand to show the values on application load you need to change the subject to BehaviorSubject
private _onChanged: BehaviorSubject<any> = new BehaviorSubject({});
public val= this._onChanged.asObservable();
update(input: any) {
this._onChanged.next(input);
}
constructor() { }
Demo
You have to bind to the right value in your display-component.component.html part:
<p>
{{val}} <!--not {{result}}-->
</p>
I found a small thing in your code. instead of bellow
<p>
{{result}}
</p>
you should use
<p>
{{val}}
</p>
The value is getting updated everything is right.
val: any;
constructor(private myService: MyServiceService) { }
ngOnInit() {
this.myService.val.subscribe(result => {
console.log(result);
this.val = result
});
}
in HTML you are using {{result}} there is no such variable use {{val}} instead, or change variable name
result: any;
constructor(private myService: MyServiceService) { }
ngOnInit() {
this.myService.val.subscribe(res => {
console.log(result);
this.result = res
});
}
I can't figure out how to fetch data from firestore when i have in data model reference (id) to another object, for example like this
City {name: string;
countryId: string; //primary key to another object in database
}
Country {
name: string;
}
I m using AngularFire 5.
After i fetch city i want fetch country and i want to asign country.name to city.countryId and i want return joined object city.
I made service for this because i want fetch this data from multiple places in code.
#Injectable()
export class CityService implements OnInit {
city: City;
constructor(
private dataFetch: FireStoreService) { }
ngOnInit() {}
getCity(ref: string): City {
this.dataFetch.getDataDoc(ref).subscribe((_city: City) => {
this.dataFetch.getDataDoc(_city.countryId)
.subscribe((country: Country) => {
_city.countryId = country.name;
this.city = _city;
});
});
return this.city;
}
}
Ye i know this will not work beacause it is async task, i have read a lot of articles, but i can not still figure out. So I don't know how to fetch some object and then fetch references from this object and return joined object (without references but with proper data).
This is my city component.
#Component({
selector: 'app-detail-city',
template: `
<p> detail-city works! </p>
<p> Name : {{ city.name }} </p>
<p> Country : {{ city.countryId }} </p>
<p> ID : {{ city.id }} </p>
`,
styleUrls: ['./detail-city.component.css']
})
export class DetailCityComponent implements OnInit {
city: City;
root: string;
constructor(
private route: ActivatedRoute,
private cityService: CityService) {
this.route.params.subscribe(
(params: Params) => {
this.root = params['root']+'/'+params['id'];
this.city = cityService.getCity(this.root);
});
}
ngOnInit() {}
}
So i manage to solve this problem at the end.
Here is code from servis.
getCity(ref: string): Observable<City> {
return this.dataFetch.getDocument(ref)
.switchMap((res: City) => {
return this.dataFetch.getDocument(res.countryId)
.map((country: Country) => {
return new City(
res.id,
res.name,
country.name
);
});
});
}
Then you can subscribe to this observable in your component or use async pipe.
Also, I found usefull link where is described how to use reference and geo type in FireStore.
Say I have classes Task and TaskGroup
class Task{
constructor(public text:string){}
}
class TaskGroup {
constructor(public title:string = "new task group", public tasks:Task[] = []){}
}
Then in my Angular 2 service I will create an Immutable List of TaskGroups
#Injectable()
class TaskService {
taskGroups:Immutable.List<TaskGroup>;
constructor() {
this.taskGroups = Immutable.List<TaskGroup>([new TaskGroup("Coding tasks")]);
}
}
This way only taskGroups List is immutable. Whatever is inside it isn't. Even if I do Immutable.fromJS(...) instead of Immutable.List<Board>(...) the nested objects are plain ol' Javascript objects.
Immutable JS doesn't supposed class inheritance (Inheriting from Immutable object with ES6 #562)
//can't do this!
class TaskGroup extends Immutable.Map<string, any>{
constructor(public title:string = "new task group", public tasks:Task[]){}
}
//it complained about the class not having methods like set, delete etc
So how to create Immutable class objects?
You can do like this:
const TodoRecord = Immutable.Record({
id: 0,
description: "",
completed: false
});
class Todo extends TodoRecord {
id:number;
description:string;
completed: boolean;
constructor(props) {
super(props);
}
}
let todo:Todo = new Todo({id: 1, description: "I'm Type Safe!"});
Not perfect but working.
It comes from this great blog post:
https://blog.angular-university.io/angular-2-application-architecture-building-flux-like-apps-using-redux-and-immutable-js-js/
You can make a wrapper with Immutable, as stated in this tutorial:
import { List, Map } from 'immutable';
export class TodoItem {
_data: Map<string, any>;
get text() {
return <string> this._data.get('text');
}
setText(value: string) {
return new TodoItem(this._data.set('text', value));
}
get completed() {
return <boolean> this._data.get('completed');
}
setCompleted(value: boolean) {
return new TodoItem(this._data.set('completed', value));
}
constructor(data: any = undefined) {
data = data || { text: '', completed: false, uuid: uuid.v4() };
this._data = Map<string, any>(data);
}
}
Hope this will help! ;)