Valor predeterminado de las opciones desplegables de Angular 2

115

En Angular 1, podría seleccionar la opción predeterminada para un cuadro desplegable usando lo siguiente:

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

En Angular 2 tengo:

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

¿Cómo podría seleccionar una opción predeterminada dado que los datos de mi opción son:

[{name: 'arm'}, {name: 'back'}, {name:'leg'}]y mi valor predeterminado es back?

ClickThisNick
fuente

Respuestas:

77

Agregue un enlace a la selectedpropiedad, como este:

<option *ngFor="#workout of workouts" 
    [selected]="workout.name == 'back'">{{workout.name}}</option>
Douglas
fuente
4
Eso no parece funcionar, mirando mi opción seleccionada, no tiene ningún tipo de indicación seleccionada
ClickThisNick
@ClickThisNick Funcionó cuando lo probé. Vea este plnkr . Cuando termina de cargarse, el menú desplegable de selección muestra "dos" aunque el valor predeterminado normal sería el primer elemento ("uno").
Douglas
2
La diferencia con el código en @Douglas plnr es que no tiene un [(ngModel)]enlace, por lo tanto, escucha el [selected]enlace en el plnkr y no en el código del OP (vea mi respuesta para obtener un enlace a un plnr bifurcado que explica este efecto)
Matthijs
2
Uso de formularios dinámicos: uso de formularios selected="workout.name == 'back'"reactivos:[selected]=workout.name == 'back'
fidev
@fidev, tienes una gran respuesta, y era exactamente lo que estaba buscando. Solo observe que a su ejemplo de formularios reactivos les falta el ". Usé su código con otra variable como esta[selected]="workout.name == exercise.name"
Alfa Bravo
48

Si asigna el valor predeterminado ay selectedWorkoutusa [ngValue](que permite usar objetos como valor; de lo contrario, solo se admiten cadenas), entonces debería hacer lo que quiera:

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

Asegúrese de que el valor que asigna selectedWorkoutsea ​​la misma instancia que la utilizada en workouts. No se reconocerá otra instancia de objeto, incluso con las mismas propiedades y valores. Solo se comprueba la identidad del objeto.

actualizar

Soporte agregado angular para compareWith, que hace que sea más fácil establecer el valor predeterminado cuando [ngValue]se usa (para valores de objeto)

De los 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;
}

De esta manera, se puede establecer una instancia de objeto diferente (nueva) como valor predeterminado y compareFnse usa para determinar si deben considerarse iguales (por ejemplo, si la idpropiedad es la misma.

Günter Zöchbauer
fuente
2
si tienes tiempo, ¿podrías hacer un plunkr por esto? Por alguna razón, cuando lo intento, $ event aparece como un evento y no como un objeto. Si cambio event a event.target.value, el valor aparece como una cadena como '[object]'
crh225
Supongo que sería más útil si intentas crear un Plunker que permita reproducir tu problema ;-) Quizás estás usando en [value]lugar de [ngValue]o tu código de alguna manera hace que el valor se convierta en una cadena.
Günter Zöchbauer
¿Qué hacen c1e c2indican en compareFn? Y también, ¿cómo funciona la evaluación en el cuerpo funcional?
DongBin Kim
El valor selectedCountriesycountry
Günter Zöchbauer
1
Lo hice funcionar gracias a la primera parte de esta respuesta.
The Sharp Ninja
35

simplemente establezca el valor del modelo en el valor predeterminado que desea así:

selectedWorkout = 'back'

Creé una bifurcación de plnkr de @Douglas aquí para demostrar las diversas formas de obtener el comportamiento deseado en angular2.

Matthijs
fuente
1
para que esto funcione para mí (en angular 4) también tuve que establecer [ngValue] = "val". Sin embargo, mi fuente de elementos no era una matriz de objetos, sino solo una matriz de cadenas. <select [(ngModel)]="selectedTimeFrame"> <option *ngFor="let val of timeFrames" [ngValue]="val">val</option> </select>
S. Robijns
33

Agregue este código en la posición o de la lista de selección.

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

Mahesh
fuente
1
¿Cuál es el propósito de establecer [ngValue] en indefinido?
bluePearl
1
Esta debería ser la respuesta aceptada. Establecer [ngValue] en undefined maneja correctamente tener un valor predeterminado seleccionado cuando el 'select' se procesa por primera vez.
Max
De acuerdo, esta es la respuesta correcta. Le permite usar la opción en la posición 0
mobiusinversion
@bluePearl, el modelo 'SelectedWorkout' comienza como 'indefinido' si no le asigna nada. Entonces ese debe ser el valor del elemento predeterminado.
Richard Aguirre
Esta es la mejor respuesta
Richard Aguirre
20

Puedes acercarte de esta manera:

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

o de esta manera:

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

o puede establecer el valor predeterminado de esta manera:

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

o

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

Utilice el índice para mostrar el primer valor como predeterminado

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

Según https://angular.io/api/forms/SelectControlValueAccessor , solo necesita lo siguiente:

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
fuente
4

Luché un poco con este, pero terminé con la siguiente solución ... tal vez ayude a alguien.

Plantilla 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
fuente
3

Completamente desarrollando otras publicaciones, esto es lo que funciona en el inicio rápido de Angular2,

Para establecer el DOM predeterminado: junto con *ngFor, use una declaración condicional en el atributo <option>'s selected.

Para configurar el Control valor predeterminado de: use su argumento de constructor. De lo contrario, antes de un cambio cuando el usuario vuelve a seleccionar una opción, que establece el valor del control con el atributo de valor de la opción seleccionada, el valor del control será nulo.

guión:

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 
  }
}

margen:

<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
fuente
3

Puedes usar eso en [ngModel]lugar de [(ngModel)]y está bien

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

Puede hacer lo anterior:

<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>

En el código anterior, como puede ver, el atributo seleccionado de la opción de repetición se establece al verificar el índice del bucle de repetición de la lista. [attr. <nombre de atributo html>] se utiliza para configurar el atributo html en angular2.

Otro enfoque será establecer el valor del modelo en el archivo mecanografiado como:

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

Agregue a la respuesta de @Matthijs, asegúrese de que su selectelemento tenga un nameatributo y namesea ​​único en su plantilla html. Angular 2 está usando el nombre de entrada para actualizar los cambios. Por lo tanto, si hay nombres duplicados o no hay un nombre adjunto al elemento de entrada, el enlace fallará.

Wei Xu
fuente
0

Agregue la propiedad de enlace seleccionada, pero asegúrese de que sea nula, para otros campos, por ejemplo:

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

Ahora funcionará

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

Si está utilizando un formulario, debe haber un namecampo dentro de la selectetiqueta.

Todo lo que necesita hacer es agregar valuea la optionetiqueta.

selectedWorkout el valor debe ser "back", y listo.

Vivek Doshi
fuente
0

Si no desea el enlace bidireccional a través de [(ngModel)], haga esto:

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

¡Acabo de probar mi proyecto en Angular 4 y funciona! El accountsList es una matriz de objetos Account en el que name es una propiedad de Account.

Observación interesante:
[ngValue] = "acct" ejerce el mismo resultado que [ngValue] = "acct.name".
¡No sé cómo lo logra Angular 4!

Daniel C. Deng
fuente
0

Paso: 1 Crear propiedades declarar clase

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

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

Potencia: 2 Su clase 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
  }
}

Paso: 3 Ver archivo .html

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

Salida:

ingrese la descripción de la imagen aquí

Ram Pukar
fuente
0

Para mí, defino algunas propiedades:

disabledFirstOption = true;

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

Luego en el constructor y ngOnInit

constructor() {
    this.disabledFirstOption = false;
}

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

Y en la plantilla agrego esto como la primera opción dentro del elemento de selección

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

Si permite seleccionar la primera opción, simplemente puede eliminar el uso de la propiedad disabledFirstOption

Tinh Dang
fuente
0

En mi caso, aquí this.selectedtestSubmitResultViewse establece con un valor predeterminado en función de las condiciones y una variable testSubmitResultViewdebe ser una y la misma que testSubmitResultView. Esto de hecho funcionó para mí

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

Para más información,

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ʜᴀɴᴛʜ ॐ
fuente
-1

Me enfrenté a este problema antes y lo solucioné con una solución alternativa simple

Para su 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>

Luego, en su component.ts puede detectar la opción seleccionada por

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

funciona muy bien como se ve a continuación:

<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
fuente
-1

Solo necesita poner el ngModel y el valor que desea seleccionar:

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