Merge objects in Angular 2 [duplicate] - javascript

This question already has answers here:
How to return value from an asynchronous callback function? [duplicate]
(3 answers)
Closed 6 years ago.
Im having trouble merging 3 objects array. My objective is to merge 3 arrays to one and send HTTP POST to the server.
I have tried using concat but Im getting this error:
EXCEPTION: Error in ./PreviewEmailPage class PreviewEmailPage_Host - inline template:0:0 caused by: Cannot read property 'concat' of undefined
These are my codes:
import { Component } from '#angular/core';
import { NavParams, NavController, LoadingController } from 'ionic-angular';
import { Validators, FormGroup, FormControl } from '#angular/forms';
import { Http, Headers} from '#angular/http';
import 'rxjs/add/operator/map';
import { Storage } from '#ionic/storage';
#Component({
selector: 'preview-email-page',
templateUrl: 'preview-email.html',
})
export class PreviewEmailPage {
headers: Headers;
loading: any;
url: string;
preview: any[];
FirstArray: any[];
SecondArray: any[];
ThirdArray: any[];
PostData: any[];
constructor(
public nav: NavController,
public navParams: NavParams,
public loadingCtrl: LoadingController,
public localStorage: Storage,
public http: Http,
) {
this.localStorage.get('FirstArray').then((value) => {
this.FirstArray= value;
})
this.localStorage.get('SecondArray').then((value) => {
this.SecondArray= value;
})
this.localStorage.get('ThirdArray').then((value) => {
this.ThirdArray= value;
})
this.PostData = this.FirstArray.concat(this.SecondArray);
this.PostData = this.PostData.concat(this.ThirdArray);
this.loading = this.loadingCtrl.create();
}
ionViewWillEnter(){
this.headers = new Headers();
this.headers.append("Content-Type", "application/x-www-form-urlencoded");
console.log(this.PostData);
this.getPreview();
}
getPreview(){
this.loading.present();
this.url = 'https://domain.com/REST/getpreview.php';
this.http.post(this.url, this.PostData, {headers: this.headers}).map(res => res.json()).subscribe(res => {
console.log(res);
this.preview = res;
}, err => {
console.log('error');
})
}
}

Since this.localStorage.get is an async operation your this.FirstArray is not defined untill the then is executed.
What you can do is run them all in parallel with Promise.all:
Promise.all([this.localStorage.get('FirstArray'), this.localStorage.get('SecondArray'), this.localStorage.get('ThirdArray')]).then(values => {
this.FirstArray= values[0];
this.SecondArray= values[1];
this.ThirdArray= values[2];
this.PostData = this.FirstArray.concat(this.SecondArray);
this.PostData = this.PostData.concat(this.ThirdArray);
});

Related

How to display data from client service in ngx-wheel Angular

I want to display the ngx-wheel using api but I'm having trouble displaying the data.
Here my Service :
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class RestServices {
restEndpoint:string = 'https://gorest.co.in/public/v2/users'
constructor(
private httpClient: HttpClient
) { }
async getServiceId() {
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
})
}
return this.httpClient.get<any[]>(this.restEndpoint, httpOptions)
}
Here my Component :
private subscription: Subscription | undefined;
items: any = []
ngOnInit(): void {
this.subscription = this._restService.getServices()
.subscribe((res:any)=>{
let item = res
this.items = item.map((v:any) => ({
text: v.name,
id: v.id,
textFillStyle: "white",
textFontSize: "16"
}));
})
}
ngOnDestroy(): void {
this.subscription?.unsubscribe()
}
Here for html
<ngx-wheel #wheel [width]='350' [height]='350' [spinDuration]='8' [disableSpinOnClick]='true' [items]='items'
[innerRadius]='10' [spinAmount]='10' [textOrientation]='textOrientation' [textAlignment]='textAlignment'
pointerStrokeColor='black' pointerFillColor='white' [idToLandOn]='idToLandOn' (onSpinStart)='before()'
(onSpinComplete)='after()'>
I hope to find the answer here. Thank you
First, you don't need await, async and ,toPromise()... remove them and simply return
return this.httpClient.get<any[]>(this.restEndpoint, httpOptions);
inside your component you should use your constructor only for simple data initialization: if you have to consume a rest api it is a better approach to move that piece of code inside the ngOnInit method:
items: any[] = []
constructor(private restService: RestService){}//dependency injection
ngOnInit(): void {
this.restService.getServiceId().subscribe(response => {
console.log('response success: ', response);
this.items = response; //this may change a little based on your api
console.log('items: ', this.items);
}, errorLog => {
console.log('response error: ', errorLog)
});
}
The above solution is valid, you can enrich it by adding a *ngIf="isLoaded" on your html element and set to true the isLoaded INSIDE subscribe method. but if you prefer you can do the following in the component.ts
items$: Observable<any> = EMPTY;
constructor(private restService: RestService){}//dependency injection
ngOnInit(): void {
this.items$ = this.restService.getServiceId();
}
then, in your html it would change to the following:
<ngx-wheel #wheel *ngIf="items$ | async as items" [width]='350' [height]='350' [spinDuration]='8' [disableSpinOnClick]='true' [items]='items'
[innerRadius]='10' [spinAmount]='10' [textOrientation]='textOrientation' [textAlignment]='textAlignment'
pointerStrokeColor='black' pointerFillColor='white' [idToLandOn]='idToLandOn' (onSpinStart)='before()'
(onSpinComplete)='after()'>

I am new to Angular, I am trying to populating MatTableDataSource from local json using http get call in Angular 8, but not working [duplicate]

This question already has answers here:
How do I return the response from an Observable/http/async call in angular?
(10 answers)
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
I am trying to populate MatTableDataSource using Http local call to JSON. But it's not working. I think the assignment operation in 'subscribe()' in 'data-table.component.ts' file is not working. I tried to debug and tried to find the solution, but nothing worked and most of the time I end up breaking up m code. Please help me.
Thanks
Below are the codes with respective file names:
data-table.component.ts
import { Component } from '#angular/core';
import { MatTableDataSource } from '#angular/material';
import { FormDataService } from 'src/app/services/form-data.service';
#Component({
selector: 'app-data-table',
templateUrl: './data-table.component.html',
styleUrls: ['./data-table.component.css']
})
export class DataTableComponent {
displayedColumns: string[] = ['request_number', 'request_name', 'last_updated_date', 'completion', 'status'];
ELEMENT_REQUEST = [];
constructor(private _formDataService: FormDataService) {
console.log("Before getting data: ", this.ELEMENT_REQUEST)
this._formDataService.getformData()
.subscribe((data:any) => {
this.ELEMENT_REQUEST = data; // This line not working!
console.log("Inside: ",data);
}, err => {
console.log(err);
})
console.log("After getting data: ", this.ELEMENT_REQUEST)
}
dataSource = new MatTableDataSource(this.ELEMENT_REQUEST);
logData(row) {
console.log(row);
}
applyFilter(filterValue: String) {
this.dataSource.filter = filterValue.trim().toLowerCase();
}
}
form-data-model.ts
export interface Form_Data {
request_name: string;
request_number: number;
last_updated_date: string;
completion: number;
status: string;
}
form-data.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Form_Data } from './form-data-model';
import { Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class FormDataService {
_url = "/assets/data/form_data.json"
constructor(private http: HttpClient) { }
getformData(): Observable<Form_Data[]> {
return this.http.get<Form_Data[]>(this._url);
}
}
I got this snippet from the chrome console.
Before getting Data is all good, Inside is also working, but After getting data, there is nothing in the array
Image

Angular 5 have error on first compile (error: TS2339), but after success compilation all works fine

I wrote not typical code for case, where I get some information from API server, but don't know, how looks all response fields. After getting response I should create form for update this and sending back.
Because I don't know all ngModels, I generate some fields dynamically after response and assign it to ngModel in cycle in my template.
After stopping my ng serve -o on next first start up my Angular 5 app I get compile error. If I comment problem's code, compile, and after that uncomment it - all works fine.
order.component.ts
import {Component, OnInit} from '#angular/core';
import {UserService} from '../user/user.service';
import {OrderService} from './order.service';
import {enumUserTypes} from '../user/user.model';
import {Router, ActivatedRoute, ParamMap} from '#angular/router';
import 'rxjs/add/operator/switchMap';
import {Order} from './order.model';
import {Observable} from 'rxjs/Observable';
#Component({
selector: 'app-order',
templateUrl: './order.component.html',
styleUrls: ['./order.component.scss']
})
export class OrderComponent implements OnInit {
orderContent = [];
edit: boolean;
userTypes = enumUserTypes;
constructor(
private route: ActivatedRoute,
private router: Router,
public userService: UserService,
public orderService: OrderService
) {
}
ngOnInit() {
this.route.paramMap
.switchMap((params: ParamMap) =>
this.orderService.getOrder(params.get('orderId'))).subscribe(response => {
this.orderService.order = response;
});
this.edit = false;
}
editOrder() {
for (let item in this.orderService.order.orderContent) {
if (this.orderService.order.orderContent.hasOwnProperty(item)) {
let newClassFieldName: string = this.orderService.order.orderContent[item].className;
let newClassFieldLabel: string = this.orderService.order.orderContent[item].label;
let newClassFieldValue: string = this.orderService.order.orderContent[item].value;
this[newClassFieldName] = {
className: newClassFieldName as string,
label: newClassFieldLabel as string,
value: newClassFieldValue as string
};
this.orderContent.push({
className: this[newClassFieldName].className,
label: this[newClassFieldName].label,
value: this[newClassFieldName].value
});
}
}
this.edit = true;
}
submit() {
this.orderContent = [];
for (let item in this) {
if (this.hasOwnProperty(item) &&
item.substring(0, 17) === 'orderContentField') {
this.orderContent.push({
// error TS2339: Property 'className' does not exist on type 'this[keyof this]'.
className: this[item].className,
// error TS2339: Property 'label' does not exist on type 'this[keyof this]'.
label: this[item].label,
// error TS2339: Property 'value' does not exist on type 'this[keyof this]'.
value: this[item].value
});
}
}
this.orderService.order.orderDataUpdate = new Date();
this.orderService.updateOrder(
this.userService.user.userId,
this.orderService.order.orderName,
this.orderService.order.orderCost,
this.orderContent).subscribe(response => {
});
}
saveEditsOrder() {
this.edit = false;
}
}
order.component.html
<div *ngIf="this.edit" class="wrapper--order--edit-form">
<form class="form" #OrderEditPageForm="ngForm" novalidate>
<ng-container *ngFor="let item of this.orderService.order.orderContent">
<label class="label" for="{{item.className}}">{{item.label}}</label>
<input class="input"
[(ngModel)]="this[item.className].value"
id="{{item.className}}"
name="{{item.className}}"/>
</ng-container>
<button class="btn"
type="submit"
role="button"
(click)="submit()">
Send
</button>
</form>
order.service.ts
import {Injectable} from '#angular/core';
import {Order} from './order.model';
import {Router} from '#angular/router';
import {HttpClient} from '#angular/common/http';
import {UserService} from '../user/user.service';
import {Observable} from 'rxjs/Observable';
import {apiRoutes} from '../app.config';
#Injectable()
export class OrderService {
order: Order = new Order();
constructor(private router: Router,
private httpClient: HttpClient,
public userService: UserService) {
}
createOrder(userId: number, orderName: string, orderCost: number, orderContent: any): Observable<Order> {
return this.httpClient.post<Order>(apiRoutes.orders,
{
userId: userId,
orderName: orderName,
orderCost: orderCost,
isOrderOpen: this.order.isOrderOpen,
isOrderPaidOf: this.order.isOrderPaidOf,
orderWorkStatus: this.order.orderWorkStatus,
orderPaymentStatus: this.order.orderPaymentStatus,
orderDataOpened: this.order.orderDataOpened,
orderDataUpdate: this.order.orderDataUpdate,
orderDataClosed: this.order.orderDataClosed,
orderDataPayment: this.order.orderDataPayment,
conversationId: this.order.conversationId,
orderContent: orderContent
});
}
updateOrder(userId: number, orderName: string, orderCost: number, orderContent: any): Observable<Order> {
return this.httpClient.put<Order>(apiRoutes.order + this.order._id,
{
userId: userId,
orderName: orderName,
orderCost: orderCost,
isOrderOpen: this.order.isOrderOpen,
isOrderPaidOf: this.order.isOrderPaidOf,
orderWorkStatus: this.order.orderWorkStatus,
orderPaymentStatus: this.order.orderPaymentStatus,
orderDataOpened: this.order.orderDataOpened,
orderDataUpdate: this.order.orderDataUpdate,
orderDataClosed: this.order.orderDataClosed,
orderDataPayment: this.order.orderDataPayment,
conversationId: this.order.conversationId,
orderContent: orderContent
});
}
getUserOrders(): Observable<Order> {
return this.httpClient.post<Order>(apiRoutes.userOrders, {userEmail: this.userService.user.userEmail});
}
getOrder(id: string): Observable<Order> {
return this.httpClient.get<Order>(apiRoutes.order + id);
}
}
order.model.ts
export class Order {
constructor(
public _id: number = null,
public userId: number = null,
public orderName: string = '',
public orderCost: number = null,
public isOrderOpen: boolean = true,
public isOrderPaidOf: boolean = false,
public orderWorkStatus: string = 'Checking documents',
public orderPaymentStatus: string = 'Not paid',
public orderDataOpened: Date = new Date(),
public orderDataUpdate: Date = null,
public orderDataClosed: Date = null,
public orderDataPayment: Date = null,
public conversationId: number = null,
public orderContent: Object = []
) {
}
}
I get some error on new fields creating after getting response API.
Errors TS2339: Property 'className' does not exist on type 'this[keyof this]'.
Error TS2339: Property 'label' does not exist on type 'this[keyof this]'.
Error TS2339: Property 'value' does not exist on type 'this[keyof this]'.
How can I solve this?
I should something switch off this checking in compiler or reformat my code?
This is your error :
editOrder() {
/* ... */
this.orderContent.push({
className: this[newClassFieldName].className,
label: this[newClassFieldName].label,
value: this[newClassFieldName].value
});
}
More precisely :
this[newClassFieldName].className
When you write that, you try to read a variable in your OrderComponent.
This could have worked, because you declare that variable just before. But your issue is that you created variables into that variable, that have very strange names. The error tells you that :
Property 'className' does not exist on type 'this[keyof this]'
You declare the variable like this
let newClassFieldName: string = this.orderService.order.orderContent[item].className;
Just before that, could you write
console.log(this.orderService.order.orderContent[item].className);
And tell me the result ?

Not able to push in an JSON array in Angular 4

I'm using a session variable array of JSON objects to get a list of dynamic data from HTTP url.
this is my component.ts code:
import { IProduct } from "../models/iproduct";
import { Component, OnDestroy, OnInit } from '#angular/core';
import { TimerObservable } from "rxjs/observable/TimerObservable";
import {
Http
} from '#angular/http';
import {
ProcessJsonService
} from '../models/myjsonprocess';
import {
Observable
} from 'rxjs/Rx';
#Component({
selector: 'app-product-list',
templateUrl: './product-list.component.html',
styleUrls: ['./product-list.component.css']
})
export class ProductListComponent implements OnInit {
pageTitle: string = 'Process List';
imageWidth: number = 50;
imageMargin: number = 2;
showImage: boolean = false;
listFilter: string = '';
processList: IProduct[] ;
mysessionvariable: IProduct[] ;
errorMessage: string;
private alive: boolean;
private interval: number
constructor(private _processJsonService: ProcessJsonService) {
this.processList = [];
this.mysessionvariable = [];
this.alive = true;
this.interval = 1000;
}
ngOnInit() {
TimerObservable.create(0, this.interval)
.takeWhile(() => this.alive)
.subscribe(() => {
this._processJsonService.getProcesslist()
.subscribe(processList => {
if (processList instanceof Array) {
this.processList = processList;
this.mysessionvariable = this.SaveDataToLocalStorage(processList);
this.processList = this.mysessionvariable;
} else {
this.processList = [processList];
this.mysessionvariable = this.SaveDataToLocalStorage(processList);
this.processList = this.mysessionvariable;
}
});
});
}
ngOnDestroy(){
this.alive = false;
}
SaveDataToLocalStorage(data)
{
var mysessionarray: any[] = Array.of(JSON.parse(localStorage.getItem('session')));
// Parse the serialized data back into an aray of objects
// localStorage.setItem('session', JSON.stringify(data));
// Push the new data (whether it be an object or anything else) onto the array
//console.log("my mysessionarray is", mysessionarray)
console.log("my data in push is", data)
mysessionarray.push(data);
//localStorage.setItem('session', JSON.stringify(mysessionarray));
console.log("my data after push is", mysessionarray)
return mysessionarray;
}
}
This is my service:
import {
Injectable
} from '#angular/core';
import {
Http,
HttpModule,
Headers,
RequestOptions,
Response
} from '#angular/http';
import {
HttpClientModule
} from '#angular/common/http';
import {
Observable
} from 'rxjs/Rx';
import 'rxjs/Rx'; //get everything from Rx
import 'rxjs/add/operator/toPromise';
import {
IProduct
} from "../models/iproduct";
#Injectable()
export class ProcessJsonService {
constructor(private http: Http) {}
//
getProcesslist(): Observable < IProduct[] > {
let url = 'myURL';
return this.http.request(url).map(res => res.json());
}
}
I'm getting this error
ERROR TypeError: mysessionarray.push is not a function
at ProductListComponent.SaveDataToLocalStorage (product-list.component.ts:71)
at SafeSubscriber.eval [as _next] (product-list.component.ts:50)
at SafeSubscriber.__tryOrUnsub (Subscriber.js:240)
at SafeSubscriber.next (Subscriber.js:187)
at Subscriber._next (Subscriber.js:128)
at Subscriber.next (Subscriber.js:92)
at MapSubscriber._next (map.js:85)
at MapSubscriber.Subscriber.next (Subscriber.js:92)
at XMLHttpRequest.onLoad (http.js:1591)
at ZoneDelegate.invokeTask (zone.js:421)
Please any help on getting this fixed? am I missing some imports? or please what's wrong with my code?
Also, how to refresh data in the JSON array means when a new JSON's data are added I need if this row exists in my array just update its data else add a new row?
You are using JSON.parse method to convert your JSON data into Typescript object.
mysessionarray = JSON.parse(localStorage.getItem('session'));
But it will not convert into array directly as your localStorage.getItem('session') may return JSON object as well.
If you are sure that you will get JSON Array only then you can specify
mysessionarray: any[] = Array.of(JSON.parse(localStorage.getItem('session')));
It will vary on data which it receives. Hope it helps !!

TypeError Undefined variable in angular5 when fetching data through service to component

I am stuck at the phase of learning CRUD operation in Angular 5
I have been trying for hours but no avail, it seems i can't solve the error.
When I subscribe data which comes from service and try to insert data using push. It says undefined.
addtasks.component.ts
import { Component } from '#angular/core';
import { AddTaskService } from '../../services/add-task.service';
import { Tasks } from '../../../Tasks/Tasks';
#Component({
selector: 'app-addtasks',
templateUrl: './addtasks.component.html',
styleUrls: ['./addtasks.component.css']
})
export class AddtasksComponent {
tasks: Tasks[];
title: string;
constructor(private addTaskService: AddTaskService) {
console.log("Add tasks page has been accessed...");
}
addTasks(event){
event.preventDefault();
var newTask = {
title: this.title,
isDone: false
};
this.addTaskService.addTask(newTask).subscribe(task => {
this.tasks.push(task);
this.title = '';
});
}
}
add-task.service.ts
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class AddTaskService {
constructor(private http: Http) { console.log("Add Task service initialized..."); }
addTask(newTask){
var headers = new Headers();
headers.append('Content-Type', 'application/json');
console.log(newTask);
return this.http.post('http://localhost:2200/api/tasks', JSON.stringify(newTask), {headers: headers})
.map(res => res.json());
}
}
Model
Tasks.ts
export class Tasks {
title: string;
isDone: boolean;
}
The error showing in my console
TypeError columnNumber: 13 fileName:
"http://localhost:2200/main.bundle.js" lineNumber: 193 message:
"_this.tasks is undefined" stack:
"../../../../../src/app/components/addtasks/addtasks.component.ts/AddtasksComponent.prototype.addTasks/<#http://localhost:2200/main.bundle.js:193:13\n../../../../rxjs/_esm5/Subscriber.js/SafeSubscriber.prototype.tryOrUnsub#http://localhost:2200/vendor.bundle.js:1697:13\n../../../../rxjs/_esm5/Subscriber.js/SafeSubscriber.prototype.next#http://localhost:2200/vendor.bundle.js:1644:17\n../../../../rxjs/_esm5/Subscriber.js/Subscriber.prototype._next#http://localhost:2200/vendor.bundle.js:1585:9\n../../../../rxjs/_esm5/Subscriber.js/Subscriber.prototype.next#http://localhost:2200/vendor.bundle.js:1549:13\n../../../../rxjs/_esm5/operators/map.js/MapSubscriber.prototype._next#http://localhost:2200/vendor.bundle.js:4978:9\n../../../../rxjs/_esm5/Subscriber.js/Subscriber.prototype.next#http://localhost:2200/vendor.bundle.js:1549:13\nonLoad#http://localhost:2200/vendor.bundle.js:75626:21\n../../../../zone.js/dist/zone.js/http://localhost:2200/polyfills.bundle.js:2504:17\nonInvokeTask#http://localhost:2200/vendor.bundle.js:53623:24\n../../../../zone.js/dist/zone.js/http://localhost:2200/polyfills.bundle.js:2503:17\n../../../../zone.js/dist/zone.js/http://localhost:2200/polyfills.bundle.js:2271:28\n../../../../zone.js/dist/zone.js/http://localhost:2200/polyfills.bundle.js:2578:24\ninvokeTask#http://localhost:2200/polyfills.bundle.js:3619:9\nglobalZoneAwareCallback#http://localhost:2200/polyfills.bundle.js:3645:17\n"
__proto: Object { stack: "", … }
You should initialize tasks variable before using it.
Initialize it in the constructor function.
constructor(private addTaskService: AddTaskService) {
console.log("Add tasks page has been accessed...");
this.tasks = [];
}
That's why you have an error saying its undefined.

Categories