Есть ли способ, которым я могу динамически установить formControlName на элемент <input>в угловых? - PullRequest
0 голосов
/ 20 февраля 2019

Я работаю над написанием компонента, предназначенного для упрощения / унификации внешнего вида и взаимодействия наших форм.Код выглядит примерно так:

Пример использования

...
<my-form-input labelKey = "email" controlName="emailAddress" [form]="userForm">
    <input myInput class="form-control" type="email" formControlName="emailAddress" />
</my-form-input>
...

Вы можете видеть, что "emailAddress" передается MyFormInputComponent как controlName и передается во второй раз директиве FormControlName элемента <input>.Я хотел бы пропустить это только один раз, чтобы мой конечный пользователь не должен был это делать.

Есть ли хороший способ, которым я могу это сделать, или это просто ограничение, которое я должен принять (еслида, объяснение, почему существует это ограничение, будет приветствоваться)?Код показан ниже.

Я пробовал два подхода:

  1. Установка аннотации @HostBinding("attr.formControlName") в компоненте MyInput.Я могу манипулировать атрибутом с именем formcontrolname на элементе таким образом, но он не вызывает директиву, необходимую Angular Forms для правильной регистрации элемента управления в группе.
  2. Попросите пользователя указать formControlNameк элементу <input> и считайте его значение для остальной части компонента.Это может сработать, но мне придется обращаться к DOM напрямую через ElementRef, , что не рекомендуется .Рекомендуемый маршрут для взаимодействия с DOM - Renderer - , по-видимому, не дает возможности читать атрибуты либо .

my-form-input.component.ts

@Component({
    selector: 'my-form-input',
    templateUrl: './my-form-input.component.html',
    styleUrls: ['./my-form-input.component.scss']
})
export class MyFormInputComponent implements OnInit, AfterContentInit {
    @Input()
    labelKey: string;

    @Input()
    controlName: string;

    @Input()
    form: FormGroup;

    @ContentChild(MyInputDirective)
    input: MyInputDirective;

    ngAfterContentInit(): void {        
        this.initInput();
    }

    /**
     * Updates the input we project into the template
     */
    private initInput() {
        this.input.updatePlaceholder(this.labelKey);
        // I'd like to somehow edit the FormControlName directive applied to the input here
    }
}

my-form-input.component.html

<label>{{ labelKey | translate }}</label>
<ng-content></ng-content>
<my-input-error [control]="form.controls[controlName]" [name]="labelKey | translate" />

my-input.directive.ts

@Directive({
    selector: '[myInput]'
})
export class myInputDirective implements OnInit {
    private placeholderKey = ""; 

    @HostBinding("placeholder")
    private placeholder: string;

    updatePlaceholder(placeholderKey: string) {
        this.placeholderKey = placeholderKey;
        this.placeholder = this.translateService.instant(this.placeholderKey);
    }

    constructor(private translateService: TranslateService) {
    }
}

my-form-error.component.ts

// Not shown since not relevant.

1 Ответ

0 голосов
/ 21 февраля 2019

Я все еще не уверен в точном объяснении, но некоторые рассуждения намекают на то, где я мог отклониться.

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

В этом случае это приводит к созданию отдельных компонентов для определенных элементов управления формой (например, <input>, <textarea> и т. Д.).Это то, что я в итоге сделал.В любом случае, это лучше с конечной точки проектирования - один компонент для обертывания всех возможных элементов управления формой никогда не должен был появиться.Или спроектируйте элемент управления формы, который дублирует некоторые свойства, как я делаю в вопросе, или создайте определенные компоненты.Или и то, и другое (просто превратите свои самые распространенные элементы управления формой в компоненты, оберните одноразовые проблемы в свой проектирующий компонент).

Вот несколько блогов, которые помогли мне найти свой путь:

  1. https://medium.com/@vadimkorr/implementing-nested-custom-controls-in-angular-5-c115c68e6b88
  2. https://blog.angularindepth.com/never-again-be-confused-when-implementing-controlvalueaccessor-in-angular-forms-93b9eee9ee83
...