Cara menangani float dan pemisah desimal dengan nomor tipe input html5

128

Saya sedang membangun aplikasi web yang terutama untuk browser seluler. Saya menggunakan bidang input dengan tipe angka, jadi (kebanyakan) browser seluler hanya memanggil papan tombol angka untuk pengalaman pengguna yang lebih baik. Aplikasi web ini terutama digunakan di daerah di mana pemisah desimal koma, bukan titik, jadi saya perlu menangani kedua pemisah desimal.

Bagaimana cara menutupi seluruh kekacauan ini dengan titik dan koma?

Temuan saya:

Chrome Desktop

  • Jenis input = angka
  • Pengguna memasukkan "4,55" ke kolom input
  • $("#my_input").val(); mengembalikan "455"
  • Saya tidak bisa mendapatkan nilai yang benar dari input

Firefox Desktop

  • Jenis input = angka
  • Pengguna memasukkan "4,55" ke kolom input
  • $("#my_input").val(); mengembalikan "4,55"
  • Baiklah, saya bisa mengganti koma dengan titik dan mendapatkan float yang benar

Browser Android

  • Jenis input = angka
  • Pengguna memasukkan "4,55" ke kolom input
  • Ketika input kehilangan fokus, nilai terpotong menjadi "4"
  • Membingungkan bagi pengguna

Windows Phone 8

  • Jenis input = angka
  • Pengguna memasukkan "4,55" ke kolom input
  • $("#my_input").val(); mengembalikan "4,55"
  • Baiklah, saya bisa mengganti koma dengan titik dan mendapatkan float yang benar

Apa "praktik terbaik" dalam situasi seperti ini ketika pengguna dapat menggunakan koma atau titik sebagai pemisah desimal dan saya ingin mempertahankan tipe input html sebagai angka, untuk memberikan pengalaman pengguna yang lebih baik?

Dapatkah saya mengonversi koma ke titik "on the fly", mengikat acara utama, apakah itu berfungsi dengan input angka?

EDIT

Currenlty Saya tidak punya solusi, bagaimana mendapatkan nilai float (sebagai string atau angka) dari input yang jenisnya diatur ke angka. Jika pengguna akhir memasukkan "4,55", Chrome selalu kembali "455", Firefox mengembalikan "4,55" yang baik-baik saja.

Juga cukup menjengkelkan bahwa di Android (diuji emulator 4.2), ketika saya memasukkan "4,55" ke kolom input dan mengubah fokus ke tempat lain, nomor yang dimasukkan terpotong menjadi "4".

devha
sumber
Dugaan saya adalah penyebab utama dari beberapa masalah Anda adalah bahwa browser disetel ke lokal AS yang menggunakan titik sebagai pemisah desimal. Sepertinya Chrome dan Android semakin bingung dengan hal ini dengan cara yang berbeda - Chrome memperlakukan koma sebagai pemisah digit, lalu mengonversi input menjadi angka, lalu mengonversinya menjadi string lagi .val(), dan Android melakukan sesuatu yang aneh. Bisakah Anda memeriksa apakah mereka berperilaku sama ketika Anda mengatur bahasa sistem ke sesuatu yang sesuai?
milimoose
1
Nvm memposting ini sebagai jawaban
kjetilh
Lihat juga di sini: stackoverflow.com/a/24423879/196210
Revious
Situasinya bahkan lebih buruk daripada yang Anda gambarkan: Anda mendapatkan titik desimal atau koma pada WP numpad tergantung pada bahasa yang Anda pilih untuk digunakan keyboard Anda. Juga tidak ada cara untuk mengetahui yang merupakan input lokal (tidak harus bahasa browser yang disukai) ... Jadi yang terbaik yang bisa saya dapatkan (dan apa yang cukup baik bagi saya) adalah: var number = $(...).get(0).valueAsNumber; if (isNaN(number)) number = parseFloat($(...).val().replace(',', '.'); Tapi solusi itu hanya berfungsi jika nomor yang dimasukkan hanya berisi 1 koma dan tidak ada titik tambahan ...
bert bruynooghe

Jawaban:

107

Saya pikir apa yang hilang dalam jawaban di atas adalah kebutuhan untuk menentukan nilai yang berbeda untuk stepatribut, yang memiliki nilai default 1. Jika Anda ingin algoritma validasi input memungkinkan nilai floating-point, tentukan langkah yang sesuai.

Misalnya, saya ingin jumlah dolar, jadi saya menetapkan langkah seperti ini:

 <input type="number" name="price"
           pattern="[0-9]+([\.,][0-9]+)?" step="0.01"
            title="This should be a number with up to 2 decimal places.">

Tidak ada yang salah dengan menggunakan jQuery untuk mengambil nilainya, tetapi Anda akan merasa berguna untuk menggunakan API DOM secara langsung untuk mendapatkan validity.validproperti elemen .

Saya memiliki masalah yang sama dengan titik desimal, tetapi alasan saya menyadari ada masalah adalah karena gaya yang ditambahkan Twitter Bootstrap ke input angka dengan nilai yang tidak valid.

Berikut biola yang menunjukkan bahwa penambahan stepatribut membuatnya berfungsi, dan juga menguji apakah nilai saat ini valid:

TL; DR: Setel stepatribut ke nilai titik-mengambang, karena itu default ke 1.

CATATAN : Koma tidak memvalidasi untuk saya, tetapi saya menduga bahwa jika saya mengatur pengaturan bahasa / wilayah OS saya ke suatu tempat yang menggunakan koma sebagai pemisah desimal, itu akan berfungsi. * note in note *: itu tidak terjadi untuk pengaturan bahasa OS / keyboard * Jerman * di Ubuntu / Gnome 14.04.

natchiketa
sumber
8
Jika Anda ingin mengizinkan banyak tempat desimal, tentukan stepatributnya "any"alih-alih misalnya "0.01"seperti yang ditunjukkan di sini. Lihat demo biola nathciketa versi tweak ini .
Mark Amery
4
Saya juga mengalami masalah dengan koma yang tidak divalidasi, meskipun saya memasukkan "1.234.56" ke dalamnya <input type="number" step="any">. Saya belum dapat menemukan cara untuk mematikan validasi HTML5. Saya dapat mematikan atau menyesuaikan pesan kesalahan, tetapi mengambil nilai dari input selalu merupakan omong kosong. Ada ide?
Nick G.
5
This attribute applies when the value of the type attribute is text, search, tel, url, email, or password, otherwise it is ignored.Jadi pola tidak berguna dengantype="number"
Michael Laffargue
seperti kata michael, tolong ubah typeke text, jika tidak jawaban Anda tidak masuk akal.
phil294
23

Menurut w3.org, atribut nilai dari input angka didefinisikan sebagai angka floating-point . Sintaks angka floating-point tampaknya hanya menerima titik sebagai pemisah desimal.

Saya telah mendaftarkan beberapa opsi di bawah ini yang mungkin bermanfaat bagi Anda:

1. Menggunakan atribut pola

Dengan atribut pattern, Anda dapat menentukan format yang diizinkan dengan ekspresi reguler dengan cara yang kompatibel dengan HTML5. Di sini Anda dapat menentukan bahwa karakter koma diizinkan dan pesan umpan balik yang bermanfaat jika polanya gagal.

<input type="number" pattern="[0-9]+([,\.][0-9]+)?" name="my-num"
           title="The number input must start with a number and use either comma or a dot as a decimal character."/>

Catatan: Dukungan lintas-browser sangat bervariasi. Mungkin lengkap, sebagian atau tidak ada ..

2. Validasi JavaScript

Anda dapat mencoba untuk mengikat panggilan balik sederhana untuk misalnya acara onchange (dan / atau blur ) yang akan menggantikan koma atau memvalidasi semua bersama-sama.

3. Nonaktifkan validasi browser ##

Ketiga, Anda bisa mencoba menggunakan atribut formnovalidate pada input angka dengan maksud menonaktifkan validasi browser untuk bidang itu secara bersamaan.

<input type="number" formnovalidate />

4. Kombinasi ..?

<input type="number" pattern="[0-9]+([,\.][0-9]+)?" 
           name="my-num" formnovalidate
           title="The number input must start with a number and use either comma or a dot as a decimal character."/>
kjetilh
sumber
2
input.valueAsNumber - Tidak membantu karena ini hanya berfungsi dengan titik-titik sebagai pemisah desimal dan dalam kasus saya, pengguna akhir mungkin menggunakan titik atau koma. Tag formulir novalidate - Belum menemukan pengaruh pada ini.
devha
Sayangnya saya kehabisan ide, jadi saya tidak yakin apakah Anda dapat membuat peramban ini berfungsi tanpa solusi penyelesaian. Saya telah memperbarui jawaban saya untuk memasukkan atribut pola. Saya juga menemukan bahwa seseorang dapat menggunakan atribut formnovalidate langsung pada bidang input. Saya tahu Anda tidak akan menyukainya tetapi jika semuanya gagal dan Anda benar-benar membutuhkan koma maka masukan = "teks" mungkin satu-satunya cara ..
kjetilh
Sepertinya nomor jenis input menghasilkan lebih banyak masalah daripada yang sebenarnya meningkatkan pengalaman pengguna. Di perangkat seluler, akan lebih bagus jika saya bisa membuka hanya keyboard angka untuk pengguna jika saya ingin mereka memasukkan angka saja. Pokoknya saya perlu memikirkan kembali ini sekali lagi ...
devha
Karena kami juga perlu mendukung penggunaan titik dan koma sebagai pemisah desimal, kami berencana menggunakan pola untuk validasi di desktop dalam kombinasi dengan type = "text". Kemudian kami akan menambahkan deteksi fitur untuk mendeteksi perangkat seluler dan menggunakan type = "number" ketika itu berlaku.
awe
9

Apakah menggunakan koma atau titik untuk pemisah desimal sepenuhnya tergantung pada browser. Peramban membuat keputusan berdasarkan lokasi sistem operasi atau peramban, atau beberapa peramban mengambil petunjuk dari situs web. Saya membuat bagan perbandingan browser menunjukkan bagaimana dukungan browser yang berbeda menangani metode pelokalan yang berbeda. Safari menjadi satu-satunya browser yang menangani koma dan titik secara bergantian.

Pada dasarnya, Anda sebagai penulis web tidak dapat benar-benar mengendalikan ini. Beberapa solusi melibatkan penggunaan dua bidang input dengan bilangan bulat. Ini memungkinkan setiap pengguna untuk memasukkan data seperti yang Anda harapkan. Ini tidak terlalu seksi, tetapi itu akan bekerja di setiap kasus untuk semua pengguna.

Aeyoun
sumber
7

Gunakan valueAsNumbersebagai ganti .val().

memasukkan . valueAsNumber [= nilai]

Mengembalikan angka yang mewakili nilai kontrol formulir, jika berlaku; jika tidak, mengembalikan nol.
Dapat diatur, untuk mengubah nilai.
Melemparkan pengecualian INVALID_STATE_ERR jika kontrolnya tidak berbasis tanggal atau waktu atau numerik.

Mike Samuel
sumber
2
Masalahnya adalah dia ingin mendukung koma sebagai pemisah desimal, dan menggunakan type = "number" pada input selalu memberikan angka yang tidak valid ketika menulis koma.
awe
Tampaknya tidak bekerja secara konsisten di Windows Phone; selalu kembali NaN.
bert bruynooghe
@bertbruynooghe, Apa yang Anda tetapkan sebagai nilainya?
Mike Samuel
Tampaknya tidak berfungsi, baik dengan '9', '9,1', '9,1'. Telepon dikonfigurasikan sebagai AS, tata letak keyboard diuji dalam AS, nl-BE.
bert bruynooghe
4

menggunakan jenis teks tetapi memaksa tampilan keyboard numerik

<input value="12,4" type="text" inputmode="numeric" pattern="[-+]?[0-9]*[.,]?[0-9]+">

tag inputmode adalah solusinya

David Navarro
sumber
Tetapi itu tidak kompatibel dengan semua browser, hanya dengan versi terbaru dari iOS Safari, Chrome, Chromium, Opera ... caniuse.com/#feat=input-inputmode :(
pgarciacamou
Dan juga Anda tidak mendapatkan papan tombol angka rapi ini di perangkat seluler.
WoIIe
3

Saya belum menemukan solusi sempurna tetapi yang terbaik yang bisa saya lakukan adalah menggunakan type = "tel" dan menonaktifkan validasi HTML5 (formnovalidate):

<input name="txtTest" type="tel" value="1,200.00" formnovalidate="formnovalidate" />

Jika pengguna memasukkan koma, ia akan menampilkan koma di setiap browser modern yang saya coba (FF terbaru, IE, edge, opera, chrome, safari desktop, android chrome).

Masalah utamanya adalah:

  • Pengguna seluler akan melihat papan ketik ponsel mereka yang mungkin berbeda dengan papan tombol angka.
  • Lebih buruk lagi, keyboard ponsel mungkin tidak memiliki kunci untuk koma.

Untuk kasus penggunaan saya, saya hanya perlu:

  • Tampilkan nilai awal dengan koma (strip firefox untuk tipe = angka)
  • Tidak gagal validasi HTML5 (jika ada koma)
  • Biarkan bidang membaca persis sebagai input (dengan kemungkinan koma)

Jika Anda memiliki persyaratan serupa, ini harusnya cocok untuk Anda.

Catatan: Saya tidak suka dukungan atribut pola. Formnovalidate tampaknya bekerja lebih baik.

Bolo
sumber
1

Ketika Anda memanggilnya $("#my_input").val();kembali sebagai variabel string. Jadi gunakan parseFloatdan parseIntuntuk konversi. Saat Anda menggunakan parseFloatdesktop atau ponsel, ITSELF memahami arti variabel.

Dan ditambah Anda dapat mengkonversi float ke string dengan menggunakan toFixedargumen yang memiliki jumlah digit seperti di bawah ini:

var i = 0.011;
var ss = i.toFixed(2); //It returns 0.01

sumber
Tidak bekerja. Coba parseFloat ("1,5") di IE11. Pengembalian 1. Bahasa adalah bahasa Jerman untuk OS dan IE.
T3rm1
1

Browser tampaknya masih memiliki masalah (meskipun Chrome dan Firefox Nightly baik-baik saja). Saya memiliki pendekatan hacky untuk orang-orang yang benar-benar harus menggunakan bidang angka (mungkin karena panah kecil yang tidak dimiliki bidang teks).

Solusi saya

Saya menambahkan keyupevent Handler ke form input dan melacak status dan mengatur nilainya begitu valid lagi.

Cuplikan JS Murni JSFIDDLE

Cuplikan 9 Sudut

Joniras
sumber
0

Rekomendasi saya? Jangan gunakan jQuery sama sekali. Saya memiliki masalah yang sama seperti Anda. Saya menemukan bahwa $('#my_input').val()selalu mengembalikan beberapa hasil yang aneh.

Coba gunakan document.getElementById('my_input').valueAsNumberalih-alih $("#my_input").val();lalu, gunakanNumber(your_value_retrieved) untuk mencoba membuat Angka. Jika nilainya NaN, Anda tentu tahu bahwa itu bukan angka.

Satu hal yang ditambahkan adalah ketika Anda menulis angka pada input, input sebenarnya akan menerima hampir semua karakter (saya dapat menulis tanda euro, dolar, dan semua karakter khusus lainnya), jadi yang terbaik adalah mengambil nilai menggunakan .valueAsNumberalih-alih menggunakan jQuery.

Oh, dan BTW, yang memungkinkan pengguna Anda untuk menambahkan internasionalisasi (yaitu: mendukung koma alih-alih titik untuk membuat angka desimal). Biarkan saja Number()objek untuk membuat sesuatu untuk Anda dan itu akan menjadi desimal-aman, sehingga untuk berbicara.

Patrick D'appollonio
sumber
Masalahnya bukan disebabkan oleh jQuery, dan saya temukan valueAsNumberjuga tidak bekerja secara konsisten di sepanjang browser.
bert bruynooghe
0

Kedengarannya Anda ingin menggunakan toLocaleString () pada input numerik Anda.

Lihat https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString untuk penggunaannya.

Pelokalan angka dalam JS juga tercakup dalam Internasionalisasi (Pemformatan angka "num.toLocaleString ()") tidak berfungsi untuk chrome

stackasec
sumber
2
Biasanya memberikan lebih banyak penjelasan tentang solusi meskipun jawabannya jika sepenuhnya dicakup oleh konten yang ditautkan.
IvanH
Pendekatan ini tampaknya lebih baik daripada pendekatan lain jika server back end menentukan lokal daripada browser itu sendiri. Sayangnya, toLocaleStringtidak dapat diandalkan di seluruh platform.
bert bruynooghe
Dukungan lintas platform nampaknya cukup luas bagi saya pada tahun 2015, lihat mis. Mozillas Devnet . Namun, jika itu masih menjadi perhatian Anda, temukan kemungkinan solusinya di sini.
stackasec
Mozillas Devnet menunjukkan hampir tidak ada kompatiblilty untuk browser seluler, dan di situlah bidang teks numerik dapat menawarkan sebagian besar manfaat. (Lihat pertanyaan asli.)
bert bruynooghe
... dan lebih dari cukup alternatif telah ditunjukkan dan dirujuk. Selamat bersenang-senang.
stackasec