Inicializando select con AngularJS y ng-repeat

133

Estoy tratando de hacer que select-box comience con una opción precargada usando ng-repeat con AngularJS 1.1.5. En cambio, la selección siempre comienza sin nada seleccionado. También tiene una opción vacía, que no quiero. Creo que hay un efecto secundario de no seleccionar nada.

Puedo hacer que esto funcione usando ng-options en lugar de ng-repeat, pero quiero usar ng-repeat para este caso. Aunque mi ejemplo reducido no lo muestra, también quiero establecer el atributo de título de cada opción, y que yo sepa, no hay forma de hacerlo usando ng-options.

No creo que esto esté relacionado con el alcance común de AngularJs / problema de herencia prototípica. Al menos no veo nada obvio al inspeccionar en Batarang. Además, cuando elige una opción en la selección con la interfaz de usuario, el modelo se actualiza correctamente.

Aquí está el HTML:

<body ng-app ng-controller="AppCtrl">
    <div>
        Operator is: {{filterCondition.operator}}
    </div>
    <select ng-model="filterCondition.operator">
       <option 
           ng-repeat="operator in operators" 
           value="{{operator.value}}"
       >
           {{operator.displayName}}
       </option>
    </select>
</body>

Y el JavaScript:

function AppCtrl($scope) {

    $scope.filterCondition={
        operator: 'eq'
    }

    $scope.operators = [
        {value: 'eq', displayName: 'equals'},
        {value: 'neq', displayName: 'not equal'}
     ]
}

JS Fiddle para esto: http://jsfiddle.net/coverbeck/FxM3B/2/

Charles O.
fuente
1
ngOption se creó porque no había una forma limpia de hacer esto con ngRepeat. ngRepeat se desenrolla después de que se ha seleccionado la opción. ¿Has intentado configurar ngSelect en tus opciones
TheSharpieOne
¡Si! El ngSelected funcionó! Publicaré un JsFiddle de trabajo actualizado.
Charles O.
Cabe señalar que en AngualrJS 1.2 este código funciona de manera diferente: no crea un nuevo elemento <OPTION> vacío, sin embargo, solo puede seleccionar la primera opción en el cuadro de lista. Puedes verlo aquí
VitalyB,

Respuestas:

226

OKAY. Si no desea utilizar la forma correcta ng-options, puede agregar un ng-selectedatributo con una lógica de verificación de condición para que la optiondirectiva haga que la preselección funcione.

<select ng-model="filterCondition.operator">
    <option ng-selected="{{operator.value == filterCondition.operator}}"
            ng-repeat="operator in operators"
            value="{{operator.value}}">
      {{operator.displayName}}
    </option>
</select>

Working Demo

zs2020
fuente
37
Te daré el crédito ya que lo descubriste por tu cuenta e hiciste el ejemplo completo. Aunque no estoy de acuerdo con tu comentario acerca de que ng-options es la "forma correcta". :) Siempre he usado ng-options, pero esto requería hacer algo que ng-options no admite, por pequeño que sea. Y el documento Angular dice que también puedes hacer ng-repeat. Gracias, Charles
Charles O.
Gracias, esa fue una manera fácil de deshabilitar algunas opciones.
Dorian
11
ng-options solo es correcto siempre que sus casos de uso se ajusten a los suyos. Es posible que necesite atributos / clases adicionales en los campos de opción / optgroup, etc.
mystrdat
66
"la forma correcta" a veces no funciona (por ejemplo, si desea traducir las cadenas que llenan los nombres de las opciones)
btk
11
Creo que la expresión ng-selected tiene que estar sin {{}}: ng-selected = "operator.value == filterCondition.operator"
mvermand
35

Para la etiqueta select, angular proporciona la directiva ng-options. Le proporciona el marco específico para configurar opciones y establecer un valor predeterminado. Aquí está el violín actualizado usando ng-options que funciona como se esperaba: http://jsfiddle.net/FxM3B/4/

HTML actualizado (el código permanece igual)

<body ng-app ng-controller="AppCtrl">
<div>Operator is: {{filterCondition.operator}}</div>
<select ng-model="filterCondition.operator" ng-options="operator.value as operator.displayName for operator in operators">
</select>
</body>
Jeremy Likness
fuente
3
Hola Jeremy, estoy tratando de hacer esto sin ng-options. Como dije en mi pregunta y en respuesta a Shaun, me gustaría establecer el atributo de título en cada opción, y no puedo hacerlo con ng-options, que yo sepa. Gracias, Charles
Charles O.
9

Gracias a TheSharpieOne por señalar la opción ng-selected. Si eso hubiera sido publicado como una respuesta en lugar de como un comentario, habría hecho que la respuesta correcta.

Aquí hay un JSFiddle que funciona: http://jsfiddle.net/coverbeck/FxM3B/5/ .

También actualicé el violín para usar el atributo de título, que había dejado fuera en mi publicación original, ya que no era la causa del problema (pero es la razón por la que quiero usar ng-repeat en lugar de ng-options) .

HTML:

<body ng-app ng-controller="AppCtrl">
<div>Operator is: {{filterCondition.operator}}</div>
<select ng-model="filterCondition.operator">
   <option ng-repeat="operator in operators" title="{{operator.title}}" ng-selected="{{operator.value == filterCondition.operator}}" value="{{operator.value}}">{{operator.displayName}}</option>
</select>
</body>

JS:

function AppCtrl($scope) {

    $scope.filterCondition={
        operator: 'eq'
    }

    $scope.operators = [
        {value: 'eq', displayName: 'equals', title: 'The equals operator does blah, blah'},
        {value: 'neq', displayName: 'not equal', title: 'The not equals operator does yada yada'}
     ]
}
Charles O.
fuente
Perdón por publicar como comentario. No tenía ganas de dar un ejemplo y no estaba 100% seguro de que funcionaría. Fue solo una corazonada.
TheSharpieOne
9

El hecho de que angular esté inyectando un elemento de opción vacío a la selección es que el objeto modelo vinculado a él por defecto viene con un valor vacío cuando se inicializa.

Si desea seleccionar una opción predeterminada, probablemente pueda establecerla en el alcance del controlador

$scope.filterCondition.operator = "your value here";

Si quieres un marcador de posición de opción vacío, esto funciona para mí

<select ng-model="filterCondition.operator" ng-options="operator.id as operator.name for operator in operators">
  <option value="">Choose Operator</option>
</select>
Ammadu
fuente
2
Esto es bueno, pero Angular crea una opción en blanco. ¿Cómo evitar esto?
MarceloBarbosa
1

Como se sugirió, debe usar ng-options y, desafortunadamente, creo que necesita hacer referencia al elemento de matriz para un valor predeterminado (a menos que la matriz sea una matriz de cadenas).

http://jsfiddle.net/FxM3B/3/

El JavaScript:

function AppCtrl($scope) {


    $scope.operators = [
        {value: 'eq', displayName: 'equals'},
        {value: 'neq', displayName: 'not equal'}
     ]

    $scope.filterCondition={
        operator: $scope.operators[0]
    }
}

El HTML:

<body ng-app ng-controller="AppCtrl">
<div>Operator is: {{filterCondition.operator.value}}</div>
<select ng-model="filterCondition.operator" ng-options="operator.displayName for operator in operators">
</select>
</body>
shaunhusain
fuente
¿Sabes por qué y estás seguro? La documentación ( docs.angularjs.org/api/ng.directive:select ) dice que solo necesita usar ng-options cuando se vincula a un valor que no es de cadena. Como dije, quiero usar el atributo de título, y no hay forma de hacerlo con ng-options. Algo así como <option title = "Una descripción muy larga de esta elección" ...> Gracias.
Charles O.
Creo que la nota en los documentos no está clara y en realidad significa que tendría que estar usando una cadena para el modelo y tener una serie de cadenas para las opciones. Si no le importa cuál es el razonamiento para usar el atributo "título", no lo veo en W3C w3schools.com/tags/tag_option.asp y no recuerdo haberlo usado realmente. ¿No podría simplemente almacenar la descripción en los objetos y aún así recuperar esos datos ya que a eso es a lo que ahora está vinculado el modelo?
shaunhusain
En la página W3C a la que se vinculó, si hace clic en el enlace Atributos globales, verá que el atributo de título es compatible con el elemento de opción. Estoy usando el atributo de título solo para mostrar el texto de "información sobre herramientas", de modo que si pasa el cursor sobre una opción, puede obtener una descripción más amplia de lo que significa la opción. Es algo pequeño, pero sería bueno tenerlo, si es posible.
Charles O.
@CharlesO. Quiero hacer exactamente como tú Establecer un objeto (valor que no sea de cadena) pero también quiero usar un título en la lista de opciones. Existe alguna solucion para esto. Parece que no puedo encontrarlo ...
March
1

Si está utilizando md-select y ng-repeat ing md-option de material angular, puede agregar ng-model-options="{trackBy: '$value.id'}"a la etiqueta md-select ceniza que se muestra en este bolígrafo

Código:

<md-select ng-model="user" style="min-width: 200px;" ng-model-options="{trackBy: '$value.id'}">
  <md-select-label>{{ user ? user.name : 'Assign to user' }}</md-select-label>
  <md-option ng-value="user" ng-repeat="user in users">{{user.name}}</md-option>
</md-select>

Japheth Ongeri - inkalimeva
fuente