Подтвердить что ты не робот

Angular2 - проверка и отправка формы извне

У меня есть простая форма, которая выглядит так

<form (ngSubmit)="save()" #documentEditForm="ngForm">
...
</form>

и необходимо отправить форму и проверить ее действительность извне

например. Либо отправьте его программно, либо с <button type="submit"> который находится за пределами тегов <form>.

4b9b3361

Ответ 1

Узнал, как это сделать:

  • инициировать отправку с помощью <formname>.ngSubmit.emit()
  • получить статус формы с помощью <formname>.form.valid

Пример:

<form (ngSubmit)="save()" #documentEditForm="ngForm">
...
</form>

<button class="btn-save button primary"
(click)="documentEditForm.ngSubmit.emit()"
[disabled]="!documentEditForm.form.valid">SAVE</button>

Редактировать: Как @yuriy-yakovenko указал, вы должны добавить в свой код компонента следующее:

@ViewChild('documentEditForm') documentEditForm: FormGroupDirective; 

И не забудьте импортировать FormGroupDirective если вы еще этого не сделали

Ответ 2

Правильный способ делать на самом деле

<form (ngSubmit)="save()" id="ngForm" #documentEditForm="ngForm"> 
    ... 
</form>

<button class="btn-save button primary" form="ngForm" [disabled]="!documentEditForm.form.valid">
    SAVE
</button>

Форма должна иметь идентификатор id="example-form", а кнопка отправки - соответствующий идентификатор в form="example-form"

Ответ 3

Важно: при использовании угловых элементов управления формы материала + реактивных форм

Вызовите onSubmit(undefined) чтобы правильно установить [formGroup] submitted = true в директиве [formGroup]

Примечание: директива не является тем же объектом, что и сама угловая форма (подробнее об этом ниже)

Здесь часть исходного кода для директивы [formGroup]. (для реактивных форм)

@Directive({
  selector: '[formGroup]',
  providers: [formDirectiveProvider],
  host: {'(submit)': 'onSubmit($event)', '(reset)': 'onReset()'},
  exportAs: 'ngForm'
})
export class FormGroupDirective extends ControlContainer implements Form,
    OnChanges {
  /**
   * @description
   * Reports whether the form submission has been triggered.
   */
  public readonly submitted: boolean = false;

 .....

 onSubmit($event: Event): boolean {
    (this as{submitted: boolean}).submitted = true;
    syncPendingControls(this.form, this.directives);
    this.ngSubmit.emit($event);
    return false;
 }

Вы используете это так:

<form [formGroup]="form" #formRef="ngForm">

И вы можете получить ссылку на FormGroupDirective в вашем ts файл с:

@ViewChild('formRef') 
formRef: FormGroupDirective;
  • Примечание. NgForm - это еще одна директива, автоматически применяемая при создании <form>.
  • Смущающее примечание: как NgForm и FormGroupDirective имеют в своем исходном коде exportAs: 'ngForm' (и они также объявляют submitted свойства и свойства ngSubmit). Но когда я ставлю #ngForm='ngForm' я получаю объект типа FormGroupDirective а не NgForm (проверено в отладчике). Я не уверен точно, почему - но именно поэтому я объявил это как FormGroupDirective а не NgForm - я думаю, может быть, первые NgForm.

Вы используете это так:

this.formRef.onSubmit(undefined)

Пример:

// html
<form [formGroup]="form" #formRef="ngForm">
    // ...Form Controls
</form>

// component.ts
export class MyComponent {

    @ViewChild('formRef')
    formRef: FormGroupDirective;

    form: FormGroup = new FormGroup({
        myInput: new FormControl(''),
        //etc...
    });

    submitFormProgrammatically() {
        this.formRef.onSubmit(undefined);
    }
}

Если бы вы просто this.formRef.ngSubmit.emit() как предлагали некоторые другие ответы, вы не получите все важные значения submitted = true.

Почему это важно?

Если вы используете какие-либо элементы управления Angular CDK или Angular Material, условие ошибки не отображается, если к полю формы не было прикосновения (нажатие или получение фокуса) ИЛИ форма была отправлена целиком.

Поэтому, если у вас отсутствует обязательное поле, которое мышь/курсор никогда не ngSubmit.emit() тогда это поле не будет отображаться красным, даже если вы выполните ngSubmit.emit() (потому что для формы submitted = false а элемент управления touched = false).

Так как же это нормально работает с обычной кнопкой отправки?

Обычно, если у вас есть <button type='submit'>Submit</button> (внутри <form>), это вызовет отправку стандартного HTML <form> (ничего общего с Angular) - и это приведет к стандартному submit событие в теге формы.

ЕСЛИ этот <form> также имеет директиву [formGroup] (как показано выше), то событие submit формы HTML 'перехватывается' директивой и вызывает то, что вызывает onSubmit() выше.

Это, в свою очередь, вызывает событие ngSubmit - которое вы можете поймать сами, если вам потребуется дополнительная обработка - например, показ предупреждения.

Поэтому очень важно вызвать onSubmit а не ngSubmit.emit чтобы заставить работать валидацию при использовании элементов управления материалом. Параметр $ event может быть нулевым или неопределенным.

Дальнейшее чтение: Посмотрите на ErrorStateMatcher (только для Angular CDK/Material), чтобы увидеть точные правила. Вы можете создать свой собственный, если обойти ограничения по умолчанию становится слишком сложным.

Еще более запутанно: директива [formGroup] НЕ является тем же объектом, что и FormGroup которая просто хранит данные. Только директива submitted его - тогда как у FormGroup есть такие вещи, как touched, pristine, dirty.

Ответ 4

Если вы используете Reactive Forms, используйте свойство formGroup invalid для отключения кнопки отправки:

<button  
  form="ngForm"
  [disabled]=" editor.invalid>Enviar</button> 

...

<form [formGroup]="editor"  id="ngForm"   (ngSubmit)="save()" novalidate >
...
</form>

Ответ 5

Трюк, который работал у меня с помощью

  • Реактивные формы
  • Angular2
  • вкл. IE

:

<!-- real button will simulate click on invisible button (cf. form) -->
<button onclick="document.getElementById('hiddenSaveButtonForMicrosoftWithLove').click()">
  The Real Button outside forms
</button>

<form>
  <!-- will be called in the background and is never visible -->
  <button id="hiddenSaveButtonForMicrosoftWithLove" type="submit" style="display: none;">hiddenSaveButtonForMicrosoftWithLove</button>
</form>

Ответ 6

Ниже решение работает в моем случае, пожалуйста, попробуйте это простое решение. Я не уверен, будет ли это работать во всех условиях:

<form #documentEditForm="ngForm" id="ngForm" (ngSubmit)="save(documentEditForm.valid)"> 
    ...Your Input Elements... 
</form>

Кнопка должна быть объявлена вне формы следующим образом:

<button form="ngForm">Submit</button>

Валидация формы должна проверяться в save() при соблюдении следующих условий

save(isValid:boolean){
    if(isValid) {
        ...Your code to save details...
    }
}

Надеюсь, это простое решение поможет вам.

Ответ 7

Этот пример будет работать в Angular 6 и выше

<form (ngSubmit)="save()" id="ngForm" [formGroup]="form"> 
    ... 
</form>

<button type="submit" class="btn-save button primary" form="ngForm">Save</button>