Tab index for dynamically added elements - html

I have a jsp page with three text boxes and a ADD button beside it. Now I have to set the tabindex for the dynamically added elements. How can I do it?

[As you may have figured out by now, posting code allows someone else to give a more definite answer. Without an example to work from, I can only imagine what your code and environment is...from ASP.NET MVC3 + jQuery]
[I used the information from this stackoverflow post and modified a lit bit.]
I use jQuery to modify the tabindex value. I have multiple forms that are dynamically added by jQuery. The forms use div and style="display: table" to organize the text fields into columns.
[The relevant CSS styles]
.tb-table
{
display: table;
}
.tb-row
{
display: table-row;
}
.tb-cell
{
display: table-cell;
}
[A chunk of my ASP.NET MVC3 Razor cshtml that produces html for the browser--should be readable]
<div class="tb-table">
<div id="namerow1" class="tb-row">
<div class="tb-label tb-cell" id="l_firstname1">
#Html.LabelFor(model => model.firstname1)
</div>
<div class="tb-field tb-cell" id="firstname1">
#Html.TextBoxFor(model => model.firstname1, new { tabindex = "1" })
#Html.ValidationMessageFor(model => model.firstname1)
</div>
<div class="tb-label tb-cell" id="l_firstname2">
#Html.LabelFor(model => model.firstname2)
</div>
<div class="tb-field tb-cell" id="firstname2">
#Html.TextBoxFor(model => model.firstname2, new { tabindex = "2" })
#Html.ValidationMessageFor(model => model.firstname2)
</div>
</div>
<div id="namerow2" class="tb-row">
<div class="tb-label tb-cell">
#Html.LabelFor(model => model.lastname1)
</div>
<div class="tb-field tb-cell">
#Html.TextBoxFor(model => model.lastname1, new { tabindex = "1" })
#Html.ValidationMessageFor(model => model.lastname1)
</div>
<div class="tb-label tb-cell">
#Html.LabelFor(model => model.lastname2)
</div>
<div class="tb-field tb-cell">
#Html.TextBoxFor(model => model.lastname2, new { tabindex = "2" })
#Html.ValidationMessageFor(model => model.lastname2)
</div>
</div>
</div>
I use tabindex for all values in a column; not just a unique order. For the browsers I tested in, when there are multiple text fields with the same tabindex, the text field encountered first in the html code will be selected first by tab-navigation.
Therefore, for each form that I have, I use a tab value from 0-9 to group them. Once I have the tab order for an individual form working the way I want, I use the following jQuery to INCREMENT the tabindex value by 10 (or 20, or 30, or 40) for each form that I dynamically add. the first decimal, 0-9, organizes the tabs within that form, and incrementing the factors of 10 keeps the subsequent form tabs following along.
$('.createtab-form [tabindex]').each(function () {$(this).attr('tabindex', parseInt($(this).attr('tabindex'))+10)})
This is my first attempt at this myself--I'm sure someone else will have a better method. Let me know what you think.

Related

Bootstrap 5 - Floating Labels with Razor syntax

Hopefully this is an easy one...
I am having an issue with Bootstrap 5 floating labels not working when I create HTML elements using Razor syntax.
If I use plain HTML they work as expected. Using razor the labels are appearing in the state you'd expect if the text box has focus (top left of input)
<div class="form-floating mb-3">
#Html.EditorFor(model => model.Recipient, new { htmlAttributes = new { #class = "form-control", #onchange = "javascript: Changed( this, 'recipient-name' );" } })
#Html.ValidationMessageFor(model => model.Recipient, "", new { #class = "text-danger" })
#Html.LabelFor(model => model.Recipient)
</div>
Here is an image of the above on load -
Code output in UI
Has anyone had this issue, know a way to get around it or spot what I am doing wrong? (I need the input tag to be populated from the model as the form can be used to create a new request or update and existing request)
Thanks
Do you want something like below?
<div class="form-floating">
<input asp-for="Recipient" class="form-control" />
<label asp-for="Recipient"></label>
<span asp-validation-for="Recipient" class="text-danger"></span>
</div>
Thanks but I figured out what I was doing wrong. The issue was simple...
ISSUE - There was no placeholder tag which this animation relies on.
RESOLUTION - Add #placeholder = "Recipient Name"
To provide a bit more info the text input looks different when in focus/not focused. This was the issue.
It should have looked like this when not focused - Not Focused
But it was looking like this - Focused
The code that fixed the issue is
<div class="form-floating mb-3">
#Html.EditorFor(model => model.Recipient, new { htmlAttributes = new { #class = "form-control", #onchange = "javascript: Changed( this, 'recipient-name' );", #placeholder = "Recipient Name" } })
#Html.ValidationMessageFor(model => model.Recipient, "", new { #class = "text-danger" })
#Html.LabelFor(model => model.Recipient)
</div>

How did my ViewBag become populated with data?

I'm working with a Kendo Grid that shows a modal when editing or adding a row. I'm seeking to modify the modal and add another dropdown list to it. The one thing I'm totally confused about at the moment is that the cshtml for the modal refers to the ViewBag to provide the source data for the dropdownlists, but I can't find anywhere in the entire solution where any code (anywhere) populates the ViewBag with the properties the modal uses.
Before I started modifying, the cshtml had:
#Html.Kendo().DropDownListFor(model => model.Status).BindTo(ViewBag.Statuses).DataTextField("Name").DataValueField("Value").OptionLabel("Please Select")
^^^^^^^^^^^^^^^^
The debugger says this is valid; the ViewBag does contain a .Statuses and it is loaded with data, but I've no idea how this thing came to be in the ViewBag. The only place the controller refers to the viewbag is in setting the .Title
Here's cshtml for the modal:
#model ModalModel
#Html.HiddenFor(model => model.Id)
<!-- this is the new one -->
<div class="editor-group">
<div class="editor-label">
#Html.LabelFor(model => model.ProjectId)
</div>
<div class="editor-field">
#Html.Kendo().DropDownListFor(model => model.ProjectId).BindTo(ViewBag.ProjectId_Data).OptionLabel("Please Select")
#Html.ValidationMessageFor(model => model.ProjectId)
</div>
</div>
<!-- existing one. Needs DataTextField and DataValueField because model.Statuses is not an IEnumerable<SelectListItem>, its a custom collection of c# enum name/value representation -->
<div class="editor-group">
<div class="editor-field">
#Html.Kendo().DropDownListFor(model => model.Status).BindTo(ViewBag.Statuses).DataTextField("Name").DataValueField("Value").OptionLabel("Please Select")
#Html.ValidationMessageFor(model => model.Status)
</div>
</div>
Here's a snip of the cshtml for the main grid and some periphery stuff:
#model GridModel
<h3>#ViewBag.Title</h3>
#{
var projectListItems = Model.Projects.Select(e => new SelectListItem { Value = e.Id.ToString(), Text = e.Name });
var activityListItems = Model.Activities.Select(e => new SelectListItem { Value = e.Id.ToString(), Text = e.PrivateName });
}
#(Html.Kendo().Grid<UsageModel>()
.Name("MainGrid")
.Columns(cfg =>
{
cfg.Bound(e => e.DateUsed).ClientTemplate("#= kendo.toString(DateUsed, \"d\") #");
cfg.ForeignKey(e => e.ProjectId, projectListItems, "Value", "Text").Title("Project name").Width(150);
cfg.ForeignKey(e => e.ActivityId, activityListItems, "Value", "Text").Title("Activity name").Width(150);
cfg.ForeignKey(e => e.Status, Model.Statuses, "Value", "Name");
cfg.Command(cmd => { cmd.Edit(); cmd.Destroy().HtmlAttributes(new { style = "visibility:hidden" }); }).Width(80);
})
.Pageable()
...
The 4 items in the ViewBag are:
ProjectId_Data (IEnumerable<SelectListItem>)
ActivityId_Data (IEnumerable<SelectListItem>)
Status_Data (IEnumerable<SelectListItem>)
Statuses (IEnumerable<a custom internal type used for expanding enums into name/value strings>)
Am I correct in assuming that Kendo added these things to the viewbag as part of the data binding process on the main grid? The rendering of the grid to page occurs before the processing of the modal..
Please give (IEnumerable) inside BindTo() for casting and try
#using Kendo.Mvc.UI
#using System.Collections
#Html.Kendo().DropDownListFor(model => model.Status).BindTo((IEnumerable)ViewBag.Statuses).DataTextField("Name").DataValueField("Value").OptionLabel("Please Select")

Why do I have 2 different required field validation popups

I have 2 different pages, each with a form on them.
now one page if I leave a required field empty I get these validation popups:
This is the code of the image above:
<div class="form-group">
<p class="control-label col-md-5"><i class="fa fa-exclamation-triangle triangle" aria-hidden="true"></i> <b>Voorletter(s)</b></p>
<div class="col-md-4">
#Html.EditorFor(model => model.Voorletters, new { htmlAttributes = new { #class = "form-control", required = "required", placeholder="K" } })
#Html.ValidationMessageFor(model => model.Voorletters, "", new { #class = "text-danger" })
</div>
</div>
but on the other I get a popup, which if you ask me has the same code:
<div class="form-group">
<p class="control-label col-md-5"><i class="fa fa-exclamation-triangle triangle" aria-hidden="true"></i> <b>Functie</b></p>
<div class="col-md-4">
#Html.EditorFor(model => model.Functie1, new { htmlAttributes = new { #class = "form-control", required = "required" } })
#Html.ValidationMessageFor(model => model.Functie1, "", new { #class = "text-danger" })
</div>
</div>
but I would prefer the latter option, how do I always get that?
Is the latter validation message a chrome standard?
EDIT:
earlier I tried to change the first validation message "This field is required" by making a metaclass, but that only changed the text.
[MetadataType(typeof(medewerkerMetaData))]
public partial class medewerker
{
public partial class medewerkerMetaData
{
//[Required(ErrorMessage = "Verplicht invullen!")]
public string Voorletters { get; set; }
// more code
}
}
The first is showing mvc client side validation error from your [Required] attribute. The 2nd is showing the browsers HTML-5 validation message (because of the required attribute) which means you have not included the jquery.validate.js and jquery.validate.unobtrusive.js scripts in that view (or thay are loaded incorrectly ad are not working).
When you use the validation scripts, its adds the novalidate attribute to your form so that the HTML-5 validation is ignored (the 2 do not work well together).
Despite what you may think, you do not want the browsers HTML-5 validation - its is client side validation only (not server side which is the most important) and will not match your server side validation attributes.

<br> tag in #Html.LabelFor?

I am trying to split lable into two lines. But if put in the #Html.LabelFor it is not working is there any alternative options?
controller
meetingAbstract.AbstractTitleInEnglishLabel = meetingQuestionses[0].question_text
+ "/" + meetingQuestionses[0].question_text_en;
view
#Html.LabelFor(model => model.AbstractTitleInEnglishLabel,
Model.AbstractTitleInEnglishLabel, new { #class = "control-label mandatory" })
Create a regular label
<label for="#Html.IdFor(m => m.AbstractTitleInEnglishLabel)"
class="control-label mandatory">
Text above
Text below
</label>
I would create a custom HtmlHelper.
Inherit IHtmlString and use TagBuilder to create one.
Then you can use it with #Html.CustomLabelFor(...).
so that the html will render you will need to use html.raw. try changing it to this
<label class="control-label mandatory">#Html.Raw(model => model.AbstractTitleInEnglishLabel)</label>
Where do you want to put break within label? After 1st, 2nd, 3rd, n-th word?
IMHO, it's better to increase the height of label and let HTML render it on it's own.
In your css set:
.control-label{
height: 60px; /* or change accordingly */
}
#Html.Raw(HttpUtility.HtmlDecode(#Html.LabelFor(model => model.AbstractTitleInEnglishLabel,
Model.AbstractTitleInEnglishLabel, new { #class = "control-label mandatory" }).ToString()))

validationmessagefor missing "data-valmsg-for" in editorfor

I have a collection of objects that I'm trying to display, however the span generated by the ValidationMessageFor does not include all the validation attributes:
<span class="field-validation-error">This field is required</span>
instead of:
<span class="field-validation-error" data-valmsg-replace="true" data-valmsg-for="Questions[0].SingleAnswer"></span>
This is how I'm generating the html:
<fieldset id="dr_profileUpdates">
#Html.EditorFor(model => model.Questions)
</fieldset>
And here is my editor template:
#Html.ValidationMessageFor(model => model.SingleAnswer)
#Html.TextBoxFor(model => model.SingleAnswer, new { #class = "textBoxDefault" })
The validation works, however the span does not dissapear after filling out the textbox and focusing out of it - I would assume this is because the span does not get generated correctly
Any help is appreciated.
EDIT: Actually it appears that after posting back to the server and returning the partial view (assuming the ModelState is invalid), those attributes do not get generated again - it only seems to affect the ValidationMessage. Any ideas?
Thanks,
Try add on top of your razor file
#{
Html.EnableUnobtrusiveJavaScript();
}