3

foreword

A module needs to be implemented in the project, task management, and the tasks here are diverse. For example, vaccination is a task. We first establish this task, and then specify several fields in the task, such as the location, time, and brand of vaccination. Caring for the elderly is another task, and the task also stipulates several fields, when to care for the elderly, behavior records, etc. The time selection component is required for vaccination time and the time to care for the elderly, the list selection component is required for the vaccination location and vaccination brand, and the text input component is required for behavior records. Different fields require different input components.

ER diagram

image.png
A task corresponds to multiple form items, and a form item has a form type. A task corresponds to each resident to generate a task detail, and a form item and a task detail together correspond to a form value. For example, vaccination is a task, the time of vaccination, the location of vaccination is the form item, the time of vaccination (form item) corresponds to the form type is time (form type), the location of vaccination (form item) corresponds to the form type is a one-way selection (form type). The task of vaccination corresponds to Zhang San (resident) generating Zhang San’s vaccination task (task details), corresponding to Li Si (resident) generating Li Si’s vaccination task (task details), and Zhang San’s vaccination task (task details). The time (form item) is March 18, 2022 (form value), and the vaccination time (form item) of the Li Sit vaccine task (task details) is March 10, 2022 (form value).

dynamic form

It is very simple to set up multiple form items for a task. It is nothing more than selecting the form type of the form item, such as text, time, single choice, multiple choice, etc. The question is how to display different input methods depending on the form type. For example, if the form type is time, a time selector will be displayed, and if the form type is text, an input box will be displayed. Of course, we can judge according to the form type. Different form types display different components, as shown in the following figure.
image.png
But this means that if we add a new form type in the future, we have to add an if, that is, change the code once, which is obviously not what we want.
Angular has the function of dynamic form, which helps us get rid of complicated if judgment (when adding a new form type, dynamic form also needs to change the code, such as adding a form type corresponding component).
First we need to define a directive, the role of this directive is to mark a location to tell angular where to insert the component.

@Directive({
  selector: '[FormItem]',
})
export class FormDirective {
  constructor(public viewContainerRef: ViewContainerRef) { }
}

Then we create the main page component v layer

<p>form-detial works!</p>
<div class="ad-banner-example">
  <h3>任务详情</h3>
  <ng-template FormItem></ng-template>
</div>

We put the directive named FormItem we defined into the ng-template tag. ng-template is an empty container and will not have any negative effects.
main page c layer

export class IndexComponent implements OnInit, OnDestroy {

  formItems: FormItem[] = [];

  @ViewChild(FormDirective, {static: true}) adHost!: FormDirective;
  interval: number|undefined;

  constructor(private formService: FormService) {}

  ngOnInit() {
    this.formItems = this.formService.getFormData();
    this.loadComponent();

  }

  ngOnDestroy() {
    clearInterval(this.interval);
  }

  loadComponent() {
    for (var i = 0; i < this.formItems.length; i++) {
      const adItem = this.formItems[i];

      const viewContainerRef = this.adHost.viewContainerRef;

      const componentRef = viewContainerRef.createComponent<FormComponent>(adItem.component);
      componentRef.instance.data = adItem.data;
    }
  }
}

During initialization, first obtain the form item array through the service layer, then loop through each form item, and finally load the component corresponding to the form item type through the createComponent() method of viewContainerRef.
For different form type input components, we first specify a common parent interface.

export interface FormComponent {
  data: any;
}

All form type input components inherit this interface, such as radio form types

@Component({
  selector: 'app-select',
  templateUrl: '
  <p>{{data.text}}</p>
  <select  class="custom-select" id="inputGroupSelect02">
    <option *ngFor="let selection of data.selections" [value]="selection.value">{{selection.name}}</option>
  </select>
    ',
  styleUrls: ['./select.component.css']
})
export class SelectComponent implements OnInit, FormComponent {

  constructor() { }

  ngOnInit(): void {
  }

  @Input() data: any;
}

text form type

@Component({
  selector: 'app-text',
  templateUrl: '
  <p>{{data.text}}</p>
  <input type="text">
    ',
  styleUrls: ['./text.component.css']
})
export class TextComponent implements OnInit, FormComponent {

  constructor() { }

  ngOnInit(): void {
  }

  @Input() data: any;
}

inheritance relationship
image.png
final effect
image.png


小强Zzz
1.2k 声望32 粉丝