bind- value to doesn't work in radio button in blazor - forms

For the following code, for some reason the selection of the radio buttons binds x.MyCapability with -> "on" instead of the label of the button (let's assume the labels of the radio element are *a ,*b and *c):
#foreach (var capability in myList)
{
<label>
<input type="radio" name="MyCapability" SelectedValue="MyCapability" #bind-value="x.MyCapability" />
#capability <text> </text>
</label>
}
how can I link x.MyCapability with a, b or c?
.NetCore 3.1

You are binding in a wrong way, here is the way you can
Your html
<div>Your Capability: #MyCapability</div>
<div>
#foreach (var capability in myList)
{
<div>
<label>#capability.MyCapability</label>
<input type="radio"
name="#capability.MyCapability"
#onchange=#(() => MyCapability = capability.MyCapability)
checked="#(capability.MyCapability==MyCapability)">
</div>
}
</div>
Here is the code behind
#code{
private string MyCapability = "a";
private List<Capabilities> myList = new()
{
new Capabilities()
{
MyCapability = "a"
},
new Capabilities()
{
MyCapability = "b"
},
new Capabilities()
{
MyCapability = "c"
}
};
public class Capabilities
{
public string MyCapability { get; set; }
}
}
When you select any option it will be update in above div

Related

How to open a blazored modal with bunit?

I want to test whether a modal opens up or not with bunit. The problem is, that the modal doesn't get rendered. How to open a blazored modal with bunit?
Modal Creation in my component under test:
<div style="display: flex; justify-content: flex-end">
<button class="btn btn-success
btn-lg"
id="openModalButton"
#onclick="CheckOpenModal">
Hinzufügen
</button>
</div>
#code
{
[CascadingParameter] public IModalService Modal { get; set; }
private async Task OpenModalForCreation()
{
List<string> ParameterA = new List<string>();
var parameters = new ModalParameters();
parameters.Add(nameof(CreationModal.ParameterA), ParameterA);
Modal.Show<CreationModal>("Create something", parameters);
}
}
My TestClass:
public class PrivateMachinesCompTest : TestContext
{
public CompTest()
{
Services.AddBlazoredModal();
}
[Fact]
public void CheckOpenModal()
{
modalService = new ModalService();
var cut = RenderComponent<ComponentUnderTest>(parameters => parameters
.AddCascadingValue(modalService));
var openModalButton = cut.Find("#openModalButton");
openModalButton.Click();
cut.MarkupMatches("Create something");
}
The problem is that you are not rendering the component that actually does the rendering. Just passing in an IModalService doesn't do it.
My approach would be to create a mock of IModalService and assert that the expected method on it is called.

Using drop-down as filter with Blazorise.DataGrid

The Blazorise DataGrid supports textbox filters.
I would like to use a drop-down component to allow filtering by specific values. What do I need to do to make the grid react to the change of the Select value?
Code Example
#page "/ItemList"
#using DataAccessLibrary
#using Blazorise
#using Blazorise.DataGrid
#inject IItemList _items;
<div align="center">
<h3>Item List</h3>
</div>
#if (ItemListItems is null)
{
<p>Loading...</p>
}
else
{
<DataGrid Data="#ItemListItems" TItem="ItemListItem" PageSize="20" ShowPager="true" Filterable="true" Striped="true" Narrow="true" #bind-SelectedRow="#selectedItem">
<EmptyTemplate>
<div class="box">
No items were found!
</div>
</EmptyTemplate>
<DataGridColumns>
<DataGridCommandColumn TItem="ItemListItem" Caption="Action" EditCommandAllowed="true">
<EditCommandTemplate>
<Button Color="Color.Primary" Clicked="#context.Clicked">Edit</Button>
</EditCommandTemplate>
</DataGridCommandColumn>
<DataGridNumericColumn TItem="ItemListItem" Field="#nameof(ItemListItem.ItemID)" Caption="Item ID" Sortable="true" TextAlignment="TextAlignment.Right">
<DisplayTemplate>
#(context.ItemID)
</DisplayTemplate>
</DataGridNumericColumn>
<DataGridSelectColumn TItem="ItemListItem" Field="#nameof(ItemListItem.TypeShortDesc)" Caption="Item Type" Sortable="true">
// This filter should replace the default textbox with a dropdown listing only specific values
<FilterTemplate>
<Select TValue="string" #bind-SelectedValue="#ItemTypeFilter">
#foreach (string type in ItemTypeList)
{
<SelectItem Value="#type">#type</SelectItem>
}
</Select>
</FilterTemplate>
</DataGridSelectColumn>
<DataGridSelectColumn TItem="ItemListItem" Field="#nameof(ItemListItem.Description)" Caption="Item Description" Sortable="true" TextAlignment="TextAlignment.Left" />
<DataGridSelectColumn TItem="ItemListItem" Field="#nameof(ItemListItem.StatusShortDesc)" Caption="Status" Sortable="true">
<FilterTemplate>
// This filter should replace the default textbox with a dropdown listing only specific values
<Select TValue="string" #bind-SelectedValue="#ItemStatusFilter">
#foreach(string status in ItemStatusList)
{
<SelectItem Value="#status">#status</SelectItem>
}
</Select>
</FilterTemplate>
</DataGridSelectColumn>
<DataGridNumericColumn TItem="ItemListItem" Field="#nameof(ItemListItem.ItemPrice)" Caption="Amount" Sortable="false" TextAlignment="TextAlignment.Right" DisplayFormat="{0:C}" />
</DataGridColumns>
</DataGrid>
}
#code {
private List<ItemListItem> ItemListItems;
private ItemListItem selectedItem;
private List<string> ItemStatusList;
private string ItemStatusFilter;
private List<string> ItemTypeList;
private string ItemTypeFilter;
protected override async Task OnInitializedAsync()
{
ItemListItems = await _items.GetItems();
ItemTypeList = await _items.GetItemTypes();
ItemStatusList = await _items.GetItemStatuses();
}
}

How to access DbContext in viewmodel with AspNetCore 2.1?

Using DropDown input fields is very common when you want to display a description while saving an ID in your database.
If I consider my Person model, I have PersonViewModel which has a SelectList used to display a list of possible Job Descriptions
public SelectList SelectJobDescription
{
get
{
MyDbContext _context = new MyDbContext();
var result = new SelectList(_context.Keywords
.Where(k => k.Name == ".JobDescription")
.OrderBy(r => r.Valuename), "Valuecode", "Valuename");
_context.Dispose();
return result;
}
}
and I use this SelectList in my create/edit views like this:
<div class="form-group row">
<label asp-for="JobDescription" class="col-sm-4 col-form-label"></label>
<div class="col-sm-8">
<select asp-for="JobDescription" asp-items="#Model.SelectJobDescription" class="form-control">
<option>Select a Job Description</option>
</select>
</div>
Is it correct to use _context this way in the ViewModel or there is some other way to do the same thing better (maybe DI?)
Set the property after instatiating the view model (or during initialization), for example:
var vm = new YourViewModel()
{
SelectJobDescription = new SelectList( _context... ),
};
return View( vm );

Html.DropDownListFor default selected value does not work

I have read hundreds of posts about this problem and I still can't find a solution.
Please help with this horrible mistery;
I would like to have different default values in my DropDownListFor. The "PartialViewList1 exists out of 4 items.
I want the DropDownListFor to select the id of the current item. (item.id)
But because of testing purposes I just filled in "3". And even that doesn't work.
The Models are filled correctly, I am able to add more code of the controller but that wouldn't add much. But please ask if you want me to.
And yes I know that it is better to make the SelectList in the controller, but first I want to make it work.
View:
#foreach (var item in Model.PartialViewList1)
{
<tr>
<td>Plaats: </td>
<td>#item.PlaceNumber</td>
<td>
#Html.DropDownListFor(x => x.PartialView.Id, new SelectList(Model.PartialViewList2, "Id", "Name", 3),
new { onchange = "this.form.submit();" })</td>
</tr>
}
Screen shot of the users view
I hope that maybe someone can use this for his or her problem.
With Stephen Mueke I have found the solution. The problem is that if "x => x.PartialView.Id" already has a value then the default value : "3" will be overriden by the Id.
And you can't generate multiple DropDownlistFor's while binding them to the same property.
My solution on my problem:
View:
#using (Html.BeginForm("_PartialSettingsDropDownList1", "Home")){
<table>
#for (int i = 0; i < Model.maxNumberOfViews; i++)
{
<tr>
<td>
Plaats #(i+1)
</td>
<td>
#Html.DropDownListFor(x => Model.PartialViewList[i].ID, new SelectList(Model.PartialViewList, "Id", "Name", Model.PartialViewList[i].ID), "select")
</td>
</tr>
}
</table>
#Html.HiddenFor(x => x.maxNumberOfViews)
<input class="submit" type="submit" value="Submit" />}
Controller:
[HttpGet]
public PartialViewResult _PartialSettingsDropDownList1()
{
PartialScreenViewModel viewModel = new PartialScreenViewModel();
viewModel.PartialViewList = homeModel.AllBoxViews(databaseRepository.PartialViews);
viewModel.maxNumberOfViews = viewModel.PartialViewList.Count();
return PartialView(viewModel);
}
[HttpPost]
public RedirectResult _PartialSettingsDropDownList1(PartialScreenViewModel viewModel)
{
for (int i = 0; i < viewModel.maxNumberOfViews; i++)
{
PartialView viewOnScreen = databaseRepository.PartialViews.FirstOrDefault(x => x.ID == viewModel.PartialViewList[i].ID);
databaseRepository.UpdatePartialView(viewOnScreen, i+1);
}
return new RedirectResult("Settings");
}
Model:
public List<PartialView> AllBoxViews(IEnumerable<PartialView> allViews)
{
List<PartialView> OnlyBoxViews = new List<PartialView>();
foreach (var item in allViews.Where(item => item.Type.Equals("box")))
{
OnlyBoxViews.Add(item);
}
return OnlyBoxViews;
}
ViewModel:
public class PartialScreenViewModel
{
public List<PartialView> PartialViewList { get; set; }
public int maxNumberOfViews { get; set; }
}
Result on screen: screenshot

MVC4 custom remote validator message appears, but is ignored at form submit

I have an MVC4 registration form that employs two custom remote validators. The first validator checks for email uniqueness, and works properly. The second checks number of uses for a voucher code. It correctly displays a message after entering a voucher code, but it fails to honor the custom remote validation at the point of submission.
In other words, you can enter a voucher code and see the "Cannot use voucher..." message from the remote validator. But you can still submit the form.
This is the abbreviated markup for the form, with just the relevant fields and the submit button. The full form is much larger. The email fields, which use custom validation successfully, are retained in this example for comparison. You can see the RegistrationVoucherCode field and validator near the end of the form.
#using (Html.BeginForm("Index", "Registration", FormMethod.Post))
{
<div class="row">
<div class="col-lg-6 col-md-6 col-xs-6 field_wrapper">
<div class="form_label">#Html.LabelFor(m => m.EmailAddress)</div>
<div class="form_field">#Html.TextBoxFor(m => m.EmailAddress)</div>
<div class="form_validator">#Html.ValidationMessageFor(m => m.EmailAddress)</div>
</div>
<div class="col-lg-6 col-md-6 col-xs-6 field_wrapper">
<div class="form_label">Confirm Email</div>
<div class="form_field">#Html.TextBoxFor(m => m.ConfirmEmail)</div>
<div class="form_validator">#Html.ValidationMessageFor(m => m.ConfirmEmail)</div>
</div>
</div>
<div class="row">
<div class="col-lg-6 col-md-6 col-xs-6 field_wrapper">
<div class="form_label">#Html.LabelFor(m => m.RegistrationVoucherCode)</div>
#{
string displayVoucherCode = Model.RegistrationVoucherCode.ToString();
if (Model.RegistrationVoucherCode == 0)
{
displayVoucherCode = string.Empty;
}
}
<div class="form_field">#Html.TextBoxFor(m => m.RegistrationVoucherCode, new { Value = displayVoucherCode, maxlength = 7 })</div>
<div class="form_validator">#Html.ValidationMessageFor(m => m.RegistrationVoucherCode)</div>
</div>
<div class="col-lg-6 col-md-6 col-xs-6 field_wrapper">
</div>
</div>
<div class="row">
<div class="col-xs-12">
<input type="submit" id="submitForm" value="Next" class="standard_button right_button" />
</div>
</div>
}
This is related code from my ProfileModel. The full model is much larger, so only relevant code is presented here. At the end of this you can see RegistrationVoucherCode.
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace SW.CEA.WebSite.Models.Registration
{
public class ProfileModel
{
public ProfileModel()
{
}
public Profile Profile { get; set; }
[Required(ErrorMessage = "Confirm Email is required.")]
[Display(Name = "Confirm Email")]
[StringLength(128)]
[RegularExpression(#"\w+([-+.']\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*", ErrorMessage = "Confirm Email Address is Not Valid")]
[System.Web.Mvc.Compare("EmailAddress", ErrorMessage = "Email addresses do not match..")]
public string ConfirmEmail
{
get
{
return Profile.ConfirmEmail;
}
set
{
Profile.ConfirmEmail = value;
}
}
[Required(ErrorMessage = "Email Address is required.")]
[Display(Name = "Email")]
[StringLength(128)]
[Remote("ValidateEmailUniqueness", "Registration")]
[RegularExpression(#"\w+([-+.']\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*", ErrorMessage = "Email Address is Not Valid")]
public string EmailAddress
{
get
{
return Profile.EmailAddress;
}
set
{
Profile.EmailAddress = value;
}
}
[Required(ErrorMessage = "Order Code is required.")]
[Display(Name = "Order Code")]
[Remote("ValidateVoucherCode", "Registration")]
public int RegistrationVoucherCode
{
get
{
return Profile.RegistrationVoucherCode;
}
set
{
Profile.RegistrationVoucherCode = value;
}
}
}
}
And these are custom validators from my RegistrationController. Again, email address validators appear here for comparison. My problem is with enforcing the ValidateVoucherCode custom validator at the point of form submission.
private bool IsEmailUnique(string EmailAddress)
{
var profile = ProfileRepository.GetProfile(EmailAddress);
return (profile == null);
}
[HttpGet]
public JsonResult ValidateEmailUniqueness(string EmailAddress)
{
if (!IsEmailUnique(EmailAddress))
{
return Json("Error, email address is already registered, please sign in.", JsonRequestBehavior.AllowGet);
}
return Json(true, JsonRequestBehavior.AllowGet);
}
[HttpGet]
public JsonResult ValidateVoucherCode(int RegistrationVoucherCode)
{
var voucher = VoucherRepository.GetVoucherWithProfiles(RegistrationVoucherCode);
if (voucher == null)
{
return Json("Invalid Order Code", JsonRequestBehavior.AllowGet);
}
if (voucher.Profiles.Count >= Settings.Default.MaxVoucherUses)
{
return Json("Cannot user voucher, will exceed maximum number of voucher uses.", JsonRequestBehavior.AllowGet);
}
return Json(true, JsonRequestBehavior.AllowGet);
}
The message, "Cannot user voucher, will exceed maximum number of voucher uses," will successfully appear on the client in this ValidationMessageFor when an overused validation code is entered. This again is from the form.
#Html.TextBoxFor(m => m.RegistrationVoucherCode, new { Value = displayVoucherCode, maxlength = 7 })
#Html.ValidationMessageFor(m => m.RegistrationVoucherCode)
Upon tabbing off the form field, debugger shows this remote validator being hit.
[HttpGet]
public JsonResult ValidateVoucherCode(int RegistrationVoucherCode)
So the ValidateVoucherCode custom validator is doing part of it's job. It's showing the "Cannot use voucher..." message when I tab off the field. But it doesn't prevent the form from being submitted. By contrast, the unique email address validator on the same form will prevent form submission. I need the RegistrationVoucherCode validator to operate in the same manner. Thanks for your help.
The solution was to replace jquery-2.1.0.min.js with https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js.
The scripts that my form presently uses are:
https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js
jquery.validate.min.js
jquery.validate.unobtrusive.min.js