Как создать Angular 2 Custom Component с несколькими полями ввода

1

Я создал простой пользовательский компонент в Angular 2, реализовав интерфейс CustomValueAccessor и он отлично работает. Этот компонент имеет только 1 поле ввода в нем. например, компонент почтового индекса

 <postcode label="Post Code" cssClass="form-control" formControlName="postcode"> </postcode>

Теперь я хочу расширить этот пример и создать компонент адреса, который имеет несколько полей ввода, line1, line 2, line3, postcode и country.

Я расширил пример почтового индекса, чтобы включить несколько полей, и я вижу, как компонент ввода появляется на экране. Однако значения компонент адреса не отражаются в форме хоста.

Оцените любой указатель в этом направлении.

Пример:

import { Component, OnInit, Input } from '@angular/core';
import { FormControl, FormGroup, ControlValueAccessor, FormBuilder, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
import { Subscription } from 'rxjs/Subscription';

@Component({
  selector: 'address',
  templateUrl: './address.component.html',
  styleUrls: ['./address.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: CommonAddressComponent,
      multi: true
    }
  ]
})

export class CommonAddressComponent implements OnInit , ControlValueAccessor {
  addressForm :  FormGroup

  ngOnInit() {
    this.addressForm = this.formBuilder.group({
      line_1: '',
      line_2: '',

    });
  }

  /*private addressForm = new FormControl()*/

  private subscription: Subscription;
  public disabled: any = false;

  constructor(private formBuilder: FormBuilder) { }

  //model to view
  writeValue(value: any) {
    console.log("value = " + value)
    this.addressForm.setValue(value); 
  }

  registerOnChange(fn: (value: any) => void) {
    console.log("registerOnChange = " + fn)

    this.addressForm.valueChanges.subscribe(fn);
  }

  registerOnTouched() {}


}

Файл шаблона:

<div class="form-group" [formGroup]="addressForm">
  <input class="form-control" type="text" formControlName="line_1" />
  <input  class="form-control" type="text" formControlName="line_2" />
</div>

Файл компонента формы хоста:

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


@Component({
  selector: 'app-contacts',
  templateUrl: './contacts.component.html',
  styleUrls: ['./contacts.component.scss']
})
export class ContactsComponent implements OnInit {

  contactsForm: FormGroup;

  constructor(private fb: FormBuilder) {
     this.createForm();
   }

   createForm() {
    this.contactsForm = this.fb.group({
      name: 'test', // <--- the FormControl called "name"
      postcode: 'tester111', // <--- the FormControl called "name"
      line_3: '111', // <--- the FormControl called "name"*/
      addressForm: new FormGroup({
              line_1: new FormControl('I am line 1', Validators.minLength(2)),
              line_2: new FormControl('I am line 2')

            }),
    });
  }

  ngOnInit() {
  }

}

Файл шаблона формы хоста:

<form [formGroup]="contactsForm">

  <p>Form value: {{ contactsForm.value | json }}</p>
  <p>Form status: {{ contactsForm.status | json }}</p>


   <div class="form-group">
    <label class="center-block">Name:
      <input class="form-control" formControlName="name">
    </label>
  </div>

    <div>
      <postcode label="Post Code" cssClass="form-control" formControlName="postcode"> </postcode>
    </div>

    <div class="form-group">
    <address-line  cssClass="form-control" name="line3" label="line 3" elementName="line3" 
      elementID="line3" formControlName="line_3"> </address-line>
    </div>

     <!--<div [formGroup]="contactsForm.addressForm"> -->
    <div >
      <address formGroupName="addressForm"> </address>
    </div>

  </form>
  • 0
    Вы не повторяете addressForm дважды?
  • 0
    Нет. Один использовался в классе пользовательских компонентов, а другой - внутри формы хоста. В случае простых компонентов, то есть только одного поля ввода, formcontrol повторяется следующим образом.
Теги:
angular
form-control

1 ответ

2

После нескольких попыток я смог получить настраиваемый элемент управления с несколькими полями ввода в режиме "Угловая". Код для этого:

  1. Пользовательский компонент с несколькими полями ввода

    import { Component, OnInit, Input, ViewChild } from '@angular/core';
    import { FormControl,NgForm, FormGroup, ControlValueAccessor, FormBuilder, NG_VALUE_ACCESSOR, Validators, NgModel } from '@angular/forms';
    import { Subscription } from 'rxjs/Subscription';
    
    @Component({
      selector: 'address',
      templateUrl: './address.component.html',
      styleUrls: ['./address.component.scss'],
      providers: [
        {
          provide: NG_VALUE_ACCESSOR,
          useExisting: AddressComponent,
          multi: true
        }
      ]
    })
    
    export class AddressComponent implements OnInit , ControlValueAccessor {
    
       addressForm :  FormGroup
    
       @Input() label: string;
    
      constructor(private formBuilder: FormBuilder) { }
    
      ngOnInit() {
        this.addressForm = this.formBuilder.group({
          line1: '',
          line2: '',
           line3: '',
            line4: '',
        });
      }
    
    
      writeValue(value: any) {
        if (value) {
          this.addressForm.setValue(value);
        }
      }
    
      registerOnChange(fn: (value: any) => void) {
        console.log("registerOnChange = " + fn)
        this.addressForm.valueChanges.subscribe(fn);
      }
     registerOnTouched() {}
    

    }

  2. Шаблон пользовательского компонента

Код шаблона

<div class="form-group" [formGroup]="addressForm">
  <input type="text" name="line1" class="form-control" type="text" formControlName="line1" />
  <input type="text" name="line2" class="form-control" type="text" formControlName="line2" />
  <input type="text" name="line3" class="form-control" type="text" formControlName="line3" />
  <input type="text" name="line4" class="form-control" type="text" formControlName="line4" />
</div>
  1. Класс Host или родительский компонент

    import {Component} из '@angular/core'; импортировать {NgForm, Validators, FormControl, FormGroup} из '@angular/forms';

    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css']
    })
    export class AppComponent {
    
     pageForm: FormGroup = new FormGroup({
      address: new FormGroup({
         line1: new FormControl('',Validators.required),
         line2: new FormControl('',Validators.required),
         line3: new FormControl('',Validators.required),
         line4: new FormControl('')
       }),
     })
    
    }
    
    4.

<div class="container">
  <form [formGroup]="pageForm">
    <p>Form value: {{ pageForm.value | json }}</p>
    <p>Form status: {{ pageForm.status | json }}</p>

    <address  label="Line 1" formControlName="address" > </address>

  </form>
</div>
  • 0
    Здравствуйте, я читаю ваше решение и пытаюсь его реализовать. Это вроде работает, но у меня есть странная ошибка: control.registerOnChange не является функцией. Похоже, это связано с тем, что я связываю formControlName с FormGroup (в вашем примере это то же самое: адрес является FormGroup и прикреплен как formControlName) Были ли у вас похожие вещи?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню