EDIT: This doesn't work with the xml2js npm package since I want to do the opposite, convert json to xml, not the other way around.
I have my API using JSON data format but I also have to save the object that I updated in a text file in an XML format, since this other application that we communicate with only accepts XML format.
I have my service
shipment.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import * as x2js from 'xml2js';
import { map } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class ShipmentService {
baseUrl = "http://localhost:5000/api/shipments/"
constructor(
private http: HttpClient
) {}
getShipments() {
return this.http.get(this.baseUrl);
}
getShipment(id) {
return this.http.get(this.baseUrl + id);
}
updateShipment(id: number, shipment) {
return this.http.put(this.baseUrl + id, shipment);
}
}
And tracker.component.ts
import { Component, OnInit } from '#angular/core';
import { ShipmentService } from 'src/app/services/shipment.service';
import { NgbModal } from '#ng-bootstrap/ng-bootstrap';
import { ShipmentModalComponent } from '../shipment-modal/shipment-modal.component';
import { Router } from '#angular/router';
import { NgxSpinnerService} from 'ngx-spinner';
var convert = require('xml-js');
#Component({
selector: 'app-tracker',
templateUrl: './tracker.component.html',
styleUrls: ['./tracker.component.css']
})
export class TrackerComponent implements OnInit {
shipments:any = [];
shipment:any = {};
modal_on:boolean = false;
modalcontent:any;
closeResult = '';
reference: string;
constructor(
private shipmentService: ShipmentService,
private modalService: NgbModal,
private spinner: NgxSpinnerService,
private router: Router
) {}
ngOnInit() {
this.getShipments();
}
convertToXML(json) {
var options = {compact: true};
var result = convert.json2xml(json, options);
console.log(result);
}
getShipments() {
this.spinner.show(undefined,{
type: "square-spin",
size: "medium",
bdColor: 'rgba(0,0,0,.5)',
color: "rgb(5, 5, 80)",
fullScreen: false
});
this.shipmentService.getShipments().subscribe(response => {
this.shipments = response;
this.spinner.hide();
this.convertToXML(response);
console.log(response);
}, error => {
console.log(error);
});
}
}
So I tried to use x2js and other xml2json libraries but I had no success converting the JSON object into an XML object or string for that matter.
So I used js2xmlparser npm package and I wrote the following method on my service.ts file and component.ts file as follows:
service.ts
import * as JsonToXML from 'js2xmlparser';
convertXML(obj) {
let options = {
format: {
doubleQuotes: true
},
declaration: {
include: false
}
}
return JsonToXML.parse("UniversalEvent", obj, options);
}
and in my component.ts file i wrote the following method:
openModal(content, shipment) {
// this.modal_on = true;
let new_obj = {};
this.modalcontent = shipment;
this.modalService.open(content, {ariaLabelledBy: 'modal-basic-title'});
new_obj = this.addXmlAttr(new_obj);
this.xmlShipment = this.shipmentService.convertXML(new_obj);
console.log(this.xmlShipment)
console.log(this.modalcontent);
}
addXmlAttr(obj) {
obj = {
"#": {
xmlns: "http://www.cargowise.com/Schema/Universal/2011/11",
version:"1.0"
},
Event: {
DataContext: {
DataTargetCollection: {
DataTarget: {
Type: "ForwardingShipment",
Key: this.modalcontent.vortex_Reference
}
}
},
EventTime: this.modalcontent.actual_Pickup,
EventType: "PCF",
AdditionalFieldsToUpdateCollection: {
AdditionalFieldsToUpdate: {
Type: "ForwardingShipment.DocsAndCartage.JP_PickupCartageCompleted",
Value: this.modalcontent.actual_Pickup
}
}
}
}
return obj;
}
As somebody suggested, I edited the json object to my specifications and then parsed it to XML and the converted object looks like so:
<UniversalEvent xmlns="http://exampleurl.com/Schema/Example/2011/11" version="1.0">
<Event>
<DataContext>
<DataTargetCollection>
<DataTarget>
<Type>ForwardingShipment</Type>
<Key>123456</Key>
</DataTarget>
</DataTargetCollection>
</DataContext>
<EventTime>2019-05-22T00:00:00</EventTime>
<EventType>PCF</EventType>
<AdditionalFieldsToUpdateCollection>
<AdditionalFieldsToUpdate>
<Type>ForwardingShipment.DocsAndCartage.JP_PickupCartageCompleted</Type>
<Value>2019-05-22T00:00:00</Value>
</AdditionalFieldsToUpdate>
</AdditionalFieldsToUpdateCollection>
</Event>
</UniversalEvent>
install npm i js2xmlparser
import * as JsonToXML from "js2xmlparser";
console.log(JsonToXML.parse("person", this.obj));
Here this.obj is your JSON object
Stackblitz Example
Related
As i have used "ngx-toastr": "^11.3.3" in my package.json and imported in my app.module.ts.
imports: [
AgmCoreModule.forRoot({ apiKey: 'AIzaSyC5gJ5x8Yw7qP_DqvNq3IdZi2WUSiDjskk' }),
BrowserAnimationsModule,
BrowserModule,
ToastrModule.forRoot({
timeOut: 1000,
positionClass: 'toast-bottom-right'
}),
]
and in my CompanyProfile.service.ts file i have used the code as follows.
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { CustomerProfile } from '../_models/CustomerProfile';
import { CustomerUser } from '../_models/CustomerUser';
import { ToastrService } from 'ngx-toastr';
#Injectable({
providedIn: 'root'
})
export class CustomerProfileService {
private messageCustomerProfileSource: BehaviorSubject<CustomerProfile>;
public currentCustomerProfileMessage: Observable<CustomerProfile>;
constructor(private http: HttpClient, private toastr: ToastrService) {
this.messageCustomerProfileSource = new BehaviorSubject<CustomerProfile>(new CustomerProfile());
this.currentCustomerProfileMessage = this.messageCustomerProfileSource.asObservable();
}
CustomerUserAdd(_CustomerUser: CustomerUser, UserLogo: File) {
const fData = new FormData();
fData.append('Id', _CustomerUser.Id == null ? '' : _CustomerUser.Id.toString());
fData.append('CustomerId', _CustomerUser.CompanyId.toString());
fData.append('FirstName', _CustomerUser.FirstName);
fData.append('LastName', _CustomerUser.LastName);
if (UserLogo != null) {
fData.append('FileUpload', UserLogo, UserLogo.name);
}
const hdrs = new HttpHeaders().append('Content-Disposition', 'mulipart/form-data');
this.http.post(`CompanyProfile/RegisterCustomerUsers`, fData, { headers: hdrs })
.subscribe(this.Success, this.Error);
}
UpdateUsersPermissions(Id: number, Type: string, IsActive: boolean) {
const fData = new FormData();
fData.append('Id', Id.toString());
fData.append('Type', Type);
fData.append('IsActive', IsActive.toString());
this.http.post(`CompanyProfile/UpdateUsersPermissions`, fData)
.subscribe(this.Success, this.Error);
}
Error(data) {
this.toastr.error(data.errorMessage, 'Error !');
}
Success(data) {
this.toastr.success(data.errorMessage, 'Success !');
location.href = "/#/CustomerUsers";
}
}
As it shows following error which is not working as expected and also i need to add location.href = "/#/CustomerUsers" within toastr success also.
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 !!
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.
Continue to the Using angular material 2 table to display the result from backend based on user's current location
My purpose for this code is when user enter the site, it will try to ask user the current location. Once my front end get current lat/lon, it will pass to backend to get the nearest restaurant based on user's location, and using angular material table to display it. But when I testing on Chrome, I got weird behavior, the home page will not display the result immediately on the first time, try refresh, doesn't work, the only way make it works is switch another tab, and back to this one, it will display the result in angular material table.
Here is the code for home.component.ts
import { Component, OnInit } from '#angular/core';
import { Http, Response, URLSearchParams } from '#angular/http';
import { DataSource } from '#angular/cdk';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/frompromise';
import { Restaurant } from '../restaurant/restaurant';
import { Category } from '../category/category';
import { RestaurantService } from '../restaurant/restaurant.service';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
displayedColumns = ['Id', 'Name', 'Category', 'Address', 'City'];
dataSource: ExampleDataSource | null;
constructor(http: Http) {
//this.exampleDatabase = new ExampleHttpDatabase(http, this.location);
this.dataSource = new ExampleDataSource(http);
}
ngOnInit() {
this.dataSource.connect();
}
}
export class ExampleDataSource extends DataSource<Restaurant> {
private url = 'api/search/location';
private params = new URLSearchParams();
private lat;
private lon;
constructor(private http: Http) {
super();
}
/** Connect function called by the table to retrieve one stream containing the data to render. */
connect(): Observable<Restaurant[]> {
// var location;
// if (navigator.geolocation){
// var options = {timeout: 60000};
// location = navigator.geolocation.getCurrentPosition((position)=>{
// return position;
// },(err) =>{
// console.log("Error")
// }, options);
// }
// console.log("Locations: " + location);
var result = this.getCurrentLocation().then((res) =>
{
return res;
});
return Observable.fromPromise(result);
}
disconnect() { }
getPosition = () => {
var latitude, longitude;
return new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition((position) => {
resolve(position.coords);
}, (err) => {
reject(err);
});
})
}
async getCurrentLocation(): Promise<Restaurant[]> {
let coords = await this.getPosition();
this.lat = coords['latitude'];
this.lon = coords['longitude'];
this.params.set('lat', this.lat);
this.params.set('lon', this.lon);
var result = this.http.get(this.url, { search: this.params }).map(this.extractData);
return await result.toPromise();
}
extractData(result: Response): Restaurant[] {
return result.json().map(restaurant => {
return {
id: restaurant.id,
name: restaurant.restaurant_name,
category: restaurant.category.map(c => c.categoryName).join(','),
address: restaurant.address.address,
city: restaurant.address.city.cityName
}
});
}
}
I don't know what I did wrong.. can someone help me? For the full code, please see https://github.com/zhengye1/Eatr/tree/dev
Finally solved....
All I need to do just change ngOnInit on HomeComponent class to following
async ngOnInit() {
await this.dataSource.connect();
}
and it works.. don't know why...
Is there a way to get the absolute URL of my Angular 2 app, including the <base href="">?
I need to send redirect URLs to my rest API for Twitter authentication. Twitter will get these and redirect the user to them upon successful authentication.
So I need something like this but with a dynamic absoluteBaseUrl dynamical (depends on environment):
// How do I avoid hardcoding this?
let absoluteBaseUrl = "https://example.com/app";
let redirectUrl = absoluteBaseUrl + "/authsuccess";
// authUrl will look something like: http://example.com/api/auth?redirect=http%3A%2F%2Fexample.com%2Fapp%2Fauthsuccess
let authUrl = ComposeTwitterAuthUrl(redirectUrl);
// Redirect the user to the Twitter auth screen
window.location.href= authUrl;
You can try something like this, Create file appConfig.service.ts in root component.
import { Injectable } from "#angular/core";
interface EndPoint {
baseUrl: string;
requiresAuthentication: boolean;
}
interface ResourceLocator {
[key: string]: EndPoint;
}
interface XResourceLocator {
x: ResourceLocator;
}
interface YResourceLocator {
y: ResourceLocator;
}
#Injectable()
export class APIConfigurations implements XResourceLocator, YResourceLocator {
private _config;
constructor() {
this._config = require("./apiConfig.json");
}
public get x(): ResourceLocator {
return this.clone(this._config.x);
}
public get y(): ResourceLocator {
return this.clone(this._config.y);
}
private clone<T>(value: T): T {
return JSON.parse(JSON.stringify(value));
}
}
and then define your all urls in apiConfig.json:
{
"x": {
"apiary": {
"baseUrl": "https://private-xyz.apiary-mock.com/test/",
"requiresAuthentication": false
},
"local": {
"baseUrl": "http://localhost:8080/test/",
"requiresAuthentication": false
}
},
"y": {
"apiary": {
"baseUrl": "https://private-xyz.apiary-mock.com/test1/",
"requiresAuthentication": false
},
"local": {
"baseUrl": "http://localhost:8080/test1/",
"requiresAuthentication": false
}
}
}
So you can define any baseUrl based on the environment here.
And use this in your any service.ts file:
import { Injectable } from '#angular/core';
import { Http, Response, Headers, RequestOptions } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import {APIConfigurations} from "../app/apiconfig.service";
import 'rxjs/Rx';
#Injectable()
export class DashboardService {
private _requestOptions: RequestOptions;
private _baseUrl: string;
constructor(private http: Http, apiConfigs: APIConfigurations) {
const headers = new Headers({ 'Accept': 'application/json' });
const config = apiConfigs.x["local"];
this._baseUrl = config.baseUrl;
this._requestOptions = new RequestOptions({ headers: headers, withCredentials: config.requiresAuthentication });
}
/**
* [getUsers list of users]
*/
getUsers() {
return this.http.get(this.resolveUrl(`users`), this._requestOptions)
.map(res => res.json())
.catch(this.handleError);
}
private handleError(error: Response) {
return Observable.throw(error.json().error || 'Server error');
}
public resolveUrl(path: string): string {
var normalized = this._baseUrl.endsWith("/")
? this._baseUrl
: this._baseUrl + "/";
return normalized + path;
}
}
Hope this will help you.