我有这种情况:
这是我的FieldDefinition
export interface FieldDefinition {
key: string,
type: string,
isId: boolean,
label: string,
required: boolean
}
这是动态字段定义
<div *ngSwitchCase="'string'" class="form-group">
<label [htmlFor]="field.key">{{ field.label }}</label>
<textarea class="form-control" [formControlName]="field.key" [id]="field.key"
[readonly]="operation == 'details' || field.isId"></textarea>
</div>
<div *ngSwitchCase="'number'" class="form-group">
<label [htmlFor]="field.key">{{ field.label }}</label>
<input class="form-control" [formControlName]="field.key" [id]="field.key"
[readonly]="operation == 'details' || field.isId"
type="number">
</div>
<div *ngSwitchCase="'[]'" class="form-group">
<label [htmlFor]="field.key">{{ field.label }}</label>
<select [id]="field.key"
[formControlName]="field.key">
<option *ngFor="let opt of field.options"
[value]="opt.key">
{{opt.value}}
</option>
</select>
</div>
<div *ngIf="form.get(field.key).hasError('required') && (submitted || form.get(field.key).touched)"
class="alert alert-danger">
{{ field.label }} is required.
</div>
</div>
</div>
ts文件:
import { Component, Input, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { FieldDefinition } from '../field-definition';
@Component({
selector: 'fw-dynamic-field',
templateUrl: './dynamic-field.component.html',
styleUrls: ['./dynamic-field.component.css']
})
export class DynamicFieldComponent {
@Input() field: FieldDefinition;
@Input() form: FormGroup;
@Input() operation: string;
@Input() submitted: boolean;
get isValid() { return this.form.controls[this.field.key].valid; }
constructor() { }
}
动态表单html
<form (ngSubmit)="onSubmit()" [formGroup]="form">
<div *ngFor="let field of vmDefinition">
<fw-dynamic-field [field]="field"
[form]="form"
[operation]="operation"
[submitted]="submitted">
</fw-dynamic-field>
</div>
<div *ngIf="errorMessage " class="alert alert-danger">
{{ errorMessage }}
</div>
<div *ngIf="status != 'waiting'">
<div *ngIf="operation === 'details'">
<button type="button" class="btn" (click)="onBack()" >Back</button>
<button type="button" class="btn btn-primary" (click)="onEdit()" >Edit</button>
</div>
<div *ngIf="operation === 'edit'">
<button type="button" class="btn" (click)="onCancel()" >Cancel</button>
<button type="button" class="btn btn-primary" (click)="onSave()" >Save</button>
</div>
<div *ngIf="operation === 'create'">
<button type="button" class="btn" (click)="onBack()" >Back</button>
<button type="button" class="btn btn-primary" (click)="onCreate()" >Create</button>
</div>
</div>
</form>
和ts文件:
export class DynamicFormComponent implements OnChanges, OnInit {
@Input() vm: any;
@Input() vmDefinition: Array<FieldDefinition>;
@Input() operation: string;
@Input() errorMessage: string;
@Output() update: EventEmitter<any> = new EventEmitter();
@Output() create: EventEmitter<any> = new EventEmitter();
form: FormGroup;
status: string;
submitted = false;
vmCopy: any;
constructor(private router: Router,
private route: ActivatedRoute,
private location: Location) { }
clearForm() {
const group = {};
this.vmCopy = Object.assign({}, this.vm);
this.vmDefinition.forEach(field => {
group[field.key] = field.required ? new FormControl(this.vmCopy[field.key], Validators.required)
: new FormControl(this.vmCopy[field.key]);
});
this.form = new FormGroup(group);
}
ngOnChanges(changes: SimpleChanges) {
if (changes['errorMessage'].currentValue && this.status === 'waiting') {
this.status = '';
}
}
ngOnInit() {
this.clearForm();
this.route.params.subscribe(params => {
this.operation = params['operation'];
this.clearForm();
});
}
我试图在我的图书详细信息页面中使用此动态表单,但我在填充下拉列表时遇到问题
export class BookDetailComponent implements OnInit {
book: Book;
books: IBook[];
authors: IAuthor[];
categories: ICategory[];
errorMessage: string;
bookDefinition: Array<FieldDefinition> = [
{
key: 'bookId',
type: 'number',
isId: true,
label: 'BookId',
required: true
},
{
key: 'title',
type: 'string',
isId: false,
label: 'Title',
required: true
},
{
key: 'authors',
type: '[]',
isId: false,
label: 'Authors',
required: false
},
{
key: 'categories',
type: '[]',
isId: false,
label: 'Categories',
required: false
}
];
operation: string;
constructor(private route: ActivatedRoute,
private router: Router,
private bookService: BookService,
private authorService: AuthorService,
private categoryService: CategoryService) { }
ngOnInit(): void {
this.operation = this.route.snapshot.params['operation'];
this.authorService.getAuthors()
.subscribe((authors: IAuthor[]) => { this.authors = authors });
this.categoryService.getCategories()
.subscribe((categories: ICategory[]) => { this.categories = categories });
if (this.operation === 'create') {
this.book = { bookId: 0, title: '', authors: this.authors, categories:
this.categories };
} else {
this.bookService.getBook(this.route.snapshot.params['id'])
.subscribe((book: Book) => { this.book = book });
}
}
在book-detail-component.html中我有这个
<h3>Book</h3>
<fw-dynamic-form *ngIf='book' [vm]="book" [vmDefinition]="bookDefinition"
[operation]="operation"
[errorMessage]="errorMessage"
(update)="updateBook($event)"
(create)="createBook($event)">
它与其他字段一起工作正常,但我对作者和类别的下拉列表有问题。首先,如何在一个订阅中进行getAuthors和getCategories调用?然后我如何将值附加到下拉列表中?我应该创建一个dropdownField并将其设置为字段类型?因为我现在没有现场选项属性.. 非常感谢!
更新:
我创造了这个:
import { FieldDefinition } from './field-definition';
export class DropdownField extends FieldDefinition {
type: 'dropdown';
options: { key: number, value: string }[] = [];
constructor(options: {} = {}) {
super();
this.options = options['options'] || [];
}
}
我尝试在book-detail-component中使用它来填充作者的下拉列表和类别的下拉列表
ngOnInit(): void {
this.operation = this.route.snapshot.params['operation'];
this.authorService.getAuthors()
.subscribe((authors: IAuthor[]) => {
this.authors = authors,
authors.forEach(function (author) {
this.authorDropdown.options = [{ key: this.author.authorId, value: this.author.authorName }]
});
});
this.categoryService.getCategories()
.subscribe((categories: ICategory[]) => { this.categories = categories, console.log(this.categories) });
if (this.operation === 'create') {
this.book = { bookId: 0, title: '', authors: this.authorDropdown, categories: this.categories };
} else {
this.bookService.getBook(this.route.snapshot.params['id'])
.subscribe((book: Book) => { this.book = book });
}
}
仍然无法工作..
更新2
export class BookDetailComponent implements OnInit {
book: Book;
author: Author;
books: IBook[];
authors: IAuthor[];
categories: ICategory[];
errorMessage: string;
bookDefinition: Array<FieldDefinition> = [
{
key: 'bookId',
type: 'number',
isId: true,
label: 'BookId',
required: true
},
{
key: 'title',
type: 'string',
isId: false,
label: 'Title',
required: true
},
{
key: 'authors',
type: '[]',
isId: false,
label: 'Authors',
required: false
},
{
key: 'categories',
type: '[]',
isId: false,
label: 'Categories',
required: false
}
];
operation: string;
authorDropdown: DropdownField;
categoryDropdown: DropdownField;
constructor(private route: ActivatedRoute,
private router: Router,
private bookService: BookService,
private authorService: AuthorService,
private categoryService: CategoryService) { }
ngOnInit(): void {
this.operation = this.route.snapshot.params['operation'];
this.authorService.getAuthors()
.subscribe((authors: IAuthor[]) => {
this.authors = authors,
authors.forEach(function (author) {
this.authorDropdown.options.push({ key: this.author.authorId, value: this.author.authorName });
});
console.log(this.authorDropdown);
});
if (this.operation === 'create') {
this.book = { bookId: 0, title: '', authors: this.authorDropdown, categories: [] };
} else {
this.bookService.getBook(this.route.snapshot.params['id'])
.subscribe((book: Book) => { this.book = book });;
}
}
答案 0 :(得分:0)
这是正确的方法,您的代码只是在迭代作者数组时添加最后一个元素,现在您将使用{{1}在this.authorDropdown.options
附加作者的每个元素}}
push