Valor padrão das opções suspensas do Angular 2

115

No Angular 1, eu poderia selecionar a opção padrão para uma caixa suspensa usando o seguinte:

<select 
    data-ng-model="carSelection"
    data-ng-options = "x.make for x in cars" data-ng-selected="$first">
</select>

No Angular 2 eu tenho:

<select class="form-control" [(ngModel)]="selectedWorkout" (ngModelChange)="updateWorkout($event)">
    <option *ngFor="#workout of workouts">{{workout.name}}</option>
</select>

Como posso selecionar uma opção padrão, considerando os dados de minha opção:

[{name: 'arm'}, {name: 'back'}, {name:'leg'}]e meu valor I para o padrão é back?

ClickThisNick
fonte

Respostas:

77

Adicione um vínculo à selectedpropriedade, como este:

<option *ngFor="#workout of workouts" 
    [selected]="workout.name == 'back'">{{workout.name}}</option>
Douglas
fonte
4
Isso não parece funcionar, olhando para minha opção selecionada, ela não tem qualquer tipo de indicação selecionada
ClickThisNick
@ClickThisNick Funcionou quando o testei. Veja este plnkr . Quando termina o carregamento, a lista suspensa de seleção mostra "dois", embora o padrão normal seja o primeiro elemento ("um").
Douglas
2
A diferença com o código no plnr @Douglas é que ele não tem uma [(ngModel)]ligação, portanto, ele escuta a [selected]ligação no plnkr e não no código do OP (veja minha resposta para um link para um plnr bifurcado que explica esse efeito)
Matthijs de
2
Uso de formulários dinâmicos: Uso de formulários selected="workout.name == 'back'"reativos:[selected]=workout.name == 'back'
fidev
@fidev, você tem uma ótima resposta e era exatamente o que eu procurava. Basta dar uma olhada se seu exemplo de formulários reativos está faltando o ". Usei seu código com outra variável como esta[selected]="workout.name == exercise.name"
Alfa Bravo
48

Se você atribuir o valor padrão a selectedWorkoute usar [ngValue](que permite usar objetos como valor - caso contrário, apenas string é suportado), então ele deve apenas fazer o que você deseja:

<select class="form-control" name="sel" 
    [(ngModel)]="selectedWorkout" 
    (ngModelChange)="updateWorkout($event)">
  <option *ngFor="let workout of workouts" [ngValue]="workout">
    {{workout.name}}
  </option>
</select>

Certifique-se de que o valor que você atribui selectedWorkoutseja a mesma instância que o usado em workouts. Outra instância de objeto, mesmo com as mesmas propriedades e valores, não será reconhecida. Apenas a identidade do objeto é verificada.

atualizar

Suporte angular adicionado para compareWith, que torna mais fácil definir o valor padrão quando [ngValue]é usado (para valores de objeto)

Dos documentos https://angular.io/api/forms/SelectControlValueAccessor

<select [compareWith]="compareFn"  [(ngModel)]="selectedCountries">
    <option *ngFor="let country of countries" [ngValue]="country">
        {{country.name}}
    </option>
</select>
compareFn(c1: Country, c2: Country): boolean {
    return c1 && c2 ? c1.id === c2.id : c1 === c2;
}

Desta forma, uma instância de objeto diferente (nova) pode ser definida como valor padrão e compareFné usada para descobrir se eles devem ser considerados iguais (por exemplo, se a idpropriedade é a mesma.

Günter Zöchbauer
fonte
2
se você tiver tempo, você poderia fazer um plunkr para isso? Por alguma razão, quando tento fazer isso, $ event está parecendo um evento e não um objeto. Se eu alterar o evento para event.target.value, o valor
aparecerá
Eu acho que seria mais útil se você tentar criar um Plunker que permita reproduzir seu problema ;-) Talvez você esteja usando em [value]vez de [ngValue]ou seu código de alguma forma faça com que o valor seja convertido em uma string.
Günter Zöchbauer
O que fazer c1e c2indicar em compareFn? E também, como funciona a avaliação no corpo de funções?
DongBin Kim
O valor selectedCountriesecountry
Günter Zöchbauer
1
Consegui funcionar graças à primeira parte desta resposta.
The Sharp Ninja
35

apenas defina o valor do modelo para o padrão que você deseja, desta forma:

selectedWorkout = 'back'

Eu criei um fork do plnkr de @Douglas aqui para demonstrar as várias maneiras de obter o comportamento desejado no angular2.

Matthijs
fonte
1
para que isso funcione para mim (no angular 4), eu também tive que definir [ngValue] = "val". My itemssource não era um array de objetos, mas apenas um array de strings. <select [(ngModel)]="selectedTimeFrame"> <option *ngFor="let val of timeFrames" [ngValue]="val">val</option> </select>
S. Robijns
33

Adicione este código na posição o da lista de seleção.

<option [ngValue]="undefined" selected>Select</option>

Mahesh
fonte
1
qual é o propósito de definir [ngValue] como indefinido?
bluePearl
1
Esta deve ser a resposta aceita. Definir [ngValue] como indefinido trata adequadamente de ter um valor padrão selecionado quando o 'selecionar' primeiro renderiza.
Máx.
Concordo que esta é a resposta correta. Permite que você use a opção na posição 0
mobiusinversion
@bluePearl o modelo 'SelectedWorkout' começa como 'indefinido' se você não definir nada para ele. Então, esse deve ser o valor do item padrão.
Richard Aguirre
Esta é a melhor resposta
Richard Aguirre
20

Você pode abordar desta forma:

<option *ngFor="let workout of workouts" [value]="workout.name">{{workout.name}}</option>

ou assim:

  <option *ngFor="let workout of workouts" [attr.value]="workout.name" [attr.selected]="workout.name == 'leg' ? true : null">{{workout.name}}</option>

ou você pode definir o valor padrão desta forma:

<option [value]="null">Please Select</option>
<option *ngFor="let workout of workouts" [value]="workout.name">{{workout.name}}</option>

ou

<option [value]="0">Please Select</option>
<option *ngFor="let workout of workouts" [value]="workout.name">{{workout.name}}</option>
Anil Samal
fonte
14

Use o índice para mostrar o primeiro valor como padrão

<option *ngFor="let workout of workouts; #i = index" [selected]="i == 0">{{workout.name}}</option>
Sajith Mantharath
fonte
5

De acordo com https://angular.io/api/forms/SelectControlValueAccessor, você só precisa do seguinte:

theView.html:

<select [compareWith]="compareFn"  [(ngModel)]="selectedCountries">
    <option *ngFor="let country of countries" [ngValue]="country">
        {{country.name}}
    </option>
</select>

theComponent.ts

import { SelectControlValueAccessor } from '@angular/forms';
    compareFn(c1: Country, c2: Country): boolean {
    return c1 && c2 ? c1.id === c2.id : c1 === c2;
}
azatprog
fonte
4

Lutei um pouco com este, mas acabei com a seguinte solução ... talvez ajude alguém.

Template HTML:

<select (change)="onValueChanged($event.target)">
    <option *ngFor="let option of uifOptions" [value]="option.value" [selected]="option == uifSelected ? true : false">{{option.text}}</option>
</select>

Componente:

import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';    
export class UifDropdownComponent implements OnInit {
    @Input() uifOptions: {value: string, text: string}[];
    @Input() uifSelectedValue: string = '';
    @Output() uifSelectedValueChange:EventEmitter<string> = new EventEmitter<string>();
    uifSelected: {value: string, text: string} = {'value':'', 'text':''};

    constructor() { }

    onValueChanged(target: HTMLSelectElement):void {
        this.uifSelectedValue = target.value;
        this.uifSelectedValueChange.emit(this.uifSelectedValue);
    }

    ngOnInit() {
        this.uifSelected = this.uifOptions.filter(o => o.value == 
        this.uifSelectedValue)[0];
    }
}
johnb
fonte
3

Completando outras postagens, aqui está o que funciona no início rápido do Angular2,

Para definir o padrão DOM: juntamente com *ngFor, use uma instrução condicional no <option>'s selectedatributo.

Para definir o Controlpadrão de: use seu argumento de construtor. Caso contrário, antes de um onchange quando o usuário selecionar novamente uma opção, o que define o valor do controle com o atributo de valor da opção selecionada, o valor do controle será nulo.

roteiro:

import {ControlGroup,Control} from '@angular/common';
...
export class MyComponent{
  myForm: ControlGroup;
  myArray: Array<Object> = [obj1,obj2,obj3];
  myDefault: Object = myArray[1]; //or obj2

  ngOnInit(){ //override
    this.myForm = new ControlGroup({'myDropdown': new Control(this.myDefault)});
  }
  myOnSubmit(){
    console.log(this.myForm.value.myDropdown); //returns the control's value 
  }
}

marcação:

<form [ngFormModel]="myForm" (ngSubmit)="myOnSubmit()">
  <select ngControl="myDropdown">
    <option *ngFor="let eachObj of myArray" selected="eachObj==={{myDefault}}"
            value="{{eachObj}}">{{eachObj.myText}}</option>
  </select>
  <br>
  <button type="submit">Save</button>
</form>
BeatriceThalo
fonte
3

Você pode usar isso em [ngModel]vez de [(ngModel)]e está tudo bem

<select class="form-control" **[ngModel]="selectedWorkout"** (ngModelChange)="updateWorkout($event)">
   <option *ngFor="#workout of workouts">{{workout.name}}</option>
</select>
Saeed
fonte
3

Você pode fazer o seguinte:

<select class="form-control" 
        [(ngModel)]="selectedWorkout" 
        (ngModelChange)="updateWorkout($event)">
    <option *ngFor="#workout of workouts;
                    let itemIndex = index"
            [attr.selected]="itemIndex == 0">
    {{workout.name}}
    </option>
</select>

No código acima, como você pode ver, o atributo selecionado da opção de repetição é definido na verificação do índice do loop de repetição da lista. [attr. <nome do atributo html>] é usado para definir o atributo html no angular2.

Outra abordagem será definir o valor do modelo no arquivo typescript como:

this.selectedWorkout = this.workouts.length > 0
                       ? this.workouts[0].name
                       : 'No data found';//'arm'
Pranav Labhe
fonte
1

Acrescente à resposta de @Matthijs, certifique-se de que seu selectelemento tenha um nameatributo e nameseja único em seu template html. Angular 2 está usando o nome de entrada para atualizar as alterações. Portanto, se houver nomes duplicados ou nenhum nome anexado ao elemento de entrada, a ligação falhará.

Wei Xu
fonte
0

Adicionar propriedade de ligação selecionada, mas certifique-se de torná-la nula, para outros campos, por exemplo:

<option *ngFor="#workout of workouts" [selected]="workout.name =='back' ? true: null">{{workout.name}}</option>

Agora vai funcionar

Jcoder
fonte
0
<select class="form-control" name='someting' [ngModel]="selectedWorkout" (ngModelChange)="updateWorkout($event)">
    <option value="{{workout.name}}" *ngFor="#workout of workouts">{{workout.name}}</option>
</select>

Se você estiver usando o formulário, deve haver um namecampo dentro da selecttag.

Tudo que você precisa fazer é apenas adicionar valueà optiontag.

selectedWorkout o valor deve ser "back" e pronto.

Vivek Doshi
fonte
0

Se você não quiser a ligação bidirecional via [(ngModel)], faça o seguinte:

<select (change)="selectedAccountName = $event.target.value">
  <option *ngFor="let acct of accountsList" [ngValue]="acct">{{ acct.name }}</option>
</select>

Acabei de testar no meu projeto no Angular 4 e funciona! O accountsList é uma matriz de objetos Account em que name é uma propriedade de Account.

Observação interessante:
[ngValue] = "acct" exerce o mesmo resultado que [ngValue] = "acct.name".
Não sei como o Angular 4 consegue isso!

Daniel C. Deng
fonte
0

Etapa: 1 Crie a classe de declaração de propriedades

export class Task {
    title: string;
    priority: Array<any>;
    comment: string;

    constructor() {
        this.title      = '';
        this.priority   = [];
        this.comment    = '';
     }
}

Haste: 2 sua classe de componente

import { Task } from './task';

export class TaskComponent implements OnInit {
  priorityList: Array<any> = [
    { value: 0, label: '✪' },
    { value: 1, label: '★' },
    { value: 2, label: '★★' },
    { value: 3, label: '★★★' },
    { value: 4, label: '★★★★' },
    { value: 5, label: '★★★★★' }
  ];
  taskModel: Task           = new Task();

  constructor(private taskService: TaskService) { }
  ngOnInit() {
    this.taskModel.priority     = [3]; // index number
  }
}

Etapa: 3 Ver Arquivo .html

<select class="form-control" name="priority" [(ngModel)]="taskModel.priority"  required>
    <option *ngFor="let list of priorityList" [value]="list.value">
      {{list.label}}
    </option>
</select>

Resultado:

insira a descrição da imagem aqui

Ram Pukar
fonte
0

Para mim, defino algumas propriedades:

disabledFirstOption = true;

get isIEOrEdge(): boolean {
    return /msie\s|trident\/|edge\//i.test(window.navigator.userAgent)
}

Então, no construtor e no ngOnInit

constructor() {
    this.disabledFirstOption = false;
}

ngOnInit() {
    setTimeout(() => {
        this.disabledFirstOption = true;
    });
}

E no modelo eu adiciono isso como a primeira opção dentro do elemento select

<option *ngIf="isIEOrEdge" [value]="undefined" [disabled]="disabledFirstOption" selected></option>

Se você permitir a seleção da primeira opção, você pode simplesmente remover o uso da propriedade disabledFirstOption

Tinh Dang
fonte
0

No meu caso, aqui this.selectedtestSubmitResultViewestá definido com o valor padrão com base nas condições e uma variável testSubmitResultViewdeve ser igual a testSubmitResultView. Isso realmente funcionou para mim

<select class="form-control" name="testSubmitResultView"  [(ngModel)]="selectedtestSubmitResultView" (ngModelChange)="updatetestSubmitResultView($event)">
    <option *ngFor="let testSubmitResultView of testSubmitResultViewArry" [ngValue]="testSubmitResultView" >
        {{testSubmitResultView.testSubmitResultViewName}}
    </option>
</select>

Para maiores informações,

testSubmitResultViewArry: Array<any> = [];
selectedtestSubmitResultView: string;
    
getTestSubmitResultViewList() {
    try {
        this.examService.getTestSubmitResultViewDetails().subscribe(response => {
            if (response != null && response !== undefined && response.length > 0) {
                response.forEach(x => {
                    if (x.isDeleted === false) {
                        this.testSubmitResultViewArry.push(x);
                    }
                    if (x.isDefault === true) {
                        this.selectedtestSubmitResultView = x;
                    }
                })
            }
        });
    } catch (ex) {
        console.log('Method: getTestSubmitResultViewList' + ex.message);
    }
}
Nɪsʜᴀɴᴛʜ ॐ
fonte
-1

Eu enfrentei esse problema antes e o corrigi com uma maneira simples de contornar o problema

Para seu Component.html

      <select class="form-control" ngValue="op1" (change)="gotit($event.target.value)">

      <option *ngFor="let workout of workouts" value="{{workout.name}}" name="op1" >{{workout.name}}</option>

     </select>

Então, em seu component.ts, você pode detectar a opção selecionada por

gotit(name:string) {
//Use it from hare 
console.log(name);
}
Ramy Hakam
fonte
-1

funciona muito bem como visto abaixo:

<select class="form-control" id="selectTipoDocumento" formControlName="tipoDocumento" [compareWith]="equals"
          [class.is-valid]="this.docForm.controls['tipoDocumento'].valid &&
           (this.docForm.controls['tipoDocumento'].touched ||  this.docForm.controls['tipoDocumento'].dirty)"
          [class.is-invalid]="!this.docForm.controls['tipoDocumento'].valid &&
           (this.docForm.controls['tipoDocumento'].touched ||  this.docForm.controls['tipoDocumento'].dirty)">
            <option value="">Selecione um tipo</option>
            <option *ngFor="let tipo of tiposDocumento" [ngValue]="tipo">{{tipo?.nome}}</option>
          </select>
André Rodrigues de Sousa
fonte
-1

Você só precisa colocar o ngModel e o valor que deseja selecionar:

<select id="typeUser" ngModel="Advanced" name="typeUser">
  <option>Basic</option>
  <option>Advanced</option>
  <option>Pro</option>
</select>
q2design.net
fonte