How do I create drag and drop upload for angular2 - node.js

I've seen tons of partial information but nothing that explains the full process of how to add a drag and drop upload to angular2. I've looked at ng2-file-upload and angular2-file-drop and file-droppa. They are all very easy to get the front end working, but with no explanation on the backend its been impossible to fully implement.
My latest attempt has been with file-droppa. I really like the look and feel of this one. (https://github.com/ptkach/fileDroppa)
So I have it deployed in so much as I can drag an image into the drop zone, see the thumbnail show up and click the Upload All Files button. What I'm missing is the magic required to get any information about the file in the backend of my application to be able to actually upload it and do anything with it.
I'm using NodeJS on the backend. The method for /upload gets called, but nothing is being passed into it.
Anyone know how to make this work?
assets.component.ts
import FileDroppa from 'file-droppa/components/Directives/FileDroppa';
#Component({
moduleId: module.id,
selector: 'pc-assets',
templateUrl: 'assets.component.html',
styleUrls: ['assets.component.css'],
directives: [FILE_UPLOAD_DIRECTIVES, NgClass, NgStyle, CORE_DIRECTIVES, FORM_DIRECTIVES, FileDroppa]
})
export class AssetsComponent implements OnInit {
#Input() asset:Asset;
#Input() uploads: Upload[];
constructor(private assetService: AssetService,
private errorService: ErrorService,
private http: Http,
private formBuilder:FormBuilder,
private uploadFileService: UploadFileService) { }
assets: Asset[] = [];
selectedAsset: Asset;
assetFilesToUpload: Array<File>;
assetUploaded = false;
assetUploadFile: any;
assetUploadObject: any;
uploadFile: any;
assetFileChangeEvent(fileInput: any){
this.assetFilesToUpload = <Array<File>> fileInput.target.files;
}
fileUploaded(success, response, file){
success && console.log("uploaded - awesome", response, file);
success || console.log("not uploaded - very bad", response, file);
}
}
assets.component.html
<fileDroppa
[url]="'http://localhost:3000/upload'"
[showFilesList]="true"
(fileUploaded)="fileUploaded($event)"
>
<!--<h1>-->
<!--You can pass anything you want here-->
<!--You can set you own file list here-->
<!--</h1>-->
</fileDroppa>

You can use ngx-file-drop package of node for implement drag and drop functionality :
hear is link for that : ngx-file-drop
documentation is very easy with example.

Related

Cannot find name 'FontFace' when using Vexflow in Angular

Im having trouble when trying to integrate VexFlow in my Angular 12 project.
First I installed the library using:
npm install vexflow
Then I created a simple component and simply used the native api example from the documentation to try out the library. Here is the component:
import {AfterViewInit, Component, ElementRef, OnInit} from '#angular/core';
import {Renderer, Stave} from "vexflow";
#Component({
selector: 'app-note-display',
templateUrl: './note-display.component.html',
styleUrls: ['./note-display.component.scss']
})
export class NoteDisplayComponent implements OnInit, AfterViewInit {
constructor(private elRef: ElementRef) { }
ngOnInit(): void {
}
ngAfterViewInit() {
const renderer = new Renderer(this.elRef.nativeElement.querySelector('#note-display'), Renderer.Backends.SVG);
// Configure the rendering context.
renderer.resize(500, 500);
const context = renderer.getContext();
// Create a stave of width 400 at position 10, 40.
const stave = new Stave(10, 40, 400);
// Add a clef and time signature.
stave.addClef('treble').addTimeSignature('4/4');
// Connect it to the rendering context and draw!
stave.setContext(context).draw();
}
}
But Im getting the following error when serving my application:
Error: node_modules/vexflow/build/types/src/font.d.ts:132:92 - error TS2304: Cannot find name 'FontFace'.
132 static loadWebFont(fontName: string, woffURL: string, includeWoff2?: boolean): Promise<FontFace>;
I tried this solution from another question, but it was not helpful in my case.
As the other solution suggest, #types/css-font-loading-module is probably what you need.
Install it with npm i -D #types/css-font-loading-module and make sure that it is included in your tsconfig.json.
It must be added to the types field, it should like similar to this:
{
"compilerOptions": {
/* other compiler options... */
"types": ["css-font-loading-module"]
}
}

Angular 8 adding component dynamically "viewContainerRef of undefined" error

I'm learning Angular and attempting to add a component to my HTML programmatically. However, I get the following error:
ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'viewContainerRef' of undefined
The following are the key parts of code.
My Placeholder directive:
import { Directive, ViewContainerRef } from '#angular/core';
#Directive({
selector: '[appPlaceholder]'
})
export class PlaceholderDirective {
constructor(public viewContainerRef: ViewContainerRef) {}
}
Main.component.ts:
export class MainComponent implements OnInit {
#ViewChild(PlaceholderDirective, {static: false, read: ViewContainerRef}) alertHost: PlaceholderDirective;
constructor(private componentFactoryResolver: ComponentFactoryResolver) {}
ngOnInit(): void {
this.showMyComp();
}
private showMyComp() {
const testCmpFactory = this.componentFactoryResolver.resolveComponentFactory(TestComponent);
const hostViewContainerRef = this.alertHost.viewContainerRef;
hostViewContainerRef.clear();
hostViewContainerRef.createComponent(testCmpFactory);
}
}
Main.component.html:
<ng-template appPlaceholder></ng-template>
I have narrowed the issue down to const hostViewContainerRef = this.alertHost.viewContainerRef; in MainComponent.ts. The problem is that this.alertHost is null but I have been unable to figure out why.
I know this is an old question, but I had the same issue a few days ago:
Method that uses alertHost is invoked from ngOnInit().
To make sure that the references injected by #ViewChild are present, always write initialization code using ngAfterViewInit().
In addition to invoking showMyComp from ngAfterViewIinit, I had to update #ViewChild to following:
#ViewChild(PlaceholderDirective, {static: false}) alertHost: PlaceholderDirective;
(it is possible that this part is caused by different angular version)

Ionic 3 Passing objects using navparams to 3 pages

I am an absolute beginner and am self taught using Ionic3
I have a problem that is driving me wild that I hope someone can assist on.
I have a master-detail-detail setup where the following happens:
Master page has a list of reports (taken from a JSON file), click on that report and it takes to a details page, click on that and it opens up another page with even more details, without having to define all the individual parts.
All I want to do is simply pass the whole object from the second page to the third page so that I can use its parameters again
master page (Report),
Second page (Reportmenu),
Third page (GenOverview)
So passing between master and second page is fine and works as it should using navparams (not shown here) but I want to use that same object and pass all the data again to the 3rd page.
I thought it would be just as simple as assigning it to a new variable and then passing that again using navparams but I get undefined
export class ReportmenuPage {
name: any;
overallscore: any;
reportdate: any;
coach: any;
age: any;
TechOverall: any;
TactOverall: any;
PhysOverall: any;
PsychOverall: any;
Logo: any;
data2: any;
constructor(public navCtrl: NavController, public navParams: NavParams,
public postsService: Posts, private toastCtrl: ToastController) {
this.overallscore = this.navParams.get('OverallScore');
this.reportdate = this.navParams.get('ReportDate');
this.name = this.navParams.get('Name');
this.coach = this.navParams.get('Coach');
this.age = this.navParams.get('Age');
this.TechOverall = this.navParams.get('TechOverall');
this.TactOverall = this.navParams.get('TactOverall');
this.PhysOverall = this.navParams.get('PhysOverall');
this.PsychOverall = this.navParams.get('PsychOverall');
this.Logo = this.navParams.get('Logo');
console.log(this.navParams.data);
this.data2 = this.navParams.data;
}
myClickHandlerOverview(data2) {
this.navCtrl.push(GenOverviewPage, data2);
So this is all fine and gives an expected output
So all I want to do now is get this to the GenOverviewPage
Here is the Reportmenu.html
<ion-item (click)="myClickHandlerOverview(data2)" color="primary">
<ion-icon name="arrow-dropright" item-end></ion-icon>
GENERAL OVERVIEW
</ion-item>
And Finally the bit that doesn't work
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { ReportmenuPage } from '../reportmenu/reportmenu';
#IonicPage()
#Component({
selector: 'page-gen-overview',
templateUrl: 'gen-overview.html',
})
export class GenOverviewPage {
constructor(public navCtrl: NavController, public navParams: NavParams) {
let data3 = this.navParams.data;
console.log(data3); //this shows as {}
}
ionViewDidLoad() {
console.log('ionViewDidLoad GenOverviewPage');
}
}
I am pretty certain I am going to get ridiculed as I think this relates to my lack of understanding of objects/ arrays and how they are passed, but I have searched high and low and cannot grasp what I am doing wrong.
and why console.log(data3) shows the second empty array but as you can see I can transfer it fine between page 1 and 2
Many thanks
In your second page, you are saving the data in a local variable that is contained within your constructor.
let data2 = this.navParams.data;
You need to save it in the class variable to be passed to your myClickHandlerOverview. Change it to:
this.data2 = this.navParams.data;
Also may need to change datatype from array to object or any.
data2: any;
A better approach seems to be to store it in a common provider.
Very simple in the end thanks to Suraj
I was missing a this!
myClickHandlerOverview(data2) {
this.navCtrl.push(GenOverviewPage, this.data2);

how to call class without declaring it in constructor angular 2

I am trying to use NFC module of Ionic 2. This is my code:
nfc-scan.ts:
import {Component} from '#angular/core';
import {IonicPage, NavController, NavParams, Platform} from 'ionic-angular';
import { Device } from '#ionic-native/device';
import {NFC, Ndef} from '#ionic-native/nfc';
#IonicPage()
#Component({
selector: 'nfc-scan',
templateUrl: 'nfc-scan.html',
})
export class NfcScan {
#ViewChild(Nav) nav: Nav;
NFC: NFC;
constructor(public platform: Platform,
public navCtrl: NavController,
public navParams: NavParams,
) {
}
// NFC Scanning
checkNFC()
{
this.NFC.enabled()
.then(() => {
this.addListenNFC();
})
.catch(err => {
console.log(err);
});
}
}
nfs-scan.html
<ion-content padding>
<button on (click)="checkNFC()">Scan NFC</button>
</ion-content>
When I run the application, I get the error:
Property 'enabled' does not exist on type 'typeof NFC'.
I know I am not declaring NFC in the constructor of nfc-scan.ts. But when I do so, the page won't even load altogether.
I did finally manage to find a solution to this problem. It turns out that it's true you can't use a class without declaring it in the constructor of the class where you want to use it.
In my case, the issue was, that I was running the app in my machine's (Macbook) browser, whereas NFC plugin can only be instantiated on a phone that supports NFC (Like camera plugin). Having said that, Ionic now provides ability to mock plugins in a way so that you can use them in your machine's browser.
To use an Ionic Native plugin in the browser and ionic serve session,
you just need to extend the original plugin class and override the
methods you’d like to mock.
Source: https://ionicframework.com/docs/native/browser.html
Hope it helps someone like me.
You would usually see an output on the console, when the page is not loading. Make sure to use private nfc : NFC in the constructor;

Using WinJS with Angular2

Trying to use a property to configure a WinJS control from within Angular2, so far I couldn't find a solution, e.g. this code below is throwing 'Can't bind to 'dataWinOptions' since it isn't a known property of the '' element'.
#View({
template: `<div id="rating" data-win-control='WinJS.UI.Rating' [data-win-options]='jsonRating'></div>`
})
class MyRating {
rating: number;
get jsonRating() {
return '{averageRating: ' + this.rating + '}';
}
constructor() {
this.rating = 1.5;
}
}
Any hint?
#ericdes about your last comment I think this would be the best option. Assuming you have Nth WinJS controls
Consider the following code. I'm specifying differents values for the averageRating property in options.
<winjs-control [options]="{averageRating: '1.5', someMoreOptions : 'x'}"></winjs-control>
<winjs-control [options]="{averageRating: '1.4', differentOptionsForThisOne :'Z'}"></winjs-control>
<winjs-control [options]="{averageRating: '1.3'}"></winjs-control>
<winjs-control [options]="{averageRating: '1.2'}"></winjs-control>
<winjs-control [options]="{averageRating: '1.1'}"></winjs-control>
// more and more...
The component will read this options property and will pass it to the view. Forget about the directive, it isn't necessary after all.
We pass options through attr.data-win-options since it isn't a property of div but an attribute.
#Component({
selector : 'winjs-control',
properties : ['options']
})
#View({
template : `<div data-win-control="WinJS.UI.Rating" [attr.data-win-options]="jsonRating"></div>`,
})
class WinJSComponent implements OnInit, AfterViewInit {
constructor() {}
// We specify onInit so we make sure 'options' exist, at constructor time it would be undefined
// And we stringify it or otherwise it will pass an object, we need to convert it to a string
onInit() {
this.jsonRating = JSON.stringify(this.options);
}
// We process WinJS after view has been initialized
// this is necessary or 'data-win-options' won't be fully processed
// and it will fail silently...
afterViewInit() {
WinJS.UI.processAll();
}
}
Here's a plnkr for this case.
That's one option and IMHO I think this is the easiest one. Another one, having the same HTML content, would be to communicate the parent with its children and I haven't tested your case with that approach.

Resources