在Angular2中更新formArray中的文件输入formControl [英] Update a formControl that is a file input in a formArray in Angular2
问题描述
我有以下代码:
$ b
从'@ angular / core'导入{Component,OnInit,ElementRef};
从'@ angular / forms'导入{FormArray,FormBuilder,FormControl,FormGroup,Validators}
$ b @Component({
selector:'app-root',
templateUrl:'./app.component.html',
styleUrls:['./app.component.css']
})
导出类AppComponent实现OnInit {
showSort:boolean = false;
form:FormGroup;
名称:FormControl;
sortSelf:FormControl;
sortItem:FormArray;
locationItems:FormArray;
构造函数(private _fb:FormBuilder,private _elementRef:ElementRef){
}
ngOnInit():void {
this.sortItem = this。 _fb.array([this.initSort()]);
this.form = this._fb.group({
sortItem:this.sortItem
});
initSort(){
return this._fb.group({
locationPicture:new FormControl('',[]),
locationItems :this._fb.array([
this.initSortItems()
])
})
}
initSortItems(){
返回this._fb.group({
itemPicture:new FormControl('',[])
})
}
addSort(){
this.sortItem.push(this.initSort());
}
addSortLocationItem(i ?: number,t ?: number){
const control:FormArray =< FormArray> this.sortItem.at(ⅰ)获得( locationItems’);
control.push(this.initSortItems());
$ b $ showImage(event,level ?: string,i ?: number,t ?: number){
let file = event.target.files [0];
if(level ==='locationPicture'){
(< FormArray> this.sortItem.at(i))。controls ['locationPicture']。setValue(file,{onlySelf:true} ); (t).get('itemPicture')。setValue(file,{
} else {
(< FormArray> this.sortItem.at(i).get('locationItems'))。 onlySelf:true});
next(value,valid:boolean){
console.log(`this is value $ {JSON.stringify(value,null,4 )}`);
$ / code $ / pre
$ b $ p < div class =col-md-8 col-md-offset-2>
< form class =action =index.htmlmethod =post[formGroup] =form(ngSubmit)=next(form.value,form.valid)>
< div class =form-group>
< div formArrayName =sortItemclass =>
< div class =top-buffer-small>
< a(click)=addSort()style =cursor:default>
添加排序位置+
< / a>
< / div>
< div * ngFor =let sortLocation of sortItem.controls; let i = index>
< div [formGroupName] =iclass =>
< div class =form-group>
< label>位置图片< / label>
< input type =fileformControlName =locationPictureclass =form-control locationPictureaccept =image / *capture =camera(change)=showImage($ event,'locationPicture' ,i,t)>
<! - < input type =fileformControlName =locationPicture(change)=showImage($ event)/> - >
< img src =alt =class =location-imagewidth =80height =80>
图片为必填项
< / div>
< div formArrayName =locationItemsclass =col-md-10 col-md-offset-1>
< div class =row>
< a(click)=addSortLocationItem(i,t)style =cursor:default>
添加商品+
< / a>
< / div>
<! - < div class =from-group* ngFor =let each.tem of form.controls.sortItem.controls [i] .controls.locationItems.controls; let t = index> - >
< div class =form-group* ngFor =let eachItem of sortLocation.get('locationItems')。controls; let t = index>
< div [formGroupName] =t>
< div class =form-group>
< label>项目图片< / label>
< input type =fileformControlName =itemPictureclass =form-control itemPicturecapture =camera(change)=showImage($ event,'itemPicture',i,t)> ;
< img src =alt =class =item-imagewidth =80height =80>
图片为必填项
< / div>
< / div>
< / div>
< / div>
< div class =clearfix>< / div>
< / div>
< / div>
< / div>
< / div>
< div class =text-center>
< button type =submitname =buttonclass =btn btn-primary[disabled] =form.invalid> Submit< / button>
< / div>
< / form>
< / div>
我试图通过更新formcontrol值来更新showImage方法中的表单。但是,我无法获得用于更新图片的表单。当我尝试上传到'locationPicture'和'itemPicture'时,出现以下错误:
无法设置HTMLInputElement上的'value'属性:该输入元素接受一个文件名,该文件名只能通过编程方式设置为空字符串。
任何帮助都会很棒
file 和其他表单域。
这是我的代码,我想发布一个 FormData对象
到Django REST API,这个 formData
同时包含字符串和图片,同时包含 user_name
和密码
。我创建了一个组件 - upload-image-form
这是我想发布的内容, Image
class(我自己定义)
// images.ts
export class Image {
构造函数(
public id:number,
public created:string,//由后端设置
public userId:number,
public fileUrl:string,
public owner:string,
public des ?: string,
public localImage ?: File,
){}
$ / code $ / pre
这是我的组件
<$ p @ p> // upload-image-form.component.ts
从'@ angular / core'导入{Component,OnInit,Input};
从'@ angular / forms / forms'导入{NgForm};
从'@ angular / forms'导入{FormControl,FormGroup,FormBuilder};
从'../image'导入{Image};
从'../user'导入{User};
从'../image.service'中导入{ImageService};
@Component({
selector:'app-upload-image-form',
templateUrl:'./upload-image-form.component.html ',
styleUrls:['./upload-image-form.component.css']
})
导出类UploadImageFormComponent实现OnInit {
@Input( )用户:用户; //这个值来自父组件user-detail的tempolate
私有文件:File;
private formData:FormData = new FormData();
private imageForm:FormGroup;
private submitted = false;
private imageUrl ='http://192.168.201.211:8024/images/';
私人密码:字符串;
构造函数(
private imageService:ImageService,
private fb:FormBuilder,
){}
ngOnInit(){
console.log(this.user);
this.createFrom(this.user); //在这里创建表单,所以我们可以得到this.user的值
}
createFrom(user:User){
//我没有在这个表单中放置文件字段
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',
所有者:user.username,
des:' ',
pw:'',
})
console.log(user);
// https://stackoverflow.com/a/41465502/2803344
//从表单输入获取文件对象
onChange(event:EventTarget ){
let eventObj:MSInputMethodContext =< MSInputMethodContext>事件;
let target:HTMLInputElement =< HTMLInputElement> eventObj.target;
让文件:FileList = target.files;
this.file = files [0];
onSubmit(){
//分别处理字符串字段和文件
this.submitted = true;
console.log(this.file); //文件在这里,由onChange()捕获
console.log(this.imageForm.value); //其他字段在这里,由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('###这里是整个表单数据');
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);
}
}
这是我的模板
<! - upload-image-form.component.html - >
< div [hidden] =submitted* ngIf =user>
< h2>上载新图片< / h2>
< form [formGroup] =imageForm(ngSubmit)=onSubmit()>
< div class =form-group>
< label for =fileUrl>档案网址< / label>
< input type =urlclass =form-controlid =fileUrl
formControlName =fileUrlrequired>
< div [hidden] =imageForm.get('fileUrl')。valid || imageForm.get('fileUrl')。pristine
class =alert alert-danger>
档案URL必须为
< / div>
< p> {{imageForm.get('fileUrl')。valid | JSON}}< / p为H.
< p> {{imageForm.get('fileUrl')。value | JSON}}< / p为H.
< / div>
<! - 上传图片
不在formGroup中定义此字段 - >
< div class =form-group>
< label for =localImage>本地文件< / label>
< input type =fileclass =form-controlid =localImage
(change)=onChange($ event)accept =。jpg,.png>
< / div>
< div class =form-group>
< label for =des>描述< / label>
< input type =textclass =form-controlid =des
formControlName =des>
< / div>
< div class =form-group>
< label for =userId>用户ID< / label>
< input type =textclass =form-controlid =userId
formControlName =userIdreadonly>
< p> {{imageForm.get('userId')。value | JSON}}< / p为H.
< / div>
< div class =form-group>
< label for =owner>所有者< / label>
< input type =textclass =form-controlid =owner
formControlName =ownerreadonly>
< / div>
<! - 输入用户密码 - >
< div class =form-group>
< label for =pw>密码< / label>
< input type =passwordclass =form-controlid =pw
formControlName =pwrequired>
< / div>
< button type =submitclass =btn btn-success[disabled] =!imageForm.valid>提交< / button>
< / form>
< / div>
最后,这是我的图片服务
// image.service.ts
从'@ angular / core'导入{Injectable};
从@ angular / http导入{Headers,Http,RequestOptions};
导入'rxjs / add / operator / toPromise';
从./image中导入{Image};
从'./user'导入{User};
@Injectable()
导出类ImageService {
private imageUrl ='http://192.168.201.211:8024/images/';
//为授权设置标头,https://stackoverflow.com/a/34465070/2803344
createAuthorizationHeader(标题:标题,名称:字符串,pw:字符串){
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'); //没有这个
// headers.append('Content-Type','multipart / form-data'); //没有这个
let options = new RequestOptions({headers:headers});
返回选项;
}
构造函数(private http:Http){}
getImageById(id:number):Promise< Image> {
const url =`$ {this.imageUrl}`;
console.log(url);
let headers = new Headers();
让令牌='令牌';
headers.append('X-Auth-Token',令牌);
返回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> {
返回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('我们将有一个帖子!');
console.log(formData.get('localImage'));
console.log(formData.get('fileUrl'));
console.log(formData.get('des'));
返回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('发生错误,错误); //仅用于演示目的
返回Promise.reject(error.message || error);
$ / code $ / pre
您可以在github中找到整个项目 https://github.com/OnlyBelter/image-sharing-system2 。
I have the code below:
import { Component, OnInit, ElementRef } from '@angular/core';
import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
showSort: boolean = false;
form: FormGroup;
name: FormControl;
sortSelf: FormControl;
sortItem: FormArray;
locationItems: FormArray;
constructor(private _fb: FormBuilder, private _elementRef: ElementRef ) {
}
ngOnInit(): void {
this.sortItem = this._fb.array([this.initSort()]);
this.form = this._fb.group({
sortItem: this.sortItem
});
}
initSort() {
return this._fb.group({
locationPicture: new FormControl('', []),
locationItems: this._fb.array([
this.initSortItems()
])
})
}
initSortItems() {
return this._fb.group({
itemPicture: new FormControl('', [])
})
}
addSort() {
this.sortItem.push(this.initSort());
}
addSortLocationItem(i?: number, t?: number) {
const control: FormArray = <FormArray> this.sortItem.at(i).get('locationItems');
control.push(this.initSortItems());
}
showImage(event, level?: string, i?: number, t?: number){
let file = event.target.files[0];
if(level === 'locationPicture'){
(<FormArray>this.sortItem.at(i)).controls['locationPicture'].setValue(file, {onlySelf: true});
}else{
(<FormArray>this.sortItem.at(i).get('locationItems')).at(t).get('itemPicture').setValue(file, {onlySelf: true});
}
}
next(value, valid: boolean){
console.log(`this is value ${JSON.stringify(value, null, 4)}`);
}
}
Mark Up:
<div class="col-md-8 col-md-offset-2">
<form class="" action="index.html" method="post" [formGroup]="form" (ngSubmit)="next(form.value, form.valid)">
<div class="form-group">
<div formArrayName="sortItem" class="">
<div class="top-buffer-small">
<a (click)="addSort()" style="cursor: default">
Add Sort Location +
</a>
</div>
<div *ngFor="let sortLocation of sortItem.controls; let i=index">
<div [formGroupName]="i" class="">
<div class="form-group">
<label>Location Picture</label>
<input type="file" formControlName="locationPicture" class="form-control locationPicture" accept="image/*" capture="camera" (change)="showImage($event, 'locationPicture', i, t)">
<!-- <input type="file" formControlName="locationPicture" (change)="showImage($event)" /> -->
<img src="" alt="" class="location-image" width="80" height="80">
<small class="form-text text-muted" [hidden]="sortItem.controls[i].controls.locationPicture.valid">
Picture is required
</small>
</div>
<div formArrayName="locationItems" class="col-md-10 col-md-offset-1">
<div class="row">
<a (click)="addSortLocationItem(i,t)" style="cursor: default">
Add Item +
</a>
</div>
<!-- <div class="from-group" *ngFor="let eachItem of form.controls.sortItem.controls[i].controls.locationItems.controls; let t=index"> -->
<div class="form-group" *ngFor="let eachItem of sortLocation.get('locationItems').controls; let t=index">
<div [formGroupName]="t">
<div class="form-group">
<label>Item Picture</label>
<input type="file" formControlName="itemPicture" class="form-control itemPicture" capture="camera" (change)="showImage($event, 'itemPicture', i, t)">
<img src="" alt="" class="item-image" width="80" height="80">
<small class="form-text text-muted" [hidden]="sortItem.controls[i].controls.locationItems.controls[t].controls.itemPicture.valid">
Picture is required
</small>
</div>
</div>
</div>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
<div class="text-center">
<button type="submit" name="button" class="btn btn-primary" [disabled]="form.invalid">Submit</button>
</div>
</form>
</div>
I am trying to update the form within the showImage method by updating the formcontrol values. However, I cannot get the form to update with the picture. When I try to upload it on the 'locationPicture' and 'itemPicture', I get the following error:
Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string.
Please any help with this will be great
解决方案 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.
这篇关于在Angular2中更新formArray中的文件输入formControl的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文