Angular 6 file upload with form content - angular6

I have create a page with different input elements with file upload. While saving the form with multiple files along with form input elements using angular 6, the file object is empty {} in console an http service in network tab.
Here is my code:
onFileChanged(event) {
this.selectedFiles = event.target.files;
const uploadData = new FormData();
uploadData.append('myFile', this.selectedFiles, this.selectedFiles[0].name);
this.createFormData.attachment = uploadData;
};
Can anyone provide a sample to help me?

This is example of upload method in service. Pass files and input values from component to service, create formData, loop on files and append each file to formData and same with input values.
upload(files, inputs) {
let formData = new FormData();
files.map((file) => {
formData.append('file', file);
});
inputs.map((input) => {
formData.append(`${input.name}`, input.value);
});
return this.http.post(`some/api/upload`, formData)
.pipe(map((res) => res.data));
}
With this example your request should contain all array of files and inputs, also if you need some special header add it after formData in post method (in my case i handle headers in interceptor).
upload(files, inputs) {
let formData = new FormData();
files.map((file) => {
formData.append('file', file);
});
inputs.map((input) => {
formData.append(`${input.name}`, input.value);
});
const headers = new HttpHeaders({
'Accept': 'application/json'
});
const options = { headers: headers };
return this.http.post(`some/api/upload`, formData, options)
.pipe(map((res) => res.data));
}

Have a look at following example with npm's ng2-file-upload (in this case with a fontAwsome-icon).
myFileUploadForm.component.html:
<!-- file upload -->
<input #fileToUpload type="file" style="display:none;" ng2FileSelect (change)="onFileChanged($event)" [uploader]="uploader"
name="customerFile" id="customerFile" class="customerFile" />
<a href="javascript:document.getElementById('customerFile').click();">
<fa class="ql-upload" *ngIf="buttonDeaktivieren" [title]="'Upload'" [name]="'upload'" [size]="0.9" [border]=false></fa>
</a>
myFileUploadForm.component.ts (I'll ommit the obvious parts with ..):
import { Component, OnInit, ViewChild, OnDestroy, TemplateRef } from '#angular/core';
import { Subscription, Observable } from '../../../../../node_modules/rxjs';
....
...
import { FileUploader } from 'ng2-file-upload';
#Component({
....
...
..
})
export class myFileUploadFormComponent implements OnInit, OnDestroy {
public uploader: FileUploader = new FileUploader({ url:
'http://localhost:3000/files/uploadFile/', itemAlias: 'customerFile' });
filesArray = [];
constructor(
...
..
private http: Http
) { }
ngOnInit() {
....
...
..
}
// INFO: Function for opening confirm modal when deleting file
openDeleteFileModal(file) {
const initialState = {
file: file
};
this.deleteFileModalRef = this.modalService.show(ConfirmFileDeletionComponent, {
initialState, class: 'modal-md modal-dialog-centered' });
}
// INFO: Handy helper for assigning appropriate file-icon according to extension
getFilesIcon(file) {
if (file === 'docx') {
return 'file-word-o';
} else if (file === 'jpeg' || file === 'jpg' || file === 'png') {
return 'image';
} else if (file === 'pdf') {
return 'file-pdf-o';
} else if (file === 'xlsx' || file === 'xls') {
return 'file-excel-o';
} else if (file === 'pptx') {
return 'file-powerpoint-o';
} else if (file === 'zip') {
return 'file-archive-o';
} else {
return 'file';
}
}
/* INFO : service for downloading the uploaded file */
downloadFile(filename) {
this.fileDataService.downloadFile(filename);
}
onFileChanged(event) {
this.uploader.onBuildItemForm = (fileItem: any, form: any) => {
form.append('id', this.customer.id);
form.append('customername', this.customer.customername);
};
this.uploader.uploadAll();
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
Obviously this is my implementation suited to my needs (uploaded files are related to a certain customer and are displayed with icons according to extension and listed for future download or deletion as well), but I'm sure you can get it done by adjusting the code to your needs and write the relevant services. Have a nice one weekend ;)

Related

How to Parse a Json Data Response from an API call in Ionic v3 and store in localStorage

I want to access array data and store in localStorage.
I made an API call and get a response as below, shown on console
My Api Provider:
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import 'rxjs/add/operator/map';
let apiUrl = 'http://localhost:83/buildit/api';
#Injectable()
export class AuthServiceProvider {
constructor(public http: Http) { }
login(credentials) {
//let headers = new Headers();
return new Promise((resolve, reject) => {
this.http.post(apiUrl + '/login.php', JSON.stringify(credentials))
.subscribe(res => {
resolve(res.json());
}, (err) => {
reject(err);
});
});
}
}
login.ts
doLogin() {
if(this.loginData.LoginID =='' || this.loginData.Password ==''){
let toast = this.toastCtrl.create({
message: "Enter username and password",
duration: 3000,
position: 'bottom',
dismissOnPageChange: true
});
toast.onDidDismiss(() => {
});
toast.present();
}
else if(this.loginData.LoginID!=='' && this.loginData.Password!==''){
this.showLoader();
this.authService.login(this.loginData).then((result) => {
this.data = result.data;
console.log(this.data.loginStatus);
if (this.data.loginStatus == 'Valid') {
localStorage.setItem('loginStatus', this.data.loginStatus);
localStorage.setItem('CustomerName', this.data.CustomerName);
localStorage.setItem('Mobile', this.data.Mobile);
localStorage.setItem('Email', this.data.Email);
localStorage.setItem('CustomerID', this.data.CustomerID);
this.navCtrl.setRoot(MyApp);
this.loading.dismiss();
}
else if (result['msg'] == "Please verify your mobile no. to Login") {
this.navCtrl.push(OtpPage,{
ID : result['data'].CustomerID , Mobile : this.loginData.LoginID,
Email: result['data'].Email
});
this.loading.dismiss();
}
else {
document.getElementById('err-span').style.display = "block";
this.loading.dismiss();
}
}, (err) => {
this.loading.dismiss();
this.presentToast(err);
});
}
}
Console.log(data) shows
{"data":[{
"loginStatus":"Valid",
"CustomerName":"Fagbemi Ayodele",
"Mobile":null,
"Email":"fagbemiayodele48#gmail.com",
"CustomerID":"3"
}]}
I need to parse the JSON data to get individual 'value'
I tried this.data.loginStatus to get the loginStatus but it give null value, likewise for others.
Please, can someone show me how to get the data individual value in ionic 3?
Thanks.
Individual values you can get like this:
data[0]['loginStatus']
localStorage.setItem('loginStatus', data[0]['loginStatus']);
localStorage.getItem('loginStatus');
//Valid
data[0]['CustomerName']
localStorage.setItem('CustomerName', data[0]['CustomerName']);
localStorage.getItem('CustomerName');
//Fagbemi Ayodele
data[0]['Mobile']
localStorage.setItem('Mobile', data[0]['Mobile']);
localStorage.getItem('Mobile');
//null
data[0]['Email']
localStorage.setItem('Email', data[0]['Email']);
localStorage.getItem('Email');
//fagbemiayodele48#gmail.com
data[0]['CustomerID']
localStorage.setItem('CustomerID', data[0]['CustomerID']);
localStorage.getItem('CustomerID');
//3

output data from json file in React

I need to output data from the json file that the user loads at the front.
I download the json file, but I get a strange store in Redux and can not figure out how to further display the data to the screen from the store.
What should I need to do?
import React from 'react'
import { connect } from 'react-redux'
import * as actions from './actions'
class File extends React.Component {
constructor (props) {
super(props)
}
handleChange (e) {
e.preventDefault();
let reader = new FileReader();
let file = e.target.files[0];
reader.onloadend = () => {
let text = reader.result;
this.props.jsonLoad(JSON.parse(text))
}
reader.readAsText(file)
}
render () {
return (
<div>
<h3> Add your file: </h3>
<input type="file" multiple onChange={this.handleChange.bind(this)}/>
<button >
add text from file
</button>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
json: state.json
}
}
function mapDispatchToProps (dispatch) {
return {
jsonLoad: (json) => dispatch(actions.jsonLoad(json)),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(File)
action.js
const USER_JSON = 'USER_JSON';
export function jsonLoad(json) {
console.log( json)
return function (dispatch) {
let file = json
dispatch(addFile(file))
}
}
export function addFile (json) {
return{
type: 'USER_JSON',
payload: json
}
};

Angular, File not uploaded to Firebase Storage

I'm trying to make an upload function for uploading file/image to my firebase database storage. I have already paste the correct API key in the environment.ts and import it to app.module.ts like AngularFireModule.initializeApp(environment.firebaseConfiguration, 'app-root'). I made the push string properties function and upload file function separately. The other properties like name and description are pushed correctly into my Firebase real-time database but the file is not uploaded to the storage so i also cant obtain the url.
//product.ts
export class Product {
$prdKey: string;
prdName: string;
prdImage ? : File;
imageURL ? : any;
prdDescription: string;
constructor(prdImage: File) {
this.prdImage = prdImage;
}
}
//product.service.ts
Product: any;
selectedProduct: Product = new Product(this.Product);
currentFileUpload: Product;
insertProduct(Product: Product) {
this.productList.push({
prdName: Product.prdName,
prdDescription: Product.prdDescription
});
}
private basePath = '/';
pushFileToStorage(Product: Product) {
const storageRef = firebase.storage().ref();
const uploadTask = storageRef.child(`${this.basePath}/${Product.prdImage.name}`).put(Product.prdImage);
uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED,
(snapshot) => {
// in progress
const snap = snapshot as firebase.storage.UploadTaskSnapshot
},
(error) => {
// fail
console.log(error)
},
() => {
// success
Product.imageURL = uploadTask.snapshot.downloadURL
Product.prdName = Product.prdImage.name
this.saveFileData(Product)
}
);
}
private saveFileData(Product: Product) {
this.firebase.list(`${this.basePath}/`).push(Product);
}
//product.component.ts
onSubmit(form: NgForm) {
if (form.value.$prdKey == null) {
this.ProductService.insertProduct(this.ProductService.selectedProduct);
} else {
this.ProductService.updateProduct(this.ProductService.selectedProduct);
}
}
upload() {
const file = this.ProductService.selectedProduct.prdImage
this.ProductService.currentFileUpload = new Product(file);
}
selectFile(event) {
this.ProductService.selectedProduct = event.target.files;
}
<!--product.component.html-->
<form #productForm="ngForm" (ngSubmit)="onSubmit(productForm); upload()">
<!--skip name and descrioption input-->
<label>Upload an Image</label>
<input type="file" class="form-control">
<button type="submit" class="btn btn-primary">Submit</button>
</form>
Can anyone help me solve this? Please let me know of more snippets are needed. Thank you in advance.

Filter the data from the return of HTTP Call - Angular

I am creating a project which uses a HTTP get from a web service and returns an array of projects, with ID, name, description etc.
Previously, before I created my filter, the get returned a list of 60 elements using an ngFor in the HTML file:
There is many projects within this web service but I am only concerned with 9 of them the rest are irrelevant.
My code was working when I had created my own observable object with manual data: in my project.service.http.ts class:
data: Project[] = [
{
id:...,
name:...
etc
},
and then in the fetchProjects Method:
fetchProjects(): Observable<Project[]> {
return Observable.of(this.data);
}
Because I want the observable object to be the data from my http get, this method is void. I tried to implement the observable being returned as the data from the web service, but I get the error below in my console when running.
Any help on this would be appreciated.
core.es5.js:1020 ERROR TypeError: response.filter is not a function
at SafeSubscriber._next (project.viewer.component.ts:36)
at SafeSubscriber.webpackJsonp.../../../../rxjs/Subscriber.js.SafeSubscriber.__tryOrUnsub (Subscriber.js:238)
at SafeSubscriber.webpackJsonp.../../../../rxjs/Subscriber.js.SafeSubscriber.next (Subscriber.js:185)
at Subscriber.webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber._next (Subscriber.js:125)
at Subscriber.webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber.next (Subscriber.js:89)
at CatchSubscriber.webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber._next (Subscriber.js:125)
at CatchSubscriber.webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber.next (Subscriber.js:89)
at MapSubscriber.webpackJsonp.../../../../rxjs/operator/map.js.MapSubscriber._next (map.js:83)
at MapSubscriber.webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber.next (Subscriber.js:89)
at XMLHttpRequest.onLoad (http.es5.js:1226)
My Code:
project.service.http.ts:
#Injectable()
export class ProjectServiceHttp extends ProjectService {
//variables
baseUrl = "";
static projectIds: string[] = ["","","","","",""
,"", "",""];
//constructor
constructor(private http: Http) {
super();
}
//methods
fetchProjects(): Observable<Project[]>{
let headers = new Headers({'Content-Type': 'application/json'});
let options = new RequestOptions({headers: headers});
return this.http.get(this.baseUrl, options)
.map((response: Response) =>
{
let result = response.json();
return Observable.of(result);
})
.catch(this.handleError);
}
}
project.viewer.component.ts:
#Component({
selector: 'project-viewer',
templateUrl: './project-viewer.html',
styleUrls: ['./project-viewer.css']
})
export class ProjectViewerComponent {
name = 'ProjectViewerComponent';
projects: Project[] = [];
static projectIds: string[] = ["",""
,"","","",""
,"", "",""];
errorMessage = "";
stateValid = true;
constructor(private service: ProjectService) {
this.service.fetchProjects().subscribe(response => {
this.projects = response.filter(elements => {
return ProjectViewerComponent.projectIds.includes(elements.id);
});
})
}
private fetchProjects() {
this.service
.fetchProjects()
.subscribe(response =>{
this.projects = response['project']
.filter(project => { return ['...', '','','','','...'
,'','',''].indexOf(project.id) !== -1})
console.log(response);
console.log(this.projects);
},
errors=>{
console.log(errors);
});
}
}
project-viewer.html:
<h3>Projects </h3>
<div >
<ul class= "grid grid-pad">
<a *ngFor="let project of projects" class="col-1-4">
<li class ="module project" >
<h4 tabindex ="0">{{project.name}}</h4>
</li>
</a>
</ul>
</div>
They are multiple error in your project. First of all in your service you are not using correctly the map operator you should do:
//methods
fetchProjects(): Observable<Project[]>{
let headers = new Headers({'Content-Type': 'application/json'});
let options = new RequestOptions({headers: headers});
return this.http.get(this.baseUrl, options)
.map(response => response.json())
}
Then in the component you subscribe to the service then you try to do the filtering. You can do that before subscribe like this:
private fetchProjects() {
const filterProject = ['TotalMobileAnalyseInsights', 'TotalMobileMendel','TotalMobileSlam','TotalMobileServer','TotalMobileWedAdmin','TotalMobileForAndroid'
,'TotalMobileForWindows','TotalMobileForWindowsUniversal','TotalMobileForIOS'];
this.service.fetchProjects()
// convert each element of the array into a single observable
.flatMap(projects => ArrayObservable.create(projects))
// filter project
.filter(project => filterProject.indexOf(project.id) !== -1)
.toArray()
// subscribe and do something with the project
.subscribe(projects => console.log(projects));
}
Here is a quick running example https://plnkr.co/edit/3nzr3CFhV2y0iu3cQwAF?p=preview

Accessing data within a view passed from model - Aurelia

Yes another Aurelia question, apologies!
So I'm trying to access data within my view passed from a model, whilst I can see the data within the response, I cannot seem to get it to display on the view. Any help greatly appreciated.
I've tried a few things but I guess being new to Aurelia,ES6 and promises, it's throwing me out a little or I've been staring at to long.
//EDIT Data Access Component
import {inject} from "aurelia-framework";
import {HttpClient} from "aurelia-http-client";
let baseUrl = "/FormDesigner";
#inject(HttpClient)
export class FormData{
constructor(httpClient)
{
this.http = httpClient;
}
GetFormById(formId)
{
return this.http.get(`${baseUrl}/GetFormById/${formId}`)
.then(f => f.content);
};
}
Model:
activate(params)
{
return this.form.GetFormById(params.formId)
.then(f => this.form = f);
}
The View:
<p class="navbar-text navbar-left">
${form.name}
</p>
The Response:
{"Id":"x","OrganisationId":"x","OrganisationDepartmentId":null,"ScheduleId":null,"DefinitionTypeId":"x","ReferenceNumber":11171,"Name":"New Form Test External Access","Description":"","IsTemplate":true,"IsActive":true,"IsSingleFormTemplate":false,"MinimumInstances":null,"MaximumInstances":null,"IsAdhocCreationEnabled":false,"HasCalculation":false,"Calculation":null,"Recalculate":true,"IsHidden":false}
So again I don't see the data appearing on the view and I feel I'm missing something rather simple.
//EDITS
So after a little digging I made a little change to my API returning a JSON array rather than a JSON object and also switched Aurelia to use Fetch... So now I can access the data in my data component but not my model - rather frustrating!
import {inject} from "aurelia-framework";
//import {HttpClient} from "aurelia-http-client";
//import 'fetch';
import {HttpClient} from 'aurelia-fetch-client';
let baseUrl = "/FormDesigner";
#inject(HttpClient)
export class FormData{
constructor(httpClient)
{
httpClient.configure(config => {
config
.withBaseUrl('/FormDesigner')
.withDefaults({
credentials: 'same-origin',
headers: {
'Accept': 'application/json',
'X-Requested-With': 'Fetch'
}
})
.withInterceptor({
request(request) {
console.log(`Requesting ${request.method} ${request.url}`);
return request;
},
response(response) {
console.log(`Received ${response.status} ${response.url}`);
return response;
}
});
});
this.http = httpClient;
}
GetFormById(formId)
{
return this.http.fetch(`/GetFormById/${formId}`)
.then(response => response.json())
.then(data => {
//Log here, to check incoming data
console.log("From component: " + data.Name);
//This WORKS
});
};
}
Again I've created an abstraction where as my model does not need to know about calls to the server.
import {inject} from "aurelia-framework";
import {FormData} from "form/formData";
#inject(FormData)
export class Form
{
constructor(formData)
{
this.form = formData;
}
activate(params)
{
if(params.formId != null)
{
return this.form.GetFormById(params.formId)
.then(data =>
{
this.form = data
console.log(this.form.Name);
//This does not work!!
});
}
else
{
//Show message that param does not exist or redirect to no form page
console.log("No Id");
}
}
}
Any help greatly appreciated,
Most likely you need to deserialize the JSON response into a Javascript object using JSON.parse.
GetFormById(formId)
{
return this.http.get(`${baseUrl}/GetFormById/${formId}`)
.then(response => JSON.parse(response.content));
};