Как сделать универсальный компонент с вводом контроля формы для угловых форм в приложении - PullRequest
1 голос
/ 19 октября 2019

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

Позволяет получить код:

export class DatePickerComponent {
@ViewChild('input', {read: ElementRef, static: false}) inputRef: ElementRef;
@Input()
formName?: FormGroup;
@Input()
formControlName: any;

constructor() {
this.formControlName.setValue(['']);
}

onKeyPress = (event) => {
const pressedKey = event.keyCode;

if (
  pressedKey !== 8 &&
  pressedKey !== 9 &&
  pressedKey !== 13 &&
  ((pressedKey < 48 || pressedKey > 105) || (pressedKey > 57 && pressedKey < 96))
) {
  event.preventDefault();
}
}

onKeyUp = (event) => {
const pressedKey = event.keyCode;
const inputString: string = this.formControlName.value;

if (!inputString) {
  return;
}

if (inputString.length === 11) {
  this.inputRef.nativeElement.value = inputString.slice(0, -1);
  return;
}

if (pressedKey === 8 && (inputString.length === 3 || inputString.length === 6)) {
  const newValue = inputString.slice(0, -1);
  this.formControlName.setValue(newValue);
  this.inputRef.nativeElement.value = newValue;
} else if (inputString.length === 2 || inputString.length === 5) {
  const newValue = inputString + '/';
  this.formControlName.setValue(newValue);
  this.inputRef.nativeElement.value = newValue;
}
}

}

И шаблон:

<div [formGroup]="formName">
<input
class="form-control"
formControlName="{{formControlName}}"
placeholder="DD/MM/YYYY"
name="dp"
ngbDatepicker
#d="ngbDatepicker"
[minDate]="{year: 1930, month: 1, day: 1}"
(click)="d.toggle()"
(keydown)="onKeyPress($event)"
(keyup)="onKeyUp($event)">
</div>

Таким образом, я хотел использовать его в родительском компоненте, который имеет форму с FormGroup свойством, установленным в X. Чтобы использовать мой компонент, я добавил <app-date-picker [formControlName]="birthDate" [formName]="registerForm"></app-date-picker>

Возможно, я что-то не так сделал в родительском компоненте:

export class UserFormComponent implements OnInit {

@Input() isRegisterPage: boolean;
@Input() isProfilePage: boolean;
@Input() user: UserInfo;
registerForm: FormGroup;
birthDate: FormControl;
loading: boolean;
.e
.t
.c

Как правильно использовать мой указатель даты? Может быть, Сомоне может мне помочь?

Скрипка только с указателем даты (не используется в родительской форме): https://stackblitz.com/edit/angular-i47zuz-jj5glk?file=app/datepicker-popup.ts

Ответы [ 3 ]

1 голос
/ 19 октября 2019

вы делаете это неправильно!, Чтобы ваш пользовательский компонент работал с формами как FormControl, вы должны сделать это FormControl, для этого вам нужно реализовать интерфейс ControlValueAccessor, чтобы ваш компонент работал как пользовательскийFormControl, вы можете прочитать, как это сделать, здесь -> ControlValueAccessor , если у вас есть проблемы с его реализацией, дайте мне знать, я могу предоставить дополнительную помощь, но сначала попробуйте реализовать ее самостоятельно, чтобыучиться лучше

0 голосов
/ 21 октября 2019

Вы можете взглянуть на библиотеку, которую я написал для создания форм под названием Easy Angular. https://github.com/adriandavidbrand/ngx-ez это позволяет вам создавать самопроверяющиеся формы с очень небольшим количеством кода, и расширение элементов управления для создания ваших собственных легко.

Здесь реализован инструмент выбора даты BootStrap.

import { Component, Optional, Self } from '@angular/core';
import { NgControl } from '@angular/forms';

import {
  EzControlBase,
  EzFormDirective,
  EzFormConfigService,
  EzFormConfigDirective,
  EzFormReadonlyDirective
} from 'ngx-ez';

@Component({
  selector: 'ez-date',
  templateUrl: './ez-date.component.html',
  styleUrls: ['./ez-date.component.css'],
  providers: [{ provide: EzControlBase, useExisting: EzDateComponent }]
})
export class EzDateComponent extends EzControlBase {
  constructor(
    configService: EzFormConfigService,
    @Optional() configDirective: EzFormConfigDirective,
    @Optional() ezForm: EzFormDirective,
    @Optional() ezezReadonly: EzFormReadonlyDirective,
    @Self() @Optional() ngControl: NgControl
  ) {
    super(configService, configDirective, ezForm, ezezReadonly, ngControl);
  }
}

и шаблон

<ez-control>
  <ng-content></ng-content>
  <ng-container controls-container>
    <ng-container *ngIf="readonly$ | async">{{ value | date : 'dd/MM/yyyy' }}</ng-container>
    <input bsDatepicker [bsConfig]="{ dateInputFormat: 'DD/MM/YYYY' }" [id]="(name$ | async) + '_control_input'" [attr.aria-describedby]="(valid$ | async) ? null : (name$ | async) + '_validation_message'" [attr.maxlength]="maxlength$ | async" type="text" [attr.placeholder]="placeholder$ | async" [value]="value | date : 'dd/MM/yyyy'" (bsValueChange)="onChange($event)"
      [ngClass]="(config$ | async).inputClasses" [valid]="valid$ | async" [class.d-none]="readonly$ | async">
  </ng-container>
</ez-control>

См. Рабочую демонстрацию в этом StackBlitz https://stackblitz.com/edit/angular-t1wshi?file=src%2Fapp%2Fez-date%2Fez-date.component.html

0 голосов
/ 21 октября 2019

На самом деле вам не нужно создавать пользовательский элемент управления, он только передает элемент управления в качестве ввода

В родительском, например,

<form [formGroup]="form">
   <my-component [control]="form.get('bithdate')"></my-component>
</form>

Ваш компонент

<input [formControl]="control" ...>

@Input() control:FormControl
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...