Mengapa AngularJS menyertakan opsi kosong di pilih?

652

Saya telah bekerja dengan AngularJS selama beberapa minggu terakhir, dan satu hal yang benar-benar mengganggu saya adalah bahwa bahkan setelah mencoba semua permutasi atau konfigurasi yang ditentukan dalam spesifikasi di http://docs.angularjs.org/api/ng .directive: select , saya masih mendapatkan opsi kosong sebagai anak pertama dari elemen pilih.

Inilah Giok:

select.span9(ng-model='form.type', required, ng-options='option.value as option.name for option in typeOptions');

Di sini controller:

$scope.typeOptions = [
    { name: 'Feature', value: 'feature' },
    { name: 'Bug', value: 'bug' },
    { name: 'Enhancement', value: 'enhancement' }
];

Akhirnya, inilah HTML yang dihasilkan:

<select ng-model="form.type" required="required" ng-options="option.value as option.name for option in typeOptions" class="span9 ng-pristine ng-invalid ng-invalid-required">
    <option value="?" selected="selected"></option>
    <option value="0">Feature</option>
    <option value="1">Bug</option>
    <option value="2">Enhancement</option>
</select>

Apa yang harus saya lakukan untuk menghilangkannya?

PS: Hal-hal bekerja tanpa ini juga, tetapi hanya terlihat aneh jika Anda menggunakan select2 tanpa banyak pilihan.

Sudhanshu
sumber

Jawaban:

646

Kosong optiondihasilkan ketika nilai yang dirujuk oleh ng-modeltidak ada di set opsi yang diteruskan ng-options. Ini terjadi untuk mencegah pemilihan model yang tidak disengaja: AngularJS dapat melihat bahwa model awal tidak terdefinisi atau tidak dalam set pilihan dan tidak ingin memutuskan nilai model sendiri.

Jika Anda ingin menyingkirkan opsi kosong cukup pilih nilai awal di controller Anda, sesuatu seperti:

$scope.form.type = $scope.typeOptions[0].value;

Inilah jsFiddle: http://jsfiddle.net/MTfRD/3/

Singkatnya: opsi kosong berarti bahwa tidak ada model yang valid dipilih (maksud saya valid: dari serangkaian pilihan). Anda harus memilih nilai model yang valid untuk menyingkirkan opsi kosong ini.

pkozlowski.opensource
sumber
7
Saya mencoba dengan $ scope.form.type = ''; dan $ scope.form.type = $ scope.typeOptions [0], namun saya masih melihat ini - <option value = "?" terpilih = "terpilih"> </option>
Sudhanshu
5
Kadang-kadang benar-benar tidak masuk akal untuk memiliki data ini di JS. Jika server yang membuat keputusan tentang apa yang ada dalam pemilihan itu, mengapa JS harus menduplikatnya?
heneryville
11
Sayangnya ini tidak berfungsi jika Anda menggunakan array dan nullmerupakan salah satu nilai Anda.
vpiTriumph
6
Apakah mungkin untuk menambahkan teks di dalam kosong <option>sehingga tat angular menghasilkan sesuatu seperti<option value="?">Select an option</option>
RPDeshaies
3
@ Tareck117 hanya wirte itu <option value="">Select an option</option>Nilai-nol dari daftar opsi. Tidak perlu untuk?
Sebastian
235

Jika Anda menginginkan nilai awal, lihat jawaban @ pkozlowski.opensource, yang FYI juga dapat diimplementasikan dalam tampilan (daripada di controller) menggunakan ng-init:

<select ng-model="form.type" required="required" ng-init="form.type='bug'"
  ng-options="option.value as option.name for option in typeOptions" >
</select>

Jika Anda tidak menginginkan nilai awal, "elemen hard-kode tunggal, dengan nilai yang disetel ke string kosong, dapat disarangkan ke dalam elemen. Elemen ini kemudian akan mewakili opsi nol atau" tidak dipilih "":

<select ng-model="form.type" required="required"
  ng-options="option.value as option.name for option in typeOptions" >
    <option style="display:none" value="">select a type</option>
</select>
Mark Rajcok
sumber
4
@hugo, working fiddle: jsfiddle.net/4qKyx/1 Perhatikan bahwa "select a type" ditampilkan, tetapi tidak ada nilai yang terkait dengannya. Dan sekali Anda memilih sesuatu yang lain, Anda tidak akan melihatnya lagi. (Uji pada Chrome.)
Mark Rajcok
1
@MarkRajcok - saran bagus! Saya telah menemukan masalah lain menggunakan contoh Anda dengan transcluding direktif. Bisakah Anda melihatnya? plnkr.co/edit/efaZdEQlNfoDihk1R1zc?p=preview
Jan-Terje Sørensen
2
Masalah dengan ini adalah Anda masih dapat memilih dengan keyboard, lihat solusi stackoverflow.com/a/8442831/57344
HaveAGuess
2
Ini mungkin berfungsi untuk saat ini, tetapi dokumentasi sudut secara khusus merekomendasikan untuk tidak menggunakan ng-init untuk apa pun selain ng-repeat - lihat docs.angularjs.org/api/ng/directive/ngInit
Ed Norris
3
Tidak bekerja di IE10, "pilih tipe" selalu terlihat dan dapat dipilih.
Robin
121

Sudut <1.4

Bagi siapa pun di luar sana yang memperlakukan "null" sebagai nilai yang valid untuk salah satu opsi (jadi bayangkan bahwa "null" adalah nilai dari salah satu item dalam typeOptions dalam contoh di bawah), saya menemukan cara paling sederhana untuk memastikan bahwa secara otomatis ditambahkan opsi yang disembunyikan adalah menggunakan ng-if.

<select ng-options="option.value as option.name for option in typeOptions">
    <option value="" ng-if="false"></option>
</select>

Kenapa ng-jika dan tidak ng-sembunyikan? Karena Anda ingin penyeleksi css yang akan menargetkan opsi pertama di dalam, pilih untuk menargetkan opsi "nyata", bukan yang disembunyikan. Ini berguna ketika Anda menggunakan busur derajat untuk pengujian e2e dan (untuk alasan apa pun) yang Anda gunakan by.css () untuk menargetkan opsi pilih.

Angular> = 1.4

Karena refactoring arahan pilih dan opsi, menggunakan ng-iftidak lagi menjadi opsi yang layak sehingga Anda harus beralih ng-show="false"untuk membuatnya bekerja lagi.

WTK
sumber
5
Seharusnya jawaban yang diterima, karena ini adalah perilaku visual yang benar untuk pilih. Anda menempatkan size="5"atribut untuk memilih dan Anda dapat melihat bahwa tidak ada yang dipilih! Seperti di <select>-Element default ! Saya tidak dapat mengerti mengapa sudut melakukan hal seperti itu untuk memilih tanpa multipleatribut ...
Sebastian
1
Ya saya setuju, ini harus menjadi jawaban yang diterima. Ini adalah 'sudut jalan'. ng-jika benar-benar menghapus elemen opsi dari dom (ketika false) sehingga solusi ini juga bekerja pada semua browser tanpa pengkodean 'hacky' (bertentangan dengan ng-hide atau ng-show).
Sander_P
2
@Sander_P menurut definisi solusi ini adalah "hacky" coding menurut pendapat saya (meletakkan sesuatu di dom untuk menipu sudut untuk mengambilnya), tetapi Anda benar itu masih merupakan solusi "terbaik". Solusi "lebih baik" adalah untuk memungkinkan untuk memilih sialan yang tidak memiliki nilai! Apa apaan? Ini tidak seperti ini adalah skenario tepi.
dudewad
@dewewad: semuanya mungkin bekerja lebih baik dengan Angular 1.4. Dari blog AngularJS untuk 1.4.0: "ngOptions telah sepenuhnya di-refactored untuk memungkinkan sejumlah bug yang mengganggu diperbaiki,"
Sander_P
1
Haha "bug yang mengganggu". Baik. Yah saya masih agak skiddish ketika harus melakukan upgrade 3 hari sebelum pengiriman jadi saya akan tetap dengan solusi Anda untuk saat ini, yang tampaknya bekerja dengan baik. Tercatat untuk masa depan, meskipun :) Terima kasih!
dudewad
36

Mungkin bermanfaat bagi seseorang:

Jika Anda ingin menggunakan opsi biasa alih-alih opsi-ng, Anda dapat melakukannya seperti di bawah ini:

<select ng-model="sortorder" ng-init="sortorder='publish_date'">
  <option value="publish_date">Ascending</option>
  <option value="-publish_date">Descending</option>
</select>

Atur model sebaris. Gunakan ng-init untuk menghilangkan opsi kosong

Abraham Jagadeesh
sumber
Saya belum dapat menemukan contoh yang jelas tentang pengaturan opsi-ng dengan OBYEK daripada array JSON dan ketika saya mencoba untuk "menerjemahkan" antara keduanya, tidak hanya tidak keluar dengan benar tetapi gagal "diam-diam" jadi Saya tidak tahu apa yang saya lakukan salah. Saya akhirnya memilih ng-repeat dalam tag opsi. Saya tahu ini bukan praktik terbaik tetapi setidaknya itu BEKERJA. Kalau ada yang bisa mengarahkan saya ke langsung, mudah ditukar pada detail, contoh KERJA ramah-sudut-n00b-ramah menggunakan opsi-ng dengan objek data (BUKAN JSON), saya akan gembira. Gandakan ganda jika menggunakan ng-init juga.
code-sushi
Saya menggunakan opsi sederhana, tetapi di controller saya sepertinya tidak mendapatkan nilai dropdown yang dipilih. Mis: Saya mencoba lansiran ($ scope.sortorder.value); dan alert ($ scope.sortorder); keduanya memberi tidak terdefinisi. Bagaimana cara mendapatkan nilai yang dipilih di sini?
Maverick Riz
Terima kasih banyak atas ini. Saya baru saja akan menulis objek yang sama sekali tidak berguna di controller yang saya tidak perlu saya hanya perlu pilih sederhana .. Terima kasih sekali lagi.
Muhammad bin Yusrat
22

Hal serupa terjadi pada saya juga dan disebabkan oleh peningkatan ke sudut 1,5. ng-inittampaknya sedang diuraikan untuk mengetik dalam versi Angular yang lebih baru. Dalam Angular yang lebih tua ng-init="myModelName=600"akan memetakan ke opsi dengan nilai "600" yaitu <option value="600">First</option>tetapi dalam Angular 1.5 tidak akan menemukan ini karena tampaknya mengharapkan untuk menemukan opsi dengan nilai 600 yaitu <option value=600>First</option>. Angular kemudian akan memasukkan item pertama acak:

<option value="? number:600 ?"></option>

Angular <1.2.x

<select ng-model="myModelName" ng-init="myModelName=600">
  <option value="600">First</option>
  <option value="700">Second</option>
</select>

Sudut> 1.2

<select ng-model="myModelName" ng-init="myModelName='600'">
  <option value="600">First</option>
  <option value="700">Second</option>
</select>
Nabil Boag
sumber
1
Terima kasih! Dalam kasus saya, saya tidak bisa menggunakan ng-init (tidak ada nilai default) jadi saya melemparkan model saya ke sebuah string dan itu berhasil!
Rodrigo Graça
Sangat berguna untuk masalah produksi aplikasi saya. Terima kasih @Nabil Boag
Venki
3
Ini berfungsi, tentu saja, tetapi opsi yang lebih baik adalah menggunakan ng-value="600"di optionbukan value. Ini akan menguraikannya ke angka dan Anda tidak perlu mengkonversi nilai-nilai Anda seperti yang Anda lakukan sekarang :)
Maks
@ Max Saya mencoba banyak jawaban bernilai tinggi tetapi tidak ada yang berhasil sampai saya menemukan jawaban Anda. Terima kasih.
Andrew
21

Di antara banyak jawaban di sini, saya pikir saya akan memposting ulang solusi yang bekerja untuk saya dan memenuhi semua kondisi berikut:

  • menyediakan placeholder / prompt ketika model-ng adalah palsu (mis. "--select region--" w. value="")
  • ketika nilai ng-model falsy dan pengguna membuka opsi dropdown, placeholder yang dipilih (solusi lain yang disebutkan di sini membuat pilihan pertama muncul yang dipilih yang dapat menyesatkan)
  • memungkinkan pengguna untuk membatalkan pilihan nilai yang valid, pada dasarnya memilih nilai falsy / default lagi

masukkan deskripsi gambar di sini

kode

<select name="market_vertical" ng-model="vc.viewData.market_vertical"
    ng-options="opt as (opt | capitalizeFirst) for opt in vc.adminData.regions">

    <option ng-selected="true" value="">select a market vertical</option>
</select>

src

q & a asli - https://stackoverflow.com/a/32880941/1121919

jusopi
sumber
Apakah maksud Anda jika standarnya adalah <option ng-selected="true" value="null">?
jusopi
Maksud saya jika nilai ng-model ditetapkan sebagai nol, pilihan sudut dibuat dan kosong pada pilihan
Flezcano
16

Solusi cepat:

select option:empty { display:none }

Semoga ini bisa membantu seseorang. Idealnya, jawaban yang dipilih harus pendekatan tetapi jika dalam kasus itu tidak mungkin maka harus berfungsi sebagai tambalan.

KK
sumber
2
Per pengujian saya ini hanya akan bekerja di Chrome (Chrome baru, di atas itu) dan Firefox. IE dan Safari istirahat. Tidak tahu tentang opera dan browser tepi lainnya. Bagaimanapun, ini bukanlah solusi yang baik, sayangnya.
dudewad
di mana kita harus meletakkannya di html sebelum penutupan <select> atau yang lain di js
H Varma
1
@Harma Ini adalah aturan CSS. Tempatkan di stylesheet atau di dalam tag <style>
KK
@K stackoverflow.com/questions/48355599/... Bisakah Anda memeriksanya?
Sudarshan Kalebere
14

Ya ng-model akan membuat nilai opsi kosong, ketika properti ng-model tidak ditentukan. Kita bisa menghindari ini, jika kita menetapkan objek ke ng-model

Contoh

pengkodean sudut

$scope.collections = [
    { name: 'Feature', value: 'feature' }, 
    { name: 'Bug', value: 'bug' }, 
    { name: 'Enhancement', value: 'enhancement'}
];

$scope.selectedOption = $scope.collections[0];


<select class='form-control' data-ng-model='selectedOption' data-ng-options='item as item.name for item in collections'></select>

Catatan penting:

Tetapkan objek array seperti $ scope.collections [0] atau $ scope.collections [1] untuk ng-model, jangan gunakan properti objek. jika Anda mendapatkan nilai opsi pilih dari server, menggunakan fungsi panggilan balik, tetapkan objek ke model-ng

CATATAN dari dokumen sudut

Catatan: ngModel membandingkan dengan referensi, bukan nilai. Ini penting saat mengikat ke array objek. lihat contoh http://jsfiddle.net/qWzTb/

Saya telah mencoba berkali-kali akhirnya saya menemukannya.

Kanagaraj Vadivel
sumber
8

Meskipun jawaban @ pkozlowski.opensource dan @ Mark benar, saya ingin membagikan versi yang sedikit dimodifikasi di mana saya selalu memilih item pertama dalam daftar, terlepas dari nilainya:

<select ng-options="option.value as option.name for option in typeOptions" ng-init="form.type=typeOptions[0].value">
</select>
denkan
sumber
4

Saya menggunakan Angular 1.4x dan saya menemukan contoh ini, jadi saya menggunakan ng-init untuk menetapkan nilai awal di pilih:

<select ng-init="foo = foo || items[0]" ng-model="foo" ng-options="item as item.id for item in items"></select>
James Drinkard
sumber
3


Saya menghadapi masalah yang sama. Jika Anda memposting bentuk sudut dengan posting normal maka Anda akan menghadapi masalah ini, karena sudut tidak memungkinkan Anda untuk menetapkan nilai untuk opsi dengan cara yang telah Anda gunakan. Jika Anda mendapatkan nilai "form.type" maka Anda akan menemukan nilai yang tepat. Anda harus memposting objek sudut itu sendiri bukan bentuk posting.

Jitu
sumber
3

Solusi sederhana adalah dengan menetapkan opsi dengan nilai kosong yang ""saya temukan ini menghilangkan opsi tambahan yang tidak ditentukan.

kgrondell
sumber
5
Doenst work @ 1.4.3, Itu hanya menambahkan 2 opsi kosong ke formulir
Denny Mueller
3

Ok, sebenarnya jawabannya adalah sederhana: ketika ada opsi yang tidak dikenali oleh Angular, itu termasuk yang membosankan. Apa yang Anda lakukan salah adalah, ketika Anda menggunakan opsi-ng, itu membaca objek, katakanlah[{ id: 10, name: test }, { id: 11, name: test2 }] right?

Ini adalah apa nilai model Anda perlu untuk mengevaluasinya sebagai sama, katakanlah Anda ingin nilai yang dipilih menjadi 10, Anda perlu mengatur model Anda ke nilai suka { id: 10, name: test }memilih 10, karena itu TIDAK akan membuat sampah itu.

Semoga ini bisa membantu semua orang untuk mengerti, saya kesulitan mencoba :)

Marco
sumber
2

Solusi ini bekerja untuk saya:

<select ng-model="mymodel">    
   <option ng-value="''" style="display:none;" selected>Country</option>
   <option value="US">USA</option>
</select>
MMM
sumber
Downvote bisa jadi karena menerapkan CSS ke elemen opsi tidak berfungsi di semua browser.
Kafoso
Saya baru saja mengujinya di Chrome, FireFox, Safari dan Edge - semuanya berfungsi.
MMM
@MMM "semua browser" termasuk IE. Banyak pengguna masih terjebak dengan IE 10 dan 11, dan itulah sebabnya mengapa downvote terjadi. Chrome, fF, Saf, dan Edge bukan "semua browser".
PKD
1

Ini berhasil untuk saya

<select ng-init="basicProfile.casteId" ng-model="basicProfile.casteId" class="form-control">
     <option value="0">Select Caste....</option>
     <option data-ng-repeat="option in formCastes" value="{{option.id}}">{{option.casteName}}</option>
 </select>
Subramanian Naya
sumber
Sederhananya menambahkan opsi ke dalam daftar dan meninggalkan ruang kosong.
AMontpetit
1

Ini berfungsi dengan baik

<select ng-model="contact.Title" ng-options="co for co in['Mr.','Ms.','Mrs.','Dr.','Prof.']">
    <option style="display:none" value=""></option>
</select>

cara kerjanya adalah, ini memberikan opsi pertama untuk ditampilkan sebelum memilih sesuatu dan display:nonemenghapusnya membentuk dropdown jadi jika Anda mau, Anda bisa melakukannya

<select ng-model="contact.Title" ng-options="co for co in['Mr.','Ms.','Mrs.','Dr.','Prof.']">
    <option style="display:none" value="">select an option...</option>
</select>

dan ini akan memberi Anda select and optionsebelum memilih tetapi setelah dipilih itu akan menghilang, dan itu tidak akan muncul di dropdown.

David Genger
sumber
Sebenarnya Anda tidak menjawab pertanyaan itu sendiri, lebih buruk dari itu, Anda hanya menyembunyikan elemennya.
Marco
0

Coba yang ini di controller Anda, dalam urutan yang sama:

$scope.typeOptions = [
    { name: 'Feature', value: 'feature' }, 
    { name: 'Bug', value: 'bug' }, 
    { name: 'Enhancement', value: 'enhancement' }
];
$scope.form.type = $scope.typeOptions[0];
Macfer Ann
sumber
Saya mencoba metode Anda, tetapi sayangnya saya tidak berhasil. Bisakah Anda melihat biola ini. jsfiddle.net/5PdaX
Aniket Sinha
0

Inilah solusinya:

untuk data sampel seperti:

financeRef.pageCount = [{listCount:10,listName:modelStrings.COMMON_TEN_PAGE},    
{listCount:25,listName:modelStrings.COMMON_TWENTYFIVE_PAGE},
{listCount:50,listName:modelStrings.COMMON_FIFTY_PAGE}];

Pilihan yang dipilih harus seperti ini: -

<select ng-model="financeRef.financeLimit" ng-change="financeRef.updateRecords(1)" 
class="perPageCount" ng-show="financeRef.showTable" ng-init="financeRef.financeLimit=10"
ng-options="value.listCount as value.listName for  value in financeRef.pageCount"
></select>

Intinya adalah ketika kita menulis value.listCountseperti value.listNameitu, secara otomatis mengisi teks value.listNametetapi nilai opsi yang dipilih adalah value.listCountmeskipun nilai-nilai saya menunjukkan normal 0,1,2 .. dan seterusnya !!!

Dalam kasus saya, financeRef.financeLimitsebenarnya meraih value.listCountdan saya dapat melakukan manipulasi saya di controller secara dinamis.

lisapanda
sumber
0

Saya ingin menambahkan bahwa jika nilai awal berasal dari ikatan dari beberapa elemen induk atau komponen 1,5, pastikan bahwa jenis yang tepat dilewatkan. Jika menggunakan @dalam pengikatan, variabel yang dikirimkan akan berupa string dan jika opsinya mis. bilangan bulat maka opsi kosong akan muncul.

Entah mengurai nilai init dengan benar, atau mengikat dengan <dan tidak @(kurang direkomendasikan untuk kinerja kecuali diperlukan).

Wtower
sumber
0

Solusi sederhana

<select ng-model='form.type' required><options>
<option ng-repeat="tp in typeOptions" ng-selected="    
{{form.type==tp.value?true:false}}" value="{{tp.value}}">{{tp.name}}</option>

gajendra kumar
sumber
0

Solusi menggiling dengan jQuery ketika Anda tidak memiliki kendali atas opsi

html:

<select id="selector" ng-select="selector" data-ng-init=init() >
...
</select>

js:

$scope.init = function () {
    jQuery('#selector option:first').remove();
    $scope.selector=jQuery('#selector option:first').val();
}
Pascal KOCH
sumber
Pascal, seseorang menurunkan Anda karena ini adalah solusi jQuery, bukan AngularJs
Mawg mengatakan mengembalikan Monica
Pertanyaannya adalah diminta untuk menggali lebih banyak sudut ...: - /
Sahu V Kumar
0

Jika Anda menggunakan ng-init model Anda untuk menyelesaikan masalah ini:

<select ng-model="foo" ng-app ng-init="foo='2'">
Pauly Garcia
sumber
0

saya punya masalah yang sama, saya (dihapus "ng-model") mengubah ini:

<select ng-model="mapayear" id="mapayear" name="mapayear" style="  display:inline-block !important;  max-width: 20%;" class="form-control">
  <option id="removable" hidden> Selecione u </option>
    <option selected ng-repeat="x in anos" value="{{ x.ano }}">{{ x.ano }}
</option>
</select>

untuk ini:

<select id="mapayear" name="mapayear" style="  display:inline-block !important;  max-width: 20%;" class="form-control">
  <option id="removable" hidden> Selecione u </option>
    <option selected ng-repeat="x in anos" value="{{ x.ano }}">{{ x.ano }}
</option>
</select>

sekarang ini berfungsi, tetapi dalam kasus saya itu karena saya menghapus lingkup itu dari ng.controller, periksa apakah Anda tidak melakukan hal yang sama.

Kuburan Kuza
sumber
0

Satu-satunya hal bekerja untuk saya menggunakan track bydalam ng-options, seperti ini:

 <select class="dropdown" ng-model="selectedUserTable" ng-options="option.Id as option.Name for option in userTables track by option.Id">

Dipendu Paul
sumber
jika saya menggunakan ini ng-optionmendapatkan nilai terakhir array yang saya ingin nilai set optiondari select. Itu tidak menyelesaikan :(
rufatZZ
0

Rujuk contoh dari dokumentasi sudut bagaimana mengatasi masalah ini.

  1. Buka tautan dokumentasi ini di sini
  2. Temukan ' Binding pilih ke nilai non-string melalui ngModel parsing / pemformatan '
  3. Di sana Anda dapat melihat di sana, arahan yang disebut ' convertToNumber ' menyelesaikan masalah.

Ini bekerja untuk saya. Bisa juga melihat cara kerjanya di sini

ihsanberahim
sumber
0

Kita bisa menggunakan CSS untuk menyembunyikan opsi pertama, Tapi itu tidak akan berfungsi di IE 10, 11. Cara terbaik adalah menghapus elemen menggunakan Jquery. Solusi ini berfungsi untuk peramban utama yang diuji dalam chrome dan IE10, 11

Juga jika Anda menggunakan sudut, kadang menggunakan karya setTimeout

$scope.RemoveFirstOptionElement = function (element) {
    setTimeout(function () {
        $(element.children()[0]).remove();
    }, 0);
};
Ashok Kumar
sumber