I'm building a form using model-driven forms and building my form elements with formcontrol. I have a service where I put some functions and I send the formgroup to this function to access the formcontrols. I would like to know how could I change the formcontrols properties to do things like hide the element. I can't find a way to do this on the internet.
Thanks for all
edit:
Here is the example code:
My app begins with app.component.html
<h1>
Orçamento
</h1>
<app-form [campos]="cpos"></app-form>
and here my app.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
cpos: any[] = [];
constructor() { }
ngOnInit() {
}
}
I have a class called campo-base.ts it's the base for all my fields:
export class CampoBase<T> {
nome: string;
valor: T;
label: string;
obrigatorio: boolean;
ordem: string;
tamanho: number;
tipoCampo: string;
combo: {chave: string, valor: string}[] = [];
tipo: string;
disabled: boolean;
tamcol: string;
espcol: string;
classe: string;
rowcol: number;
f3: string;
change: string;
visivel:boolean;
constructor (opcoes: {
valor?: T,
nome?: string,
label?: string,
obrigatorio?: boolean,
ordem?: string,
tamanho?: number,
tipoCampo?: string,
combo?: {chave: string, valor: string}[],
tipo?: string,
disabled?: boolean,
tamcol?: string,
espcol?: string,
classe?: string,
rowcol?: number,
f3?: string,
change?: string,
visivel?: boolean
} = {}) {
this.valor = opcoes.valor;
this.nome = opcoes.nome || '';
this.label = opcoes.label || '';
this.obrigatorio = !!opcoes.obrigatorio;
this.ordem = opcoes.ordem || '';
this.tamanho = opcoes.tamanho === undefined ? 1 : opcoes.tamanho;
this.tipoCampo = opcoes.tipoCampo || '';
this.combo = opcoes.combo || [];
this.tipo = opcoes.tipo || '';
this.disabled = !!opcoes.disabled;
this.tamcol = opcoes.tamcol || '';
this.espcol = opcoes.espcol || '';
this.classe = opcoes.classe || '';
this.rowcol = opcoes.rowcol === undefined ? 0 : opcoes.rowcol;
this.f3 = opcoes.f3 || '';
this.change = opcoes.change || '';
this.visivel = (!!opcoes.visivel ? true : opcoes.visivel);
}
}
and I use it in form.component.ts which received data from a service containing a list of fields with their properties.
import { Component, Input, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { CampoBase } from './campo-base';
import { FormService } from "./form.service";
import { FormDadosService } from './form-dados.service';
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.css'],
providers:[FormService,FormDadosService]
})
export class FormComponent implements OnInit {
@Input() campos: CampoBase<any>[] = [];
formulario: FormGroup = new FormGroup({});
payLoad = '';
coluna: number = 0;
constructor(private formService: FormService, private servico: FormDadosService) { }
ngOnInit() {
this.servico.getCampos().subscribe((data) => {
let classe: string = '';
let combobox: {chave: string, valor:string}[] = [];
data.forEach(campo => {
classe = '';
//Ajusta os tamanhos dos campos no form
if (campo.ZI2_TIPO != '4') {
classe += 'form-group ';
if (campo.ZI2_ESPCOL !== '00') {
classe += 'col-md-' + parseInt(campo.ZI2_TAMCOL).toString() + ' col-md-pull-' + parseInt(campo.ZI2_ESPCOL).toString() + ' col-md-offset-' + parseInt(campo.ZI2_ESPCOL).toString();
classe += ' col-lg-' + parseInt(campo.ZI2_TAMCOL).toString() + ' col-lg-pull-' + parseInt(campo.ZI2_ESPCOL).toString() + ' col-lg-offset-' + parseInt(campo.ZI2_ESPCOL).toString();
} else {
classe += 'col-md-' + parseInt(campo.ZI2_TAMCOL).toString() + ' col-lg-' + parseInt(campo.ZI2_TAMCOL).toString();
}
}
//Calcula o tamanho dos campos na linha para adicionar um novo row
if (this.coluna >= 12) {
this.coluna = 0;
}
this.coluna += parseInt(campo.ZI2_TAMCOL) + parseInt(campo.ZI2_ESPCOL);
//Trata os campos combobox
combobox.length = 0;
if (campo.ZI2_CBOX !== null) {
for (let x in campo.ZI2_CBOX) {
if (campo.ZI2_CBOX.hasOwnProperty(x)) {
combobox.push({chave: x, valor: campo.ZI2_CBOX[x]});
}
}
}
//Instancia o campo e adiciona na lista de campos
this.campos.push(new CampoBase({
valor: '',
nome: campo.ZI2_CAMPO,
label: campo.ZI2_DESC,
tipoCampo: campo.ZI2_TIPO,
tamanho: campo.ZI2_TAM,
ordem: campo.ZI2_SEQ,
obrigatorio: campo.ZI2_OBRIGA === '1',
disabled: campo.ZI2_VISUAL !== "A",
classe: classe,
tamcol: campo.ZI2_TAMCOL,
espcol: campo.ZI2_ESPCOL,
rowcol: this.coluna,
f3: campo.ZI2_F3,
combo: combobox.slice(),
change: campo.ZI2_CHANGE,
visivel: true
}));
});
this.formulario = this.formService.toFormGroup(this.campos);
});
}
onSubmit() {
this.payLoad = JSON.stringify(this.formulario.value);
}
}
I build my form using form-campo.component.ts:
import { Component, Input, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { CampoBase } from './campo-base';
import { OrcamentoService } from '../orcamento.service';
@Component({
selector: 'formcampos',
templateUrl: './form-campo.component.html',
styleUrls: ['./form-campo.component.css']
})
export class FormCampoComponent implements OnInit {
@Input() campo: CampoBase<any>;
@Input() form: FormGroup;
isValid() {
return this.form.controls[this.campo.nome].pristine || this.form.controls[this.campo.nome].valid;
}
constructor(private orcamentoService: OrcamentoService){}
ngOnInit() {
if (this.campo.change)
this.form.controls[this.campo.nome].valueChanges.subscribe(valor => {
let aChanges = this.campo.change.split(";");
let expression = "";
for (let i = 0; i < aChanges.length; i++) {
if (aChanges[i].length > 0) {
expression = "_this.orcamentoService." + aChanges[i].replace(/\(\)/g,"") + '(_this.form, valor)';
eval(expression);
}
}
});
}
}
with this template:
<div [formGroup]="form" [class]="campo.classe" *ngIf="campo.visivel">
<label [attr.for]="campo.nome" [hidden]="campo.tipoCampo === '4'">{{campo.label}}</label>
<div [class.input-group]="campo.f3">
<select *ngIf="(campo.tipoCampo == '1' || campo.tipoCampo == '3') && campo.combo.length > 0" [formControlName]="campo.nome" class="form-control" [id]="campo.nome">
<option *ngFor="let opt of campo.combo" [value]="opt.chave">{{opt.valor}}</option>
</select>
<input *ngIf="(campo.tipoCampo == '1' || campo.tipoCampo == '3') && campo.combo.length == 0" [formControlName]="campo.nome" class="form-control"
[id]="campo.nome" [type]="'text'" [maxlength]="campo.tamanho" [placeholder]="campo.label">
<input *ngIf="campo.tipoCampo == '2'" [formControlName]="campo.nome" class="form-control"
[id]="campo.nome" [type]="'email'" [maxlength]="campo.tamanho" [placeholder]="campo.label">
<input *ngIf="campo.tipoCampo == '4'" [formControlName]="campo.nome"
[id]="campo.nome" [type]="'hidden'">
<textarea *ngIf="campo.tipoCampo == '5'" [formControlName]="campo.nome" class="form-control"
[id]="campo.nome" [placeholder]="campo.label"></textarea>
<span class="input-group-btn" *ngIf="campo.f3">
<button class="btn btn-primary" type="button" id="f3{{campo.nome}}"><span class="glyphicon glyphicon-search"></span></button>
</span>
</div>
</div>
and finally in orcamento.service I tried to manipulate the visibility of some fields like below:
import { Injectable } from '@angular/core';
@Injectable()
export class OrcamentoService {
constructor() { }
gatTipoOrc(form, valor) {
if (valor == "N") {
form.controls['ZPO_UM'].enable();
} else {
form.controls['ZPO_UM'].disable();
form.controls['ZPO_UM'].reset();
}
}
gatUM(form, valor) {
form.controls['ZPO_QTDPCX'].visivel = false;
}
habEntrega(form, valor) {
}
}
If I understand you correctly, you want to do things like hide an element - <div hidden></div>
or in angular1 <div ng-hide="isHidden"></div>
In angular2 you should bind to the element properties similar to the traditional way:
<div [hidden]="true"></div>
.
Of course you can use a variable, <div [hidden]="isHidden"></div>
Also note that using hidden
is not recomended: https://stackoverflow.com/questions/35578083
EDIT:
As J. Adam Connor mentioned you can also use *ngIf
instead of [hidden]
. This will cause your element to be completely removed from the DOM which is a very good approach in general but should be carefully used with Forms because some validations and bindings require your form to match your model. That can be messy if it is missing from your actual Form in the DOM.