我正在创建一个使用可重用组件来构建表单等的应用程序。我有一个名为DropdownComponent
的子组件,该子组件在表单中多次使用。该组件包含@Input
个指令,这些指令在动态加载服务中使用ComponentFactoryResolver
填充。对于我的一种表单中此子组件的特定实例,我正在进行一个REST
调用,该调用返回一个特定的对象数组,然后使用该对象填充下拉列表。格式与此类似:
[{ "Name": "proj 1", "client":"c1", "lead":"l1"}, { "Name": "proj 2", "client":"c2", "lead":"l2"}, { "Name": "proj 3", "client":"c3", "lead":"l3"}]
我使用此数据中的name
指令填充我的子组件,该子组件在表单上使用@ViewChild('f2', { read: ViewContainerRef }) f2;
显示。到这里为止,一切都很好。但是,我想做的是,每当用户从下拉菜单中选择特定选项时,就会向用户显示2个div(即客户名称和潜在客户名称)如上所示,分别填充了client
和lead
字段。看起来像这样(我们也有URL
字段,但是原理是相同的:
我已经看到了一些解决问题的方法,例如this和this,但它们显示的是在表单内创建而不是作为子组件导入的下拉菜单/选择的解决方案。我不想对下拉组件进行太多更改,因为该组件还有其他实例也不需要此功能,并且可能导致它们发生故障。我无法解决该问题。非常感谢您的帮助。
dropdown.component.ts
import { Component, OnInit, ViewEncapsulation, Input } from '@angular/core';
import { FormGroup } from '@angular/forms';
@Component({
selector: 'app-dropdown',
templateUrl: './dropdown.component.html',
styleUrls: ['./dropdown.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class DropdownComponent implements OnInit {
@Input() group: FormGroup;
@Input() formControlName: string;
@Input() id: string;
@Input() data: any;
@Input() placeholder: string;
constructor() { }
ngOnInit() {
}
}
dropdown.component.html
<div [formGroup]="group">
<select id="{{ id }}" formControlName="{{ formControlName }}" class="form-control">
<option value="" disabled selected>{{placeholder}}</option>
<option *ngFor="let item of data" [ngValue]="item.id">
{{item.name}}
</option>
</select>
</div>
knowledge-base-create.component.ts(包含表单)
//imports
@Component({
selector: 'app-knowledge-base-create',
templateUrl: './knowledge-base-create.component.html',
styleUrls: ['./knowledge-base-create.component.scss']
})
export class KnowledgeBaseCreateComponent implements OnInit, AfterContentInit {
@ViewChild('f1', { read: ViewContainerRef }) f1;
@ViewChild('f2', { read: ViewContainerRef }) f2; //this is the dropdown
@ViewChild('f3', { read: ViewContainerRef }) f3;
@ViewChild('f4', { read: ViewContainerRef }) f4;
projectsList: any; //stores the projects list from rest call
kbForm: FormGroup;
module = "PP_1_Knowledge_Base";
relate_module = "pp_1_projects_pp_1_knowledge_basepp_1_projects_ida";
constructor(//arguments
) { }
ngOnInit() {
this.buildForm();
}
buildForm() {
this.kbForm = this.fb.group({
'f1': ['', Validators.required],
'f2': ['', Validators.required],
'f3': ['', Validators.required],
'f4': ['', Validators.required]
})
}
ngAfterContentInit() {
this.buildf1();
this.buildf3();
this.buildf4();
this.retrieveProjectData();
}
retrieveProjectData() {
this.search.searchCall("PP_1_Projects", "", "", true).subscribe(
response => {
response = response.records;
this.projectsList = response;
this.buildf2();
},
error => {
console.log(error);
}
)
}
goBack() {
this.location.back();
}
buildf1() {
//implementation
}
buildf2() { //this function is for dropdown
let data: any;
if (this.projectsList == undefined) {
data = [
{
"name": ""
}
]
} else {
data = this.projectsList;
}
let array = {
reference: this.f2,
id: "f2",
formControlName: "f2",
group: this.kbForm,
data: data,
placeholder: this.translate.transform("pages[knowledge_base][create][data][placeholder][project_name]")
}
this.dynamicdropdown.loadDropdown(array);
}
buildf3() {// another dropdown implementation
}
buildf4() {
//implementation
}
get form() {
return this.kbForm.controls;
}
postDataToServer() {
//posts data to server
}
}
knowledge-base-create.component.html
<div>
<app-toolbar></app-toolbar>
<app-side-nav></app-side-nav>
<div class="container-fluid">
<div class="card-group">
<div class="card p-4">
<form [formGroup]="kbForm">
<app-button description="{{ 'pages[knowledge_base][buttons][go_back]' | translate }}" class="btn btn-danger btn-md custom" (callFunction)="goBack()"></app-button>
<h2 class="col-md-6">{{ 'pages[knowledge_base][create][heading]' | translate }}</h2>
<div class="col-md-3">
<div #f1 class="input"></div>
<div #f2 class="input"></div> <!-- Want to add divs under here -->
<div #f3 class="input"></div>
</div>
<div class="col-md-6">
<div #f4 class="input"></div>
</div>
<app-button description="{{ 'pages[knowledge_base][buttons][submit]' | translate }}" class="btn btn-success btn-md custom" (callFunction)="postDataToServer()"></app-button>
</form>
</div>
</div>
</div>
</div>
Dynamic-dropdown-service.ts
import { Injectable, ComponentFactoryResolver } from '@angular/core';
import { DropdownComponent } from 'src/app/components/core/dropdown/dropdown.component';
@Injectable({
providedIn: 'root'
})
/**
* This service initialzies the DropdownComponent
*/
export class DynamicDropdownService {
/**
* Initializes the ComponentFactoryResolver
*/
constructor(private resolver: ComponentFactoryResolver) { }
/**
* Takes in array and uses the array items to populate the properties of the DropdownComponent
* Initializes instance of the DropdownComponent
*/
loadDropdown(array) {
let reference = array.reference;
const inputFactory = this.resolver.resolveComponentFactory(DropdownComponent);
const dropdown = reference.createComponent(inputFactory);
dropdown.instance.group = array.group;
dropdown.instance.id = array.id;
dropdown.instance.formControlName = array.formControlName;
dropdown.instance.data = array.data;
dropdown.instance.placeholder = array.placeholder;
}
}