4

I am currently developing in Angular 2 a form that allows a user to update his profile: email and password.

user-edit.component.html:

<form novalidate="novalidate" [ngFormModel]="form" (ngSubmit)="form.valid && onSubmit()">
    <fieldset>
        <div>
            <label for="email">
                Email
            </label>

            <input id="email" type="email" #email="ngForm" ngControl="email"/>

            <div class="error" *ngIf="email.control.hasError('required') && email.touched">
                This value is required.
            </div>
        </div>

        <div>
            <label for="password">
                Password
            </label>

            <input id="password" type="password" #password="ngForm" ngControl="password"/>

            <div class="error" *ngIf="password.control.hasError('required') && password.touched">
                This value is required.
            </div>
        </div>
    </fieldset>

    <button type="submit" [disabled]="!form.valid">
        Save
    </button>
</form>

user-edit.component.ts:

@Component({
    selector: 'user-edit',
    templateUrl: 'app/components/user-edit/user-edit.component.html',
})
export class UserEditComponent implements OnInit {
    form: any;

    errors = [];

    constructor(
        private _formBuilder: FormBuilder,
        private _router: Router,
        private _userService: UserService
    ) {}

    ngOnInit() {
        this.form = this._formBuilder.group({
            'email': ['', Validators.required)],
            'password': ['', Validators.required],
        });
    }

    onSubmit() {
        var self = this;

        this._userService.edit(this.form.value, function (response: Response) {
            console.log('OK');
        }, function (response: Response) {
            console.log('ERROR');
        });
    }
}

user.service.ts:

@Injectable()
export class UserService {
    constructor (
        private _http: Http
    ) {}

    edit(user: User, cfOnNext?: Function, cfOnError?: Function): void {
        let body = JSON.stringify(user);
        let headers = new Headers({
            'Content-Type': 'application/json',
        });
        let options = new RequestOptions({
            headers: headers,
        });

        self._http.put('https://api.dom/me', body, options).subscribe(function (response) {
            if (cfOnNext) {
                cfOnNext(response);
            }
        }, function (response) {
            if (cfOnError) {
                cfOnError(response);
            }
        });
    }
}

Today I want to allow uploading of a photo by simply adding a file type field.

But I found very little information on the subject.

The only solution seems to approach what I want to do is here: https://www.thepolyglotdeveloper.com/2016/02/upload-files-to-node-js-using-angular-2/

Is there a better solution to achieve this? A solution that is closer to my code because I want maximum standardization? For example with the $http Angular service I already use?

Thanks!

tadaa9
  • 523
  • 1
  • 5
  • 10

1 Answers1

2

File Uploading in angular2,

In fact, the Http class doesn't support that at the moment.

You need to leverage the underlying XHR object to do that:

import {Injectable} from 'angular2/core';
import {Observable} from 'rxjs/Rx';

@Injectable()
export class UploadService {
  constructor () {
    this.progress$ = Observable.create(observer => {
      this.progressObserver = observer
    }).share();
  }

  private makeFileRequest (url: string, params: string[], files: File[]): Observable {
    return Observable.create(observer => {
      let formData: FormData = new FormData(),
        xhr: XMLHttpRequest = new XMLHttpRequest();

      for (let i = 0; i < files.length; i++) {
        formData.append("uploads[]", files[i], files[i].name);
      }

      xhr.onreadystatechange = () => {
        if (xhr.readyState === 4) {
          if (xhr.status === 200) {
            observer.next(JSON.parse(xhr.response));
            observer.complete();
          } else {
            observer.error(xhr.response);
          }
        }
      };

      xhr.upload.onprogress = (event) => {
        this.progress = Math.round(event.loaded / event.total * 100);

        this.progressObserver.next(this.progress);
      };

      xhr.open('POST', url, true);
      xhr.send(formData);
    });
  }
}

See this plunkr for more details: https://plnkr.co/edit/ozZqbxIorjQW15BrDFrg?p=info.

There is a an issue and a pending PR regarding this in the Angular repo:

took answer from here

Community
  • 1
  • 1
Pardeep Jain
  • 84,110
  • 37
  • 165
  • 215
  • Answer is exact similar to [this answer](http://stackoverflow.com/a/35985489/2435473) (decto each and every word is copy pasted as is), why don't you mark it as an duplicate.. rather than rewriting it again – Pankaj Parkar Apr 03 '16 at 08:58
  • yeah it is, because i think question is something different from that question so posting as answer. – Pardeep Jain Apr 03 '16 at 09:12
  • Then why don't mark it as duplicate, if you thought it so.. or just add an answer link to comment.. – Pankaj Parkar Apr 03 '16 at 09:15
  • 2
    already told you i don't think this question is exactly similar to that question so not marks this one as duplicate. yeah its my fault i have to post the link instead of answer sorry. – Pardeep Jain Apr 03 '16 at 09:17
  • ya.. I understand it.. even if you are referring to other answer, do try to add an that answer in your own words(what you understood and what you new thing you wanna add it to). don't take it it personally. I just wanted to improve your answer quality & community too.. – Pankaj Parkar Apr 03 '16 at 09:26
  • 2
    hmm sure and thnks alot for commenting, i updated my answer with the link of original answer. from now i take care of this point while answering to questions. – Pardeep Jain Apr 03 '16 at 09:29
  • Thanks for your answer. I'm going with that for now hoping that it will evolve in the near future. – tadaa9 Apr 03 '16 at 10:19