I use bootstrap with ASP.NET Core and to indicate form field validation errors i want to add has-errors class to form-group div when given field has an error. The view looks like that:
<div class="form-group">
<label asp-for="Fragment.Content" class="col-lg-2 control-label "></label>
<div class="col-lg-10">
<textarea asp-for="Fragment.Content" class="form-control content-editor"></textarea>
<span class="help-block">A longer block of help text that breaks onto a new line and may extend beyond one line.</span>
<span asp-validation-for="Fragment.Content"></span>
</div>
</div>
I would like to do something like:
<div class="form-group" asp-add-class-if-error="has-errors" for-field="Fragment.Content"/>
I know i can write my own tag helper, however i am curious if there is a built-in solution.
I found that you can use:
#using Microsoft.AspNetCore.Mvc.ModelBinding
#if(ViewData.ModelState.GetFieldValidationState("Fragment.Content") == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid)
{
// something here
}
Related
I am creating a large html form (using the EditForm tag) in my Blazor WASM app, containing many properties. Mostly all of which follow an identical pattern of a label, an input, and a validation section. I would like to create a render fragment that would let me cut down on my mark up. I am struggling with how to reference the "bind-Value" for the correct property.
Here is the start of the edit form, which has a model called registerModel with many properties, including string "Company" representing "Company Name"
<EditForm autocomplete="off" Model="#registerModel" OnValidSubmit="#HandleValidRegisterSubmit">
This is an example of a single section for the company name part, of which there are many in the form for all the individual properties:
<div class="row mb-3 align-items-center">
<div class="col-sm-2">
<label>
Company Name
</label>
</div>
<div class="col-sm-6 p-0">
<InputText #bind-Value="registerModel.Company" type="text" placeholder="Enter Company Name"
class="rounded-input form-control"
id="Last"
autocomplete="off"/>
</div>
<div class="col-sm-4">
<ValidationMessage For="() => registerModel.Company"/>
</div>
</div>
I want a render fragment function to automate creating each form section so I don't have to repeat so much html, and I can make my component more reusable. This is what I have tried so far
RenderFragment<(
EventCallback<string> eventCallback,
Expression<Func<string>> func,
string id,
string label,
string placeholder)> RenderFieldSection = (item) => __builder =>
{
<div class="row mb-3 align-items-center">
<div class="col-sm-2">
<label>#item.label</label>
</div>
<div class="col-sm-6 p-0">
<InputText #bind-Value="#item.eventCallback" type="text" placeholder="#item.placeholder"
class="rounded-input form-control"
id="#item.id"
autocomplete="off"/>
</div>
<div class="col-sm-4">
<ValidationMessage For="#item.func"/>
</div>
</div>
};
Which I am trying to call in the markup with:
#RenderFieldSection((
eventCallback: EventCallback.Factory.Create<string>(this, s => { registerModel.Company = s;}),
func:()=> registerModel.Company,
id: "Company",
label:Translate("CompanyNameLabel"),
placeholder:Translate("CompanyNamePlaceholder")
)
)
Everything works except the input #bind-Value="#item.eventCallback" part, which is supposed to take an EventCallback<string>. This gives the following error.
Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type
I guess I am constructing the event callback wrongly, but I don't know how to do it. Any ideas? I expect I could do it by finding the property via reflection, but I (naively?) wonder if I can avoid the overhead of that.
I have a code like this in my aspx page:
<div class="container">
<h3 class="my-5 h2">Tasks List</h3>
<div class="form-group w-75">
<label for="lastmonth">Enter Tasks:</label>
<textarea class="form-control" id="lastmonth" rows="7"></textarea>
</div>
</div>
But the text area does not seem to change even if I give or .I want to increase the textbox to occupy 3/4th of my page. Right now, it is only 1/4th. I even did the below change in my Site.css but it doesnt seem to change.
input,
select,
textarea {
max-width: 100%;
}
You can easily achieve by setting cols and rows as attributes instead of using bootstrap
Try this:
<textarea class="form-control" id="lastmonth" cols="30" rows="10"></textarea>
I am attaching the screenshot for your reference:
I read the other questions that were similar but my issue is more basic. I'm rather new to bootstrap but I'm testing it out to see if this will work for a simple form that I need to be opened by phones, tablets, and any other device.
I'm trying to get my textbox on the same line as the text that describes it. Instead, the textbox is under the text.
Here is what is happening:
Here is the cshtml page of the above:
#model MvcBootstrap.Models.HomeModels.VisitingCustomer
#{
ViewBag.Title = "Home Page";
}
<div class="">
<p class="lead">Please enter your branch number, account number, and at least the first three characters of your last name or at least the first three characters of your company name below so we can locate your account.</p>
</div>
<div class="container">
#using (Html.BeginForm("TypeOfPayment", "Home", FormMethod.Post))
{
<div class="row">
<h2>Account Lookup</h2>
<div class=".col-md-4">
Branch Number
</div>
<div class=".col-md-8">
#Html.TextBoxFor(m => m.Branch, new {#class = "", #maxlength = "2"})
</div>
</div>
<div class="row">
<input id="submitpayment" class="typicalbutton" type="submit" value="Continue" />
</div>
}
</div>
I have no additional css code nor have I modified any of the existing css.
This should be pretty straight forward but I'm just not grasping the concept I guess. What am I doing wrong?
You could group the Branch Number and the text box in one column like so
<div class="col-md-4">
<label for="branch-number">Branch Number</label>
# add text box here and give it an id="branch-number"
</div>
Also, you don't need to have a . before the class name in your classes.
You can try this format. form-inline class makes the form inline. you don't need to use the responsive column classes. also you should use class="col-md-*" not class=".col-md-*"
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<form class="form-inline">
<div class="form-group">
<label for="branch"> Branch Number</label>
<input type="text" class="form-control" id="branch no">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
You can specify the class for different screen
i.e
col-lg-1 to col-lg-12 for large screen
col-md-1 to col-md-12 for desktop / laptop screen
col-sm-1 to col-sm-12 for tablet screen
col-xs-1 to col-xs-12 for mobile screen
Example
<input type="text" class="col-lg-6 col-md-6 col-sm-6 col-xs-12" >
What you are looking for is an inline form.
#using (Html.BeginForm("TypeOfPayment", "Home", FormMethod.Post, new { #class="form-inline" }))
{
<div class="row">
<div class="col-md-12">
<h2>Account Lookup</h2>
<div class="form-group">
#Html.LabelFor(m => m.Branch)
#Html.TextBoxFor(m => m.Branch, new {#class = "form-control", #maxlength = "2"})
</div>
<input id="submitpayment" class="typicalbutton" type="submit" value="Continue" />
</div>
</div>
}
In your model for this form you will want to add a [DisplayName] attribute for your Branch property so that you can use the Html.LabelFor() helper I included above:
[DisplayName("Branch Number")]
public string Branch { get; set; }
You will also want to read more about the grid system. Your original code did not use the proper classes for the columns.
Like #Asif Raza said, you should specify what size of screen are targeting. Keep in mind that the sizing will work for the size you specify and UP. So if you specify a medium size screen, it will affect medium size screens and larger, not smaller.
I dont think thats your issue though, I think whats happening with you is there are extra margins you are not seeing that is causing the textbox to be placed below. The max width of the container is going to be 12 columns, which you are using, but if there are any other margins in between it's going to cause the textbox to fall below. I recommend inspecting the element with F12 to zone in and see if there is anything extra being added.
The width of the Select tag helper in the following veiw remains fixed no matter what value I change in its style attribute style="width:10000px;". Whether it's set to 10px or 10000px the width remains the same. On the other hand, in the same example below, the input tag ProjectNumber along with the Instructions message (correctly) occupies the entire width of the computer screen. Note 1: It's a multi select dropdown (but I think that should not mater). 2. I'm using VS2015-Update3 that comes with built-in Bootstrap functionality:
<div class="row">
<div class="col-sm-3">
#await Component.InvokeAsync("MainLeftMenu")
</div>
<div class="col-md-9">
<form id="target" asp-controller="myTest" asp-action="myAction" method="post" class="form-horizontal">
<div class="form-group">
<label asp-for="SelectedIDs" class="col-md-2 control-label"></label>
<div class="col-md-10">
<select asp-for="SelectedIDs" asp-items="Model.myList" style="width:10000px;"></select>
</div>
</div>
<div class="form-group">
<label asp-for="ProjectNumber" class="col-md-2 control-label"></label>
<div class="col-md-2">
<input asp-for="ProjectNumber" class="form-control" />
<span asp-validation-for="ProjectNumber" class="text-danger"></span>
</div>
<div class="col-md-5">Instructions: Add number in the format such as: ABC-123-xyz-000</div>
</div>
<button type="submit" class="btn btn-default">Submit Test</button>
</form>
</div>
</div>
In bootstrap for the select in form you can add class="form-control" like input type text.
For reference: http://getbootstrap.com/css/#forms
Issue resolved by adding style="min-width:700px;overflow:auto;" to the select tag helper. You can change 700px to whatever width you need.
I am fairly new to C# and asp.net and am having trouble showing something submitted in a form. The form element is a tag. The drop-down info is pulled from a data base and displays correctly. It's just getting it to post to another page after the form is submitted is where I am having the problem. Any help would be appreciated.
Contact.aspx:
<form action="Default.aspx" method="post" data-transition="pop">
<div data-role="fieldcontain">
<label for="topEmails">Business Entity ID:</label>
<select name="topEmails" id="topEmails" data-native-menu="false"
runat="server">
</select>
</div>
<input type="submit" data-iconpos="right" data-inline="true"
data-icon="plus" name="sendMessage" id="sendMessage" value="Send Info">
</form>
Contact.aspx.cs:
AdventureWorks2012DataContext db = new AdventureWorks2012DataContext();
var emails = (from b in db.EmailAddresses
select new { b.EmailAddressID, b.BusinessEntityID }).Take(20);
topEmails.DataTextField = "BusinessEntityID";
topEmails.DataValueField = "BusinessEntityID";
topEmails.DataSource = emails;
topEmails.DataBind();
Default.aspx.cs:
FormSuccessBID.InnerHtml = "Business Entity ID: " + Request.Form["topEmails"] + "";
Any ideas why this wouldn't be working?
Update:
Contact.aspx:
<asp:Content runat="server" ID="BodyContent" ContentPlaceHolderID="MainContent">
<h2 style="text-align: center;">Contact Kyle</h2>
<form action="Default.aspx" method="post" data-transition="pop">
<div data-role="fieldcontain">
<label for="userFName">First Name:</label>
<input type="text" name="firstName" id="uFName">
</div>
<div data-role="fieldcontain">
<label for="userLName">Last Name :</label>
<input type="text" name="lastName" id="uLName">
</div>
<div data-role="fieldcontain">
<label for="productsCategories">Products:</label>
<select name="productCategories" id="productCategories" data-native-menu="false" runat="server"></select>
</div>
<div data-role="fieldcontain">
<label for="topEmails">Business Entity ID:</label>
<select name="topEmails" id="topEmails" data-native-menu="false" runat="server"></select>
</div>
<input type="submit" data-iconpos="right" data-inline="true" data-icon="plus" name="sendMessage" id="sendMessage" value="Send Info">
</form>
</asp:Content>
You're missing "runat='server'" in your form definition.
In ASP.NET you're also allowed one form per page. Not sure from what you're posted if you're trying to put multiple forms on there, but if you are, it's not going to work.
I think all you need to do to accomplish what you want is have an ASP.NET button on the page, with the postbackURL set to the page you want to go to. (Of course, you need to do this in a server-side form)
I think you're mixing ASP.NET methods with other, different technologies. (From the look of it, you probably used classic ASP or PHP perhaps?)
If you can't use .NET for whatever reason, the ID/name of the field is not going to be what you're expecting. You need to inspect the form post and find its value - something along the lines of "clt00_somethingelse_topEmails". (Again, this is going to be a heck of a lot easier if you use the .NET way of doing things, but you may have a requirement not to)