Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

como manda uma lista criado por um ngFor

Ola, estou com um problema, tenho uma lista de produtos que recebo fazendo um "GET" em uma API Spring, nela vem as informações de produtos

codigo html do component produto:

  <tbody>
        <tr *ngFor="let product of listProduct; let i = index">
          <input type="hidden" value={{product.id}} name='productid-{{i}}' (ngModel)="products.id">
          <td class="text-uppercase"> <i class="bi bi-graph-up-arrow m-2 h4"></i>{{product.name}}</td>
          <td class="text-uppercase">$ {{product.price}}</td>
          <td>
            <input type="number" class="text-center" name="quantity" [(ngModel)]="quantity">
          </td>
          <td>
            <i class="bi bi-cart-check h5" role="button"></i>
          </td>
        </tr>
      </tbody>

só que esse form tem um input de quantidade, que o usuário vai ser capaz de mudar, mas ai ja tenho um problema, quando eu altero um input, ele altera todos, o que não é um comportamento desejavel.

Segundo que gostaria de ao clicar no botão de "add to cart", fosse pego toda a lista de objetos produto que estão com a propriedade "quantity" preenchida, mas essa propriedade não faz parte da minha classe produto, no meu modelo de objeto um produto não possui quantidade e sim o carrinho de compras. Mas não consigo pegar os valores e mandar para o component.ts

codigo do products.component.ts:

@Component({
  selector: 'app-products',
  templateUrl: './products.component.html',
  styleUrls: ['./products.component.scss']
})

export class ProductsComponent implements OnInit {

  public listProduct: Product[];

  @Input() public products: Product[];

  public quantity: number[];

  constructor(private service: ProductService){}

  ngOnInit(){
    this.service.getProducts().subscribe(
      (listProduct: Product[]) =>{
      this.listProduct = listProduct;
    },
      (error) => console.error(error)
    );
  }

  buildCarShopping(){
    console.log(this.products)
  }

}

Insira aqui a descrição dessa imagem para ajudar na acessibilidadeInsira aqui a descrição dessa imagem para ajudar na acessibilidadeSe alguém souber como fazer agradeço.

4 respostas

Fala Gabriel,

Parece que o problema está relacionado com o [(ngModel)] que utiliza o valor "quantity" sem ter um identificador exclusivo para ele, o que faz com que ocorra esse erro de todas as instâncias compartilharem da mesma variável.

Segue abaixo uma forma de resolver esse problema:

<input type="number" class="text-center" name="quantity-{{i}}" [(ngModel)]="quantity[i]">

Quando ao segundo pedido, do botão que "adiciona ao carrinho" somente os produtos com uma quantidade maior que zero, você pode fazer utilizar um filter.

<button (click)="addToCart()">Add to cart</button>

E no componente, setar o resultado do filtro direto na variável selectedProducts, desse jeito:

   ...
   selectedProducts: Product[] = [];
   ...
   addToCart() {
    this.selectedProducts = this.listProduct.filter(product => product.quantity > 0);
  }

Espero que esa resposta tenha esclarecido sua dúvida, e sigo a disposição.

Obrigado pela resposta Leandro.

mais uma dúvida se puder ajudar, como eu pego o valor do ID que está no meu input type ''hidden'', tentei de varias formas mas nao conseguir fazer:

          <input type="hidden" value={{product.id}} name='productid-{{i}}' (ngModel)="products.id">
solução!

Olá, Gabriel! Utilizar input type="hidden" para armazenar valores do objeto que estão no componente é considerado uma má prática. Em vez disso, você pode acessar diretamente o objeto product, onde já estão os valores do id necessários.

Ao usar ngModel, os valores da propriedade quantity são atualizados automaticamente tanto na tela quanto no objeto. Por isso sugeri aquele método filter dentro do addToCart() para filtrar os produtos maior que zero, após esse filtro você tem a lista de objetos Product com todas as propriedades incluindo o id

Mas, vamos simular que fosse necessário o tal input hidden ou você queira somente aprender como recuperar valores do input da tela sem usar ngModel. Marque seu input com essa técnica chamada "Template Reference Variable", no caso pode ser um nome qualquer, ex: #productId :

<input type="hidden" #productId value={{product.id}} name='productid-{{i}}'>

No seu componente, você utiliza o @ViewChildren para ouvir todos os elementos que usam essa referência:

@ViewChildren('productId') productIdElements: QueryList<ElementRef>;

addToCart() {
  this.productIdElements.forEach((element: ElementRef) => {
    const id = element.nativeElement.value;
    // Aqui você teria que fazer um filtro buscando o produto pelo id
  });
}

Acomplexidade é maior usando a solução acima, e temos que desenvolver de forma mais limpa.

No código abaixo está a solução simplificada e já exibindo a lista de id com o console.log

selectedProducts: Product[] = [];

addToCart() {
  this.selectedProducts = this.listProduct.filter(product => product.quantity > 0);

  this.selectedProducts.map(product => console.log(product.id));
}

Espero ter ajudado e me diga se conseguiu.

Valeu

Muito Obrigado Leandro pela ajuda.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software