Dada uma lista de caixas de seleção vinculadas ao mesmo formControlName
, como posso produzir uma matriz de valores de caixa de seleção vinculados a formControl
, em vez de simplesmente true
/ false
?
Exemplo:
<form [formGroup]="checkboxGroup">
<input type="checkbox" id="checkbox-1" value="value-1" formControlName="myValues" />
<input type="checkbox" id="checkbox-2" value="value-2" formControlName="myValues" />
<input type="checkbox" id="checkbox-3" value="value-2" formControlName="myValues" />
</form>
checkboxGroup.controls['myValues'].value
atualmente produz:
true or false
O que eu quero produzir:
['value-1', 'value-2', ...]
javascript
angular
checkbox
angular2-forms
ReactingToAngularVues
fonte
fonte
Respostas:
Com a ajuda de silentsod answer, escrevi uma solução para obter valores em vez de estados em meu formBuilder.
Eu uso um método para adicionar ou remover valores no formArray. Pode ser uma abordagem ruim, mas funciona!
component.html
component.ts
Quando eu envio meu formulário, por exemplo, meu modelo se parece com:
Só falta uma coisa, uma função para preencher o formArray se o seu modelo já tiver verificado os valores.
fonte
myChoices: new FormArray([], Validators.required)
Este é um bom lugar para usar o
FormArray
https://angular.io/docs/ts/latest/api/forms/index/FormArray-class.htmlPara começar, vamos construir nosso conjunto de controles com um
FormBuilder
ou com um novoFormArray
FormBuilder
novo FormArray
Fácil de fazer, mas então vamos mudar nosso modelo e deixar o mecanismo de modelagem lidar com como nos ligamos aos nossos controles:
template.html
Aqui, estamos iterando nosso conjunto de
FormControls
em nossomyValues
FormArray
e para cada controle que estamos vinculando[formControl]
a esse controle em vez de aoFormArray
controle e<div>{{checkboxGroup.controls['myValues'].value}}</div>
produz,true,false,true
ao mesmo tempo que tornamos a sintaxe do modelo um pouco menos manual.Você pode usar este exemplo: http://plnkr.co/edit/a9OdMAq2YIwQFo7gixbj?p=preview para bisbilhotar
fonte
*ngFor="let control of checkboxGroup.controls['myValues'].controls ; let i=index""
É significativamente mais fácil fazer isso no Angular 6 do que nas versões anteriores, mesmo quando as informações da caixa de seleção são preenchidas de forma assíncrona a partir de uma API.
A primeira coisa a perceber é que, graças ao
keyvalue
tubo do Angular 6, não precisamosFormArray
mais usar e, em vez disso, podemos aninhar umFormGroup
.Primeiro, passe FormBuilder para o construtor
Em seguida, inicialize nosso formulário.
Quando nossos dados de opções de caixa de seleção estiverem disponíveis, itere-os e podemos colocá-los diretamente no aninhado
FormGroup
como um nomeFormControl
, sem ter que depender de matrizes de pesquisa indexadas por número.Finalmente, no modelo, precisamos apenas iterar o
keyvalue
das caixas de seleção: sem adicionaislet index = i
, e as caixas de seleção estarão automaticamente em ordem alfabética: muito mais limpo.fonte
const checkboxes = ..
fora do foreach;)Se você estiver procurando por valores de caixa de seleção no formato JSON
Exemplo completo aqui .
Peço desculpas por usar os nomes dos países como valores da caixa de seleção em vez dos da pergunta. Explanação adicional -
Crie um FormGroup para o formulário
Deixe cada caixa de seleção ser um FormGroup construído a partir de um objeto cuja única propriedade é o valor da caixa de seleção.
A matriz de FormGroups para as caixas de seleção é usada para definir o controle para os 'países' no formulário pai.
No modelo, use um tubo para obter o nome do controle de caixa de seleção
fonte
TL; DR
Isso também me surpreendeu algumas vezes, então tentei as abordagens FormArray e FormGroup.
Na maioria das vezes, a lista de caixas de seleção era preenchida no servidor e eu a recebia por meio da API. Mas às vezes você terá um conjunto estático de caixa de seleção com seu valor predefinido. Com cada caso de uso, o FormArray ou FormGroup correspondente será usado.
Para simplificar, imagine que você tem um formulário de criação de produto simples com
Primeiro, configurei um formulário com apenas o nome de produto formControl. É um campo obrigatório.
Como a categoria é renderizada dinamicamente, terei que adicionar esses dados ao formulário mais tarde, depois que os dados estiverem prontos.
Existem duas abordagens para construir a lista de categorias.
1. Matriz de formulário
Isso
buildCategoryFormGroup
me retornará um FormArray. Ele também leva uma lista de valores selecionados como um argumento. Se você quiser reutilizar o formulário para editar dados, pode ser útil. Para fins de criação de um novo formulário de produto, ainda não é aplicável.Observe que, ao tentar acessar os valores de formArray. Será parecido
[false, true, true]
. Para obter uma lista de id selecionados, é necessário um pouco mais de trabalho para verificar a lista, mas com base no índice da matriz. Não parece bom para mim, mas funciona.É por isso que comecei a usar
FormGroup
para esse assunto2. Grupo de forma
A diferença do formGroup é que ele armazena os dados do formulário como o objeto, o que requer uma chave e um controle de formulário. Portanto, é uma boa ideia definir a chave como categoryId e então podemos recuperá-la mais tarde.
O valor do grupo de formulários será semelhante a:
Mas, na maioria das vezes, queremos obter apenas a lista de categoryIds como
["category2", "category3"]
. Eu também tenho que escrever um get para obter esses dados. Eu gosto mais dessa abordagem em comparação com formArray, porque eu poderia realmente pegar o valor do próprio formulário.3. O validador personalizado para verificar se pelo menos uma caixa de seleção foi selecionada
Eu fiz o validador marcar pelo menos a caixa de seleção X selecionada, por padrão, ele marcará apenas uma caixa de seleção.
fonte
Não vejo uma solução aqui que responda completamente à pergunta usando formas reativas em sua extensão máxima, então aqui está minha solução para o mesmo.
Resumo
Aqui está o cerne da explicação detalhada, juntamente com um exemplo StackBlitz.
FormArray
para as caixas de seleção e inicialize o formulário.valueChanges
observável é perfeito para quando você deseja que o formulário exiba algo, mas armazene outra coisa no componente. Mapeie os valorestrue
/false
para os valores desejados aqui.false
valores no momento do envio.valueChanges
observável.Exemplo StackBlitz
Explicação detalhada
Use FormArray para definir o formulário
Conforme já mencionado na resposta marcada como correta.
FormArray
é o caminho a seguir em casos em que você prefere obter os dados em uma matriz. Portanto, a primeira coisa que você precisa fazer é criar o formulário.Isso apenas definirá o valor inicial de todas as caixas de seleção como
false
.Em seguida, precisamos registrar essas variáveis de formulário no modelo e iterar sobre o
checkboxes
array (NÃO os,FormArray
mas os dados da caixa de seleção) para exibi-los no modelo.Faça uso do observável valueChanges
Esta é a parte que não vejo mencionada em nenhuma das respostas aqui. Em situações como essa, em que gostaríamos de exibir esses dados, mas armazená-los como outra coisa, o
valueChanges
observável é muito útil. UsandovalueChanges
, podemos observar as mudanças nocheckboxes
e, em seguida,map
astrue
/false
os valores recebidos doFormArray
com os dados desejados. Observe que isso não mudará a seleção das caixas de seleção, pois qualquer valor verdadeiro passado para a caixa de seleção irá marcá-lo como marcado e vice-versa.Isso basicamente mapeia os
FormArray
valores para ocheckboxes
array original e retorna ovalue
caso a caixa de seleção esteja marcada comotrue
, do contrário, ele retornafalse
. OemitEvent: false
é importante aqui, pois definir oFormArray
valor sem ele fará comvalueChanges
que seja emitido um evento criando um loop infinito. Ao definiremitEvent
comofalse
, estamos garantindo que ovalueChanges
observável não emita quando definimos o valor aqui.Filtre os valores falsos
Não podemos filtrar diretamente os
false
valores noFormArray
porque fazer isso bagunçará o modelo, pois eles estão vinculados às caixas de seleção. Portanto, a melhor solução possível é filtrar osfalse
valores durante o envio. Use o operador de propagação para fazer isso.Isso basicamente filtra os valores falsos do
checkboxes
.Cancelar inscrição em valueChanges
Por último, não se esqueça de cancelar a assinatura de
valueChanges
Observação: há um caso especial em que um valor não pode ser definido como
FormArray
invalueChanges
, ou seja, se o valor da caixa de seleção estiver definido como o número0
. Isso fará com que pareça que a caixa de seleção não pode ser selecionada, pois marcá-la definirá oFormControl
como o número0
(um valor falso) e, portanto, o manterá desmarcado. Seria preferível não usar o número0
como um valor, mas se for necessário, você deve definir condicionalmente0
para algum valor verdadeiro, por exemplo, string'0'
ou simplesmentetrue
e, ao enviar, convertê-lo de volta para o número0
.Exemplo StackBlitz
O StackBlitz também tem código para quando você deseja passar valores padrão para as caixas de seleção, para que sejam marcados como marcados na IU.
fonte
Faça um evento quando for clicado e então altere manualmente o valor de true para o nome que a caixa de seleção representa, então o nome ou true terá o mesmo valor e você poderá obter todos os valores em vez de uma lista de true / false. Ex:
component.html
component.ts
Isso captura o evento depois que ele já foi alterado para verdadeiro ou falso pelo Angular Forms, se for verdadeiro eu altero o nome para o nome do que a caixa de seleção representa, que se necessário também será avaliada como verdadeira se estiver sendo marcada para verdadeiro / falso como bem.
fonte
Se você quiser usar uma forma reativa angular ( https://angular.io/guide/reactive-forms ).
Você pode usar um controle de formulário para gerenciar o valor de saída do grupo de caixas de seleção.
componente
html
checklistState
Gerencia o modelo / estado das entradas da lista de verificação. Este modelo permite mapear o estado atual para qualquer formato de valor necessário.
Modelo:
checklist
Controle de formulárioEste controle armazena o valor que gostaria de salvar como, por exemplo
saída de valor:
"value_1,value_2"
Veja a demonstração em https://stackblitz.com/edit/angular-multi-checklist
fonte
Minha solução - resolvi para Angular 5 com Material View
A conexão é através do
Dessa forma, ele pode funcionar para matrizes de várias caixas de seleção em um formulário. Basta definir o nome do array de controles para conectar a cada vez.
No final você está conseguindo salvar o formulário com a matriz de id de registros originais para salvar / atualizar.
fonte
PARTE DO MODELO: -
PARTE DO CONTROLADOR: -
fonte
Adicione meus 5 centavos) Meu modelo de pergunta
template.html
component.ts
fonte
Resposta relacionada a @ nash11, eis como você produziria uma matriz de valores de caixa de seleção
E
tem uma caixa de seleção que também seleciona Todas as caixas de seleção:
https://stackblitz.com/edit/angular-checkbox-custom-value-with-selectall
fonte