Validação condicional no método valueChanges em formulários reativos Angular
Você sabe como usar Angular detecção de alteração de valor do Reactive Forms? Esta postagem do blog mostrará os caminhos.
Nesta postagem do blog, aprenderemos a usar Angular detecção de alteração de valor do Reactive Forms e habilitar a validação condicional com base nisso com a ajuda das melhores e mais completas bibliotecas de componentes Angular disponíveis –Ignite UI.
Saiba como criar seu primeiro formulário Angular reativo aqui.
Digamos que você tenha um formulário reativo criado usando a classe FormBuilder, conforme mostrado abaixo:
ngOnInit() {
this.loginForm = this.fb.group({
email: [null, Validators.required],
password: [null, [Validators.required, Validators.maxLength(8)]],
phonenumber: [null]
});
}
Você criou loginForm, que tem três controles: e-mail, senha e número de telefone. Aqui, você está usando o FormBuilder para criar um formulário reativo. No modelo de componente, você pode anexar loginForm conforme mostrado na listagem de código abaixo. Usando a vinculação de propriedade, a propriedade formGroup do elemento de formulário HTML é definida como loginForm e o valor formControlName desses controles é definido como a propriedade FormControl individual de FormBuilder.
<form (ngSubmit)='loginUser()' [formGroup]='loginForm' novalidate class="form">
<input formControlName='email' type="text" class="form-control" placeholder="Enter Email" />
<div class="alert alert-danger" *ngIf="loginForm.get('email').hasError('required') && loginForm.get('email').touched">
Email is required
</div>
<input formControlName='password' type="password" class="form-control" placeholder="Enter Password" />
<input formControlName='phonenumber' type="text" class="form-control" placeholder="Enter Phone Number" />
<div class="alert alert-danger" *ngIf="loginForm.get('phonenumber').hasError('required') && loginForm.get('phonenumber').touched">
Phone Number is required
</div>
<br />
<button [disabled]='loginForm.invalid' class="btn btn-default">Login</button>
</form>
Também colocamos mensagens de erro para campos de e-mail e número de telefone. Além disso, esse botão de envio só seria ativado quando o formulário fosse válido. O envio do formulário é tratado conforme mostrado na lista abaixo:
loginUser() {
console.log(this.loginForm.status);
console.log(this.loginForm.value);
}
Se o formulário for válido no console do navegador, você obterá a saída conforme abaixo:

Além disso, se houver um erro, o botão enviar será desativado e uma mensagem de erro será exibida conforme abaixo:

Você pode aprender a criar validadores personalizados para Angular formulários reativos aqui.
Agora, suponha um cenário em que você tenha um botão de opção para enviar uma notificação. O usuário deve ser capaz de selecionar a opção de envio de notificação e, com base nisso, certos FormControl terão alguma validação.
Considere o formulário abaixo,

Adicionamos uma opção Enviar notificação. Se o usuário selecionar Telefone para enviar notificação, o campo Número de telefone deverá ser obrigatório, caso contrário, não deverá ser. Para conseguir isso, precisamos realizar as seguintes tarefas,
- Ouvindo as mudanças
- Put conditional validation
Para começar, vamos modificar nosso formulário para lidar com a notificação. Portanto, agora o formulário tem um FormControl de notificação com o valor padrão definido como nulo, conforme mostrado na listagem abaixo:
this.loginForm = this.fb.group({
email: [null, Validators.required],
password: [null, [Validators.required, Validators.maxLength(8)]],
phonenumber: [null],
notification: ['email']
});
No modelo de formulário reativo, adicionaremos um grupo de botões de opção para lidar com a opção Enviar notificação.
<form (ngSubmit)='loginUser()' [formGroup]='loginForm' novalidate class="form">
<input formControlName='email' type="text" class="form-control" placeholder="Enter Email" />
<div class="alert alert-danger" *ngIf="loginForm.get('email').hasError('required') && loginForm.get('email').touched">
Email is required
</div>
<input formControlName='password' type="password" class="form-control" placeholder="Enter Password" />
<input formControlName='phonenumber' type="text" class="form-control" placeholder="Enter Phone Number" />
<div class="alert alert-danger" *ngIf="loginForm.get('phonenumber').hasError('required') && loginForm.get('phonenumber').touched">
Phone Number is required
</div>
<br />
<label class='control-label'>Send Notification</label>
<br />
<label class="radio-inline">
<input type="radio" value="email" formControlName="notification">Email
</label>
<label class="radio-inline">
<input type="radio" value="phone" formControlName="notification">Phone
</label>
<br />
<button [disabled]='loginForm.invalid' class="btn btn-default">Login</button>
</form>
Neste formulário, neste ponto, parece abaixo:

Inscreva-se no valueChanges
Em formulários reativos, FormControls e FormGroups têm um método valueChanges. Ele retorna um tipo observável, para que você possa assiná-lo, para trabalhar com a alteração de valor em tempo real de FormControls ou FormGroups.
Em nosso exemplo, precisamos assinar valueChanges da notificação FormControl. Isso pode ser feito da seguinte forma:
formControlValueChanged() {
this.loginForm.get('notification').valueChanges.subscribe(
(mode: string) => {
console.log(mode);
});
}
Precisamos chamar isso de gancho de ciclo de vida OnInit, conforme mostrado abaixo:
ngOnInit() {
this.loginForm = this.fb.group({
email: [null, Validators.required],
password: [null, [Validators.required, Validators.maxLength(8)]],
phonenumber: [null],
notification: ['email']
});
this.formControlValueChanged();
}
Agora, quando você altera a seleção para notificação no formulário no console do navegador, você pode ver, você tem o valor mais recente.

Lembre-se de que não estamos lidando com nenhum evento no botão de opção para obter o valor mais recente. Angular tem um método valueChanges que retorna o valor recente como observável no FormControl e FormGroup, e estamos inscritos nele para o valor recente na notificação FormControl.
Conditional Validation
Nosso requisito é que, quando a notificação estiver definida como telefone, o número de telefone FormControl deve ser o campo obrigatório e, se estiver definido como e-mail, o número de telefone FormControl não deve ter nenhuma validação.
Vamos modificar a função formControlValueChnaged() conforme mostrado na próxima listagem para habilitar a validação condicional no número de telefone FormControl.
formControlValueChanged() {
const phoneControl = this.loginForm.get('phonenumber');
this.loginForm.get('notification').valueChanges.subscribe(
(mode: string) => {
console.log(mode);
if (mode === 'phone') {
phoneControl.setValidators([Validators.required]);
}
else if (mode === 'email') {
phoneControl.clearValidators();
}
phoneControl.updateValueAndValidity();
});
}
Existem muitos códigos acima, então fale linha por linha.
- Usando o método get do FormBuilder obtendo uma instância do número de telefone FormControl
- Assinando o método valueChanges no FormControl de notificação
- Verificando o valor atual da notificação FormControl
- Se o valor atual for phone, usando o método setValidators de FormControl para definir o validador necessário no controle phonenumber
- Se o valor atual for email, usando o método clearValidators de FormControl para limpar toda a validação no controle de número de telefone
- Na última chamada do método updateValueAndValidity para atualizar as regras de validação do phonecontrol
Execute o aplicativo e você verá que, à medida que altera o valor da notificação, a validação do número de telefone está sendo alterada,

Usando o poder do método valueChanges do Angular Reactive Form, você pode obter validações condicionais e muitas outras funcionalidades, como reagir a alterações no modelo de dados subjacente do formulário reativo.
Gostou deste post?
Se você gostou deste post, por favor, compartilhe-o. Além disso, se você ainda não conferiu nossa biblioteca, certifique-se de fazê-lo! É a caixa de ferramentas mais completa com componentes de interface do usuário baseados em materiais, a grade de dados Angular mais rápida do mercado e 60+ gráficos de alto desempenho!
