12
respostas

Como obter valor de um select

Estou criando um componente que contem um select com todos os livros que vem da API. Vou usar esse select em outro componente para fazer o cadastro do emprestimo do livro, como faco para pegar o valor do select ? Estou tentando da seguinte maneira: book.select.component.html

<div class="form-group">
    <label class="control-label">Book Name</label>
    <select [(ngModel)]="model" name="livro" class="form-control">
        <option *ngFor="let book of books" [ngValue]="book">{{book.nome}}</option>
    </select>
</div>

book.select.component.ts

import { Component, Input } from "@angular/core";
import { BookComponent } from "./book.component";
import { BookService } from "./book.service";


@Component({
    moduleId: module.id,
    selector: 'select-book',
    templateUrl: './book.select.component.html'
})

export class BookSelectComponent{

    @Input() model;
    books: BookComponent[] = [];
    service: BookService;

    constructor(service: BookService){
        this.service = service;

        service.getList()
        .subscribe(books => {
            this.books = books;
        }, error => console.log(error));

    }

}

loan.register.component.html

<div class="container">
    <div class="row">
        <div class="col-md-3"></div>
        <div class="col-md-6">
            <h1>New Loan</h1>
            <form [formGroup]="form" (submit)="identifyAction($event)">

                <select-book model="loan.livro"></select-book>

                <select-user></select-user>

                <div class="form-group">
                    <label class="control-label">Loan Date</label>
                    <input type="date" formControlName="dataEmprestimo" [(ngModel)]="loan.dataEmprestimo" name="dataEmprestimo"
                     class="form-control">
                </div>
                <div class="form-group">
                    <label class="control-label">Return Date</label>
                    <input type="date" formControlName="dataDevolucao" [(ngModel)]="loan.dataDevolucao" name="dataDevolucao"
                     class="form-control">
                </div>
                <div class="form-group">
                    <label class="control-label">Returned</label>
                    <input type="checkbox" formControlName="devolvido" [(ngModel)]="loan.devolvido" name="devolvido"
                     class="form-control">
                </div>

                <a [routerLink]="['']" class="btn btn-default">Back To List</a>
                <button type="submit" class="btn btn-success">Register / Edit Loan</button>
            </form>
        </div>
        <!--col-md-6-->
        <div class="col-md-3"></div>
    </div>
    <!--row-->
</div>
<!--container-->
12 respostas

loan.register.component.ts

import { Component } from "@angular/core";
import { LoanComponent } from "./loan.component";
import { LoanService } from "./loan.service";
import { ActivatedRoute, Router } from "@angular/router";
import { FormGroup, FormBuilder, Validators } from "@angular/forms";

@Component({
    moduleId: module.id,
    selector: 'form-loan',
    templateUrl: './loan.register.component.html'
})

export class LoanRegisterComponent{

    loan: LoanComponent = new LoanComponent();
    service: LoanService;
    activatedRoute: ActivatedRoute;
    router: Router;
    form: FormGroup;

    constructor(service: LoanService, fb: FormBuilder, activatedRoute: ActivatedRoute, router: Router) {

                this.service = service;

                this.activatedRoute = activatedRoute;
                this.router = router;

                this.activatedRoute.params.subscribe(params => {

                    let id = params["id"];

                    if(id){
                        this.service
                        .getById(id)
                        .subscribe(loan => this.loan = loan, erro => console.log(erro));
                    }

                });

                this.form = fb.group({
                    livro: [""],
                    usuario: [""],
                    dataEmprestimo: [""],
                    dataDevolucao: [""],
                    devolvido: [""]
                });

            }

            identifyAction(event) {

                if(this.loan.id){
                    this.update(event);
                }
                else{
                    this.add(event);
                }

            }

            add(event) {
                console.log(this.loan.livro);
                this.service.add(this.loan).subscribe(res => {
                    this.loan = new LoanComponent();
                }, erro => console.log(erro));

            }

            update(event) {

                this.service.update(this.loan).subscribe(res => {
                    this.router.navigate(["/loans"]);
                }, erro => console.log(erro));

            }

}

loan.component.ts

import { Component } from "@angular/core";
import { BookComponent } from "../book/book.component";
import { UserComponent } from "../user/user.component";

@Component({
    moduleId: module.id,
    template: ''
})

export class LoanComponent{

    id: number;
    livro: BookComponent;
    usuario: UserComponent;
    dataEmprestimo: Date = new Date();
    dataDevolucao: Date = new Date();
    devolvido: boolean;

}

Boa tarde. Analisando seu código, você esta fazendo o bind corretamente do valor selecionado. Qual valor esta chegando em BookSelectComponent, na propriedade model?

Esta undefined. Olhando pro json que ele monta

{dataEmprestimo: "275760-05-02", dataDevolucao: "58484-12-04", devolvido: true}

O livro nao esta sendo pego, mas nao sei o motivo.

Lucas, fiz um teste do seu componente usando um mock dos dados de um livro e seu componente funcionou perfeitamente consultando o dado logo em seguida.

Foi este código que fiz para testar:

book-select.component.ts

import { Component, Input } from '@angular/core'

@Component({
  selector: 'select-book',
  template: `
  <div class="form-group">
    <label class="control-label">Book Name</label>
    <select [(ngModel)]="model" name="livro" >
        <option *ngFor="let book of books" [ngValue]="book">{{book.nome}}</option>
    </select>
  </div>

  <!-- aqui estou consultando o valor do atributo model que está
 recebendo o valor selecionado,
 por causa do uso da diretiva NgModel -->
  {{model.nome}}
  `,
  styles: []
})
export class BookSelectComponent {

  @Input() model = ''
  books = [
    {nome: 'livro1'},
    {nome: 'livro2'},
    {nome: 'livro3'}
  ]

  constructor(){}

}

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <select-book></select-book>
  `,
  styles: []
})
export class AppComponent {
  title = 'app';
}

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule, FormsModule } from '@angular/forms'

import { AppComponent } from './app.component';
import { BookSelectComponent } from './book-select/book-select.component';


@NgModule({
  declarations: [
    AppComponent,
    BookSelectComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

No seu componente você está conseguindo ver o nome dos livros no select?

Seu BookComponent esta estranho.

 @Input() model;

Você esta indicando que a propriedade model é uma inbound property, mas esta realizando um bind para passar o valor para ele. Estou confuso com o que você esta querendo com isso.

Experimente remover o @Input().

Sobre o código que você postou:

<div class="form-group">
    <label class="control-label">Book Name</label>
    <select [(ngModel)]="model" name="livro" class="form-control">
        <option *ngFor="let book of books" [ngValue]="book">{{book.nome}}</option>
    </select>
</div>

Você usou corretamente o *ngFor, inclusive usou o [ngValue] para que pudesse associar um objeto, pois se tivesse usado o [value] ele guardaria não o objeto, mas a representação dele como string.

Como disse, remova o @Input() e verifique o resultado.

Continuou undefined, vou tentar explicar o que tentei fazer. Eu estou usando o @Input() model para passar o loan.livro no register.loan.component, sendo o ngModel do select, assim eu conseguiria pegar o objeto do livro selecionado. Se eu coloco loan.livro direto no ngModel do book.select.component recebo o erro: "BookSelectComponent.html:3 ERROR TypeError: Cannot read property 'livro' of undefined" Vou deixar o codigo abaixo.

<div class="form-group">
    <label class="control-label">Book Name</label>
    <select [(ngModel)]="loan.livro" name="livro" class="form-control">
        <option *ngFor="let book of books" [ngValue]="book">{{book.nome}}</option>
    </select>
</div>

Queria saber o que preciso colocar no NgModel para que o data binding funcione e eu obtenha o objeto do livro selecionado.

Lucas, como valor do ngModel passamos o nome do atributo da classe do componente que receberá o valor do select, pois é o ngModel o responsável por passar o valor do select para algum atributo.

Então vc não pode passar um atributo que já tem outra função, você tem que criar um atributo novo específico para isto (receber o valor do select).

Faz sentido?

Oi Vanessa, faz sentindo sim, tentei implementar aqui da seguinte maneira, coloquei uma prop chamada selectedValue no meu component.

    loan: LoanComponent = new LoanComponent();
    selectedValue;
    service: LoanService;
    activatedRoute: ActivatedRoute;
    router: Router;
    form: FormGroup;

e passei na view desse jeito

<select-book formControlName="selectedValue" [(ngModel)]="selectedValue" name="selectedValue" ngDefaultControl></select-book>

mas devo estar fazendo algo errado, pois o que ele pegou foi o nome do livro e nao o objeto todo. No meu ngValue passei o objeto

<div class="form-group">
    <label class="control-label">Book Name</label>
    <select name="livro" class="form-control">
        <option *ngFor="let book of books" [ngValue]="book">{{book.nome}}</option>
    </select>
</div>

Consegui entender o que vc precisa, mas ainda não encontrei a resposta certa.

Você precisa que <select-book></select-book> retorne um BookComponent para o ngModel na view loan.register.component.html

Vou continuar fazendo uns testes aqui, mas se mais alguém quiser ajudar, pelo menos já temos o problema bem entendido, haha!

Exatamente, perdao pela confusao, simplificando aqui so, eu consigo exibir os livros no select sem problemas, meu problema e que preciso mandar o objeto do livro selecionado e nao sei como fazer isso.

Ideias para vc também ir tentando, é trabalhar os tipos ou instancias dos objetos em LoanRegisterComponent.

Por exemplo tentar definir um tipo para SelectedValue, ou isso virar o valor para uma instancia de BookComponent... Ou algo nessa linha... :)

Sim, agora pelo menos ja sei exatamente o que preciso fazer :D