Search code examples
typescriptangularwebstormng-file-uploadtypescript1.8

How to use ng2-file-uploader with WebStorm 2016.1?


I have to use the ng2-file-uploader in my application. I have followed this Github project but this error has occurred.

PS : I am new to Angular2 development.

I am using the latest version of webstorm (2016.1) and Typescript 1.8.2


ERROR in ./~/ng2-file-upload/components/file-upload/file-uploader.ts
Module parse failed: C:\Users\...\Desktop\FrontEndSkilify\skilify-front\node_modules\tslintloader\index.js!C:\Users\...\Desktop\FrontEndSkilify\skilify-front\node_modules\ng2-file-upload\components\file-upload\file-uploader.ts Line 1: Unexpected token
    You may need an appropriate loader to handle this file type.
    | import {FileLikeObject} from './file-like-object';
    | import {FileItem} from './file-item';
    |
     @ ./~/ng2-file-upload/ng2-file-upload.js 6:9-58

Here is my code :

demo.ts :

import {Component, NgZone} from 'angular2/core';
import {Http} from "angular2/http";
import {UPLOAD_DIRECTIVES} from 'ng2-uploader/ng2-uploader';
import {NgFileSelect} from 'ng2-uploader/src/directives/ng-file-select';

let styles = require('./demo.css')
   let template = require('./demo.html');
@Component({
    selector: 'demo',
    template: template,
    styles: [styles],
    providers: [],
   directives: [UPLOAD_DIRECTIVES,NgFileSelect],
    pipes: []

  })


    export class Demo {
    file:File;
    zone: NgZone;
    options: Object = {
        url: 'http://ng2-uploader.com:10050/upload'
    };
    basicProgress: number = 0;
    basicResp: Object;
    multipleProgress: number = 0;
    multipleResp: any[] = [];
    dropProgress: number = 0;
    dropResp: any[] = [];

    response : string;
    constructor(public http: Http){

        this.zone = new NgZone({ enableLongStackTrace: false });
    }

    handleBasicUpload(data): void {
        this.basicResp = data;
        this.zone.run(() => {
            this.basicProgress = data.progress.percent;
        });
        /* return this.http.post(API + '/api/upload',JSON.stringify(name),{ headers: contentHeaders })
         .subscribe(res => {console.log(res)},
         error=>{this.response = error.text()}

         );*/

    }

    }

my demo.html:

<div class="columns">
    <div class="column is-4">
        <div class="message is-danger">
            <div class="message-header">Basic Example</div>
            <div class="message-body">
                <div class="content">
                    <label class="tag btn is-danger">
                        <i class="fa fa-upload icon is-small"></i> Choose file
                        <input type="file" [ng-file-select]="options" (onUpload)="handleBasicUpload($event)">
                    </label>
                    <div class="progress">
                        <div class="progress-bar" [style.width]="basicProgress + '%'"></div>
                        <span class="percent">{{ basicProgress }}%</span>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="message resp">
        <div class="message-header">Response</div>
        <div class="message-body">
            <p>
                {{ basicResp | json }}
            </p>
    </div>
    </div>
</div>

my webpack.js ;

var sliceArgs = Function.prototype.call.bind(Array.prototype.slice);
var toString  = Function.prototype.call.bind(Object.prototype.toString);
var path = require('path');
var webpack = require('webpack');
// Webpack Plugins
var CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;

module.exports = {
  devtool: 'source-map',
  // devtool: 'eval',

  //
  entry: {
    'vendor': [
      // Polyfills
      'es6-shim',
      'es6-promise',
      'reflect-metadata',
      'zone.js/dist/zone-microtask',
      'zone.js/dist/long-stack-trace-zone',
      // Angular2
      'angular2/platform/browser',
      'angular2/platform/common_dom',
      'angular2/core',
      'angular2/router',
      'angular2/http',
      // RxJS
      'rxjs',
      // Other
      'angular2-jwt'
    ],
    'app': [
      './src/index'
    ]
  },

  // Config for our build files
  output: {
    path: root('build'),
    filename: '[name].js',
    // filename: '[name].[hash].js',
    sourceMapFilename: '[name].js.map',
    chunkFilename: '[id].chunk.js'
    // publicPath: 'http://mycdn.com/'
  },

  resolve: {
    root: __dirname,
    extensions: [
      '',
      '.ts',
      '.js',
      '.json',
      '.css',
      '.html'
    ]
  },

  module: {
    preLoaders: [ { test: /\.ts$/, loader: 'tslint-loader' } ],
    loaders: [
      // Support for .ts files.
      {
        test: /\.ts$/,
        loader: 'ts-loader',
        query: {
          'ignoreDiagnostics': [
            2403, // 2403 -> Subsequent variable declarations
            2300, // 2300 Duplicate identifier
            2374, // 2374 -> Duplicate number index signature
            2375  // 2375 -> Duplicate string index signature
          ]
        },
        exclude: [ /\.spec\.ts$/, /\.e2e\.ts$/, /node_modules/ ]
      },

      // Support for *.json files.
      { test: /\.json$/,  loader: 'json-loader' },

      // Support for CSS as raw text
      { test: /\.css$/,   loader: 'raw-loader' },

      // support for .html as raw text
      { test: /\.html$/,  loader: 'raw-loader' },
    ],
    noParse: [
     /zone\.js\/dist\/.+/,
     /reflect-metadata/,
     /es(6|7)-.+/,
    ]
  },

  plugins: [
    new CommonsChunkPlugin({ name: 'vendor', filename: 'vendor.js', minChunks: Infinity }),
    new CommonsChunkPlugin({ name: 'common', filename: 'common.js', minChunks: 2, chunks: ['app', 'vendor'] })
  ],
  
  // Other module loader config
  tslint: {
    emitErrors: false,
    failOnHint: false
  },
  
  // our Development Server configs
  // our Webpack Development Server config
  devServer: {
    historyApiFallback: true,
    publicPath: '/build'
  }
};

function getBanner() {
  return 'This is a sample that shows how to add authentication to an Angular 2 (ng2) app by @auth0';
}

function root(args) {
  args = sliceArgs(arguments, 0);
  return path.join.apply(path, [__dirname].concat(args));
}
function rootNode(args) {
  args = sliceArgs(arguments, 0);
  return root.apply(path, ['node_modules'].concat(args));
}

My NgFileSelect :

import {Directive, ElementRef, EventEmitter} from 'angular2/core';
import {Ng2Uploader} from '../services/ng2-uploader';

@Directive({
    selector: '[ng-file-select]',
    inputs: ['options: ng-file-select'],
    outputs: ['onUpload'],
    host: {'(change)': 'onFiles()'},
})
export class NgFileSelect {
    uploader:Ng2Uploader;
    options:any;
    onUpload:EventEmitter<any> = new EventEmitter();

    constructor(public el:ElementRef) {
        this.uploader = new Ng2Uploader();
        setTimeout(() => {
            this.uploader.setOptions(this.options);
        });

        this.uploader._emitter.subscribe((data) => {
            this.onUpload.emit(data);
        });
    }

    onFiles():void {
        let files = this.el.nativeElement.files;
        if (files.length) {
            this.uploader.addFilesToQueue(files);
        }
    }

}

Solution

  • Your project is not understanding typescript (.ts) files - at least this is the error complaining.

    Did you setup typescript correctly for your project? You could activate it with your WebStorm IDE, just go into settings - search typescript and enable it. But the problem with the IDE typescript support is, only files you actively work on will get compiled.

    And what about your build script..? Do you use webpack or browserify or system.js to build your project? I recommend to start with a nice seed project, which has all of this already setup for you, for example: https://github.com/AngularClass/angular2-webpack-starter

    An example how to setup the typescript workflow together with webpack: http://www.jbrantly.com/typescript-and-webpack/

    Basically:

    • setup webpack for your project
    • setup typescript npm module and tsconfig.json for your project
    • include the tsloader part for your webpack config

    enjoy a runnable typescript/ng2 project ;)

    Update

    Now with your code provided.. i'm wondering what your ts-loader definition is doing there with this query... i barely remember that when you provide the "query" param, it will only pick up what is defined by that.. if you remove it, he will pickup everything which matches the "test" param, except it is matching the exclude regex.

    the one i am using is much simpler:

    {test: /\.ts$/, loader: 'ts-loader', exclude: [/\.(spec|e2e)\.ts$/]},
    

    and picking up really all .ts files in the project which are not ending with *.spec.ts or *.e2e.ts - try this out once.. if the error remains, i have to run this code on my own to investigate deeper..