Boostrap 5, is-valid and empty field howto? - bootstrap-5

From the documentation (it's what I've understood): when a form is posted to our server, we check it, if it's not valid, me return it. In such case, we must add class="was-validated" to the form, and we me must precise for all fields, whether it's good (add class is-valid) or not (add class is-invalid).
In our case, we do accept empty fields as valid. So we return some fields with class is-valid and because the fields are empty, bootstrap still shows the red outline, not the green, like this:
The form code is :
<form action="" method="post"
class="was-validated" novalidate>
<div class="row mb-3">
<label for="id_content2" class="col-sm-2 col-form-label">Content2</label>
<div class="col-sm-10">
<input type="text" name="content2" class="form-control is-valid"
required id="id_content2" aria-describedby="content2" />
<div class="valid-feedback"> Valid </div>
</div>
</div>
</form>
What am I doing wrong? What is the solution to consider some empty fields as valid?

It seems like that the "is-valid" is being added when the form is returned to the user but the field is empty. That would explain the behaviour at least...
One solution to consider an empty field as valid is to remove the "required" attribute from the input field and check if the field is empty on the server side before processing the form.

Related

How to validate Form only on submit in Angular Dart?

I am using the Angular Component library which includes material-input. Is there a way to disable input auto validate when changing or emptying the material-input? Meaning that I want to only validate the form upon submit.
Plus the onSignInPressed() function is not getting triggered on submit despite that the material-button is of type submit.
<div class="container">
<form (ngSubmit)="onSignInPressed()" #signInForm="ngForm">
<div>
<material-input
floatingLabel type="email"
label="E-mail"
[(ngModel)]="email"
ngControl="email"
required></material-input>
</div>
<div>
<material-input
floatingLabel type="password"
label="Password"
[(ngModel)]="password"
ngControl="pass"
required></material-input>
</div>
<div class="w-100">
<material-button class="mx-0 btn-primary w-100 margin-zero" type="submit"
[disabled]="!signInForm.form.valid">
Sign In
</material-button>
</div>
</form>
</div>
You can try to use a different value accessor on the material-input, however you won't be able to validate the form on submit.
With changeUpdate, validation will be triggered on blur or when press ENTER
<material-input changeUpdate [(ngModel)]="value"
Docs
About the material-button, there is an issue on github with a hacky solution.
You can also try to add an hidden input
<input type="submit" hidden />

SimpleForm 3 initializer for Bootstrap4 beta

The current Bootstrap 4 beta adds error class attributes directly to the input tag like this:
<div class="col-md-6 mb-3">
<label for="validationServer03">City</label>
<input type="text" class="form-control is-invalid" id="validationServer03" placeholder="City" required>
<div class="invalid-feedback">
Please provide a valid city.
</div>
</div>
SimpleForm however, adds the class to the field wrapper. Is there any way to change the initializer so it adds an error class to the input field instead of the field wrapper?

Why does ASP.NET Core Tag Helper for Boolean Checkbox Not Display Label?

I'm looking at the login.cshtml page of a new asp.net core account view page and I notice that the use DisplayNameFor to output the name of the field ("RememberMe"). Why is the not sufficent for this? It seems the label is not participating.
<div class="checkbox">
<label asp-for="RememberMe">
<input asp-for="RememberMe" />
#Html.DisplayNameFor(m => m.RememberMe)
</label>
</div>
Since input and label are both Tag Helpers, shouldn't the name be rendered automatically like for email and other input tags on same page?
Very interesting question.
Per MVC code, the labeltaghelper gives precedence to available child content. Only when no child content is available will it put in a default label text (order and possible values per)
If you remove all child elements of the label you will notice that the label will in fact use the display name or property name (Remember Me)
Personally, I think in the template, it's just a design decision to use #Html.DisplayNameFor(m => m.RememberMe)so that it goes well with bootstrap.
Update: This would show the same information but the formatting is not going to be as good
<div class="checkbox">
<input asp-for="RememberMe" />
<label asp-for="RememberMe">
</label>
</div>

Textbox missing when no data in model

I have an input that will display data in model. There supposed to be 2 ways to access this form. Either by entering ID no at the form before, so
the name displayed here, or without entering ID no, which means it is only a blank textbox. I successully retrieved the value from model where the
value is displayed inside the textbox. The problem is when the form is access without model. Textbox are not shown. It only displayed the label.
I am not sure why but i think it is maybe because the input value are assign to model. All i need is a textbox so user can input the data.
<div Class="form-group">
<Label Class="control-label col-md-4">Appointment Start</Label>
<div Class="col-sm-8">
#For Each Item In Model
#<input type="text" name="name" Class="form-control" value="#Html.DisplayFor(Function(modelItem) Item.name)">
Next
</div>
</div>

Handling form with repeatable inputs

Before i start with my question, i will try to explain on what i'm trying to do.
I'm creating a form using Grails, and in the form, there are 2 sections on it, the primary input and the repeatable input. See below for ideas on how the structure looks like.
<div class="primary">
<div class="${hasErrors(bean: dataInputInstance, field: 'mainInput', 'error')}">
<label class="control-label">
<g:message code="dataInput.mainInput.label" default="Main Input"/>
</label>
<div class="controls">
<g:textField name="mainInput" value="${dataInputInstance?.mainInput}" />
</div>
</div>
</div>
<div class="repeatable">
<div class="span6">
<div class="${hasErrors(bean: dataInputInstance, field: 'inputA', 'error')}">
<label class="control-label">
<g:message code="dataInput.InputA.label" default="Input A"/>
</label>
<div class="controls">
<g:textField id='inputA_1' name="inputA" value="${dataInputInstance?.inputA}" />
</div>
</div>
</div>
<div class="span6">
<div class="${hasErrors(bean: dataInputInstance, field: 'inputB', 'error')}">
<label class="control-label">
<g:message code="dataInput.InputB.label" default="Input B"/>
</label>
<div class="controls">
<g:textField id='inputB_1' name="inputB" value="${dataInputInstance?.inputB}" />
</div>
</div>
</div>
The repeatable part of the input can be repeated from 1-50 times. The number of instances generated and saved in the database depends on how many repeated form created. Each instance is a combination of primary input + repeated input.
If say, i created 5 repeated sections, then when saving the form, the params will look like below
params:[mainInput: valMain, inputA:[valA1, valA2, valA3, valA4, valA5], inputB :[valB1, valB2, valB3, valB4, valB5]]
In the controller, i used the following when i try to form the instances and save it to the database
def save() {
def length = inputA.size()
def i
if (i = 0; i < length; i++){
DataInput dataInputInstance = new DataInput()
dataInputInstance.mainInput = params.mainInput.trim()
dataInputInstance.inputA = params.inputA[i].trim()
dataInputInstance.inputB = params.inputB[i].trim()
dataInputInstance.save(flush:true)
}
}
So far i managed to get that part correct.
Now here comes the problem.
Inside the save controller, i plan to include some data checking before i save it to the database. If checking is success, then it will proceed to save the data. If its not, then it will return back to the form page, together with the data that user input in the form. The code for that is as follow
if (insert checking condition here){
render(view: "create", model: [dataInputInstance: dataInputInstance]) //If fail
}
If the amount of repeatable part is 1, then the form will render along with the data that the user input. However if the repeatable part is more than 1, then it will have trouble to pass the data back to the form.
I tried to pass back the params back to the form because i thought since the params contain arrays on it, so it would be logical to pass back the params to the form, like below
if (insert checking condition here){
render(view: "create", model: [dataInputInstance: params]) //If fail
}
But still not working.
So anyone have any idea on this?
I'm looking at this block where you are setting dataInputInstance.inputA to be a single value and not the entire list object. Is this what you intended?
dataInputInstance.inputA = params.inputA[i].trim()
dataInputInstance.inputB = params.inputB[i].trim()
Could you post your view GSP code if this is not the cause? Need to see how are you reading the values from your view on validation failure.

Resources