Update a formControl that is a file input in a formArray in Angular2

后端 未结 1 729
清酒与你
清酒与你 2020-12-11 06:47

I have the code below:

import { Component, OnInit, ElementRef } from \'@angular/core\';
import { FormArray, FormBuilder, FormControl, FormGroup, Validators }         


        
相关标签:
1条回答
  • 2020-12-11 07:36

    I also got this problem, but we can deal with file and other form field separately.

    This is my code, I want to post a FormData Object to Django REST API, this formData contains both strings and image, also with user_name and password. I created a component - upload-image-form

    This is what I want to post, an Image class(I define it by myself)

    // images.ts
    export class Image {
    
        constructor(
            public id: number,
            public created: string,  // set by back end
            public userId: number,
            public fileUrl: string,
            public owner: string,
            public des?: string,
            public localImage?: File,
        ) { }
    
    }
    

    This is my component

    // upload-image-form.component.ts
    import { Component, OnInit, Input } from '@angular/core';
    import { NgForm } from '@angular/forms/forms';
    import { FormControl, FormGroup, FormBuilder } from '@angular/forms';
    
    import { Image } from '../image';
    import { User } from '../user';
    import { ImageService } from '../image.service';
    
    
    @Component({
        selector: 'app-upload-image-form',
        templateUrl: './upload-image-form.component.html',
        styleUrls: ['./upload-image-form.component.css']
    })
    export class UploadImageFormComponent implements OnInit {
    
        @Input() user: User;  // this value comes from parent component user-detail's tempolate
        private file: File;
        private formData: FormData = new FormData();
        private imageForm: FormGroup;
        private submitted = false;
        private imageUrl = 'http://192.168.201.211:8024/images/';
        private password: string;
    
        constructor(
            private imageService: ImageService,
            private fb: FormBuilder,
        ) { }
    
        ngOnInit() {
            console.log(this.user);
            this.createFrom(this.user);  // create form here, so we can get this.user's value
        }
    
        createFrom(user: User) {
            // I didn't put file field in this form
            this.imageForm = this.fb.group({
                id: 1,
                created: '20170825',
                userId: user.id,
                fileUrl: 'http://images.fineartamerica.com/images-medium-large-5/mt-shuksan-picture-lake-dennis-romano.jpg',
                owner: user.username,
                des: '',
                pw: '',
            })
            console.log(user);
        }
    
        // https://stackoverflow.com/a/41465502/2803344
        // get a file object from form input
        onChange(event: EventTarget) {
            let eventObj: MSInputMethodContext = <MSInputMethodContext> event;
            let target: HTMLInputElement = <HTMLInputElement> eventObj.target;
            let files: FileList = target.files;
            this.file = files[0];
        }
    
        onSubmit() {
            // deal with string fields and file separately
            this.submitted = true;
            console.log(this.file);  // file is here, captured by onChange()
            console.log(this.imageForm.value);  // other fields are here, captured by formGroup
    
            this.formData.append('localImage', this.file, this.file.name);
            for (let item in this.imageForm.value) {
                console.log(item)
                if (item !== 'pw') {
                    this.formData.append(item, this.imageForm.value[item]);
                }
                else {
                    this.password = this.imageForm.value[item];
                }
    
            }
    
            // console.log('###here is the total form data');
            console.log(this.formData);
            console.log(this.formData.get('fileUrl'));
            console.log(this.user.username);
            this.imageService.post(this.formData, this.user.username, this.password)
                             .then(res =>{
                               console.log(res);
                             });
        }
    
        onClick(form: FormGroup) {
            form.reset({
                userId: this.user.id,
                owner: this.user.username,
                created: '20170825',
                fileUrl: 'http://www.fujifilm.com.sg/Products/digital_cameras/x/fujifilm_x_t1/sample_images/img/index/ff_x_t1_001.JPG',
            })
            this.submitted=false;
            console.log(form.value);
        }
    
    }
    

    This is my template

    <!-- upload-image-form.component.html -->
    <div [hidden]="submitted" *ngIf="user">
    
        <h2>Upload New Image</h2>
    
        <form [formGroup]="imageForm" (ngSubmit)="onSubmit()" >
            <div class="form-group">
                <label for="fileUrl">File Url</label>
                <input type="url" class="form-control" id="fileUrl" 
                formControlName="fileUrl" required>
                <div [hidden]="imageForm.get('fileUrl').valid || imageForm.get('fileUrl').pristine" 
                      class="alert alert-danger">
                  File Url is required
                </div>
                <p>{{imageForm.get('fileUrl').valid | json}}</p>
                <p>{{imageForm.get('fileUrl').value | json}}</p>
            </div>
            <!-- upload an image 
            don't define this field in formGroup-->
            <div class="form-group">
                <label for="localImage">Local File</label>
                <input type="file" class="form-control" id="localImage"
                (change)="onChange($event)" accept=".jpg, .png" >
            </div>
            <div class="form-group">
                <label for="des">Description</label>
                <input type="text" class="form-control" id="des" 
                formControlName="des">
            </div>
            <div class="form-group">
                <label for="userId">User ID</label>
                <input type="text" class="form-control" id="userId" 
                formControlName="userId" readonly>
                <p>{{imageForm.get('userId').value | json}}</p>
            </div>
            <div class="form-group">
                <label for="owner">Owner</label>
                <input type="text" class="form-control" id="owner"
                formControlName="owner" readonly>
            </div>
            <!-- input user's password -->
            <div class="form-group">
                <label for="pw">password</label>
                <input type="password" class="form-control" id="pw"
                formControlName="pw" required>
            </div>
            <button type="submit" class="btn btn-success" [disabled]="!imageForm.valid">Submit</button>
        </form>
    </div>
    

    At last, this is my image service

    // image.service.ts
    import { Injectable } from '@angular/core';
    import { Headers, Http, RequestOptions } from "@angular/http";
    
    import 'rxjs/add/operator/toPromise';
    
    import { Image } from "./image";
    import { User } from './user';
    
    @Injectable()
    export class ImageService {
    
        private imageUrl = 'http://192.168.201.211:8024/images/';
        //set headers for authorization, https://stackoverflow.com/a/34465070/2803344
        createAuthorizationHeader(headers: Headers, name: string, pw: string) {
            headers.append('Authorization', 'Basic ' +
              btoa(`${name}:${pw}`)); 
        }
    
        createOptions(name: string, pw: string) {
            let headers = new Headers();
            this.createAuthorizationHeader(headers, name, pw);
            // headers.append('Content-Type', 'application/json');  // without this
            // headers.append('Content-Type', 'multipart/form-data');  // without this
            let options = new RequestOptions({ headers: headers });
            return options;
        }
    
        constructor(private http: Http) { }
    
        getImageById(id: number): Promise<Image> {
            const url = `${this.imageUrl}`;
            console.log(url);
            let headers = new Headers();
            let token = 'token';
            headers.append('X-Auth-Token', token);
            return this.http.get(url, {headers: headers})
                            .toPromise()
                            // .then(res => res.json().data as Image)
                            .then(res => console.log(res))
                            .catch(this.handleError);
        }
    
        getImageByUrl(url: string): Promise<Image> {
            return this.http.get(url)
                          .toPromise()
                          .then(res => res.json() as Image)
                          // .then(res => console.log(res))
                          .catch(this.handleError);
        }
    
        post(formData: FormData, user: string, pw: string): Promise<Image> {
            let options = this.createOptions(user, pw);
            console.log('we will have a post!');
            console.log(formData.get('localImage'));
            console.log(formData.get('fileUrl'));
            console.log(formData.get('des'));
            return this.http.post(this.imageUrl, formData, options)
                            .toPromise()
                            .then(res => res.json() as Image)
                            .catch(this.handleError);
        }
    
        private handleError(error: any): Promise<any> {
            console.error('An error occurred', error); // for demo purposes only
            return Promise.reject(error.message || error);
        }
    }
    

    You can find the whole project in github, https://github.com/OnlyBelter/image-sharing-system2.

    0 讨论(0)
提交回复
热议问题