chore(champs-number): render as text input to validate them when invalid

Les input=number n'ont pas de value lorsque la valeur saisie n'est pas un
nombre. Par conséquent dans ces cas là, nous ne pouvions faire remonter
au backend pour validation / enregistrement, et il n'y avait aucun
feedback signalement l'erreur à l'usager.

On les convertit en inputs texte, avec les adaptations nécessaires
pour montrer le pavé numérique sur mobile, et un style correct.
This commit is contained in:
Colin Darie 2023-09-25 11:39:08 +02:00
parent a559bf54eb
commit aac7de208f
No known key found for this signature in database
GPG key ID: 8C76CADD40253590
6 changed files with 27 additions and 4 deletions

View file

@ -296,6 +296,8 @@
input[type=email], input[type=email],
input[type=password], input[type=password],
input[type=number], input[type=number],
input[inputmode=numeric],
input[inputmode=decimal],
input[type=tel] { input[type=tel] {
max-width: 500px; max-width: 500px;
} }
@ -315,6 +317,8 @@
&[type='date'], &[type='date'],
&[type='tel'], &[type='tel'],
&[type='number'], &[type='number'],
&[inputmode='numeric'],
&[inputmode='decimal'],
&[type='datetime-local'] { &[type='datetime-local'] {
width: 33.33%; width: 33.33%;
} }

View file

@ -1 +1 @@
= @form.number_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, step: :any, required: @champ.required?)) = @form.text_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, required: @champ.required?, pattern: "-?[0-9]+([\.,][0-9]{1,3})?", inputmode: :decimal))

View file

@ -1 +1 @@
= @form.number_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, placeholder: 5, required: @champ.required?)) = @form.text_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, pattern: "[0-9]*", inputmode: :numeric, required: @champ.required?))

View file

@ -1 +1 @@
= @form.number_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, placeholder: @champ.libelle, required: @champ.required?)) = @form.text_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, placeholder: @champ.libelle, required: @champ.required?, pattern: "[0-9]*", inputmode: :decimal))

View file

@ -205,6 +205,8 @@ export class AutosaveController extends ApplicationController {
formData.append(input.name, input.value); formData.append(input.name, input.value);
} }
} else { } else {
// NOTE: some type inputs (like number) have an empty input.value
// when the filled value is invalid (not a number) so we avoid them
formData.append(input.name, input.value); formData.append(input.name, input.value);
} }
} }

View file

@ -144,7 +144,11 @@ describe 'The user' do
end.to change { Champ.count } end.to change { Champ.count }
end end
let(:simple_procedure) { create(:procedure, :published, :for_individual, types_de_champ_public: [{ mandatory: true, libelle: 'texte obligatoire' }, { mandatory: false, libelle: 'texte optionnel' }]) } let(:simple_procedure) {
create(:procedure, :published, :for_individual, types_de_champ_public: [
{ mandatory: true, libelle: 'texte obligatoire' }, { mandatory: false, libelle: 'texte optionnel' }, { mandatory: false, libelle: "nombre", type: :integer_number }
])
}
scenario 'save an incomplete dossier as draft but cannot not submit it', js: true, retry: 3 do scenario 'save an incomplete dossier as draft but cannot not submit it', js: true, retry: 3 do
log_in(user, simple_procedure) log_in(user, simple_procedure)
@ -170,6 +174,19 @@ describe 'The user' do
expect(page).to have_current_path(merci_dossier_path(user_dossier)) expect(page).to have_current_path(merci_dossier_path(user_dossier))
end end
scenario 'validates invalid number', js: true, retry: 3 do
log_in(user, simple_procedure)
fill_individual
# Check an incomplete dossier can be saved as a draft, even when mandatory fields are missing
fill_in('nombre', with: 'environ 300')
wait_for_autosave
within ".fr-message--error" do
expect(page).to have_content("doit être un nombre entier")
end
end
scenario 'extends dossier experation date more than one time, ', js: true, retry: 3 do scenario 'extends dossier experation date more than one time, ', js: true, retry: 3 do
simple_procedure.update(procedure_expires_when_termine_enabled: true) simple_procedure.update(procedure_expires_when_termine_enabled: true)
user_old_dossier = create(:dossier, user_old_dossier = create(:dossier,