I'm trying to create a radio button component in Blazor that has two way data binding but I can't seem to get the value (testNumber) on the parent to change. I am new to Blazor and C#, so any help would be greatly appreciated. Thanks
ChildComp.razor
<div>
<label for="radio1">1</label>
<input
id="radio1"
type="radio"
value="1"
name="test"
checked="#(_selectedGroup == 1)"
#onclick="#(() => _selectedGroup = 1)"/>
<label for="radio2">2</label>
<input
id="radio2"
type="radio"
value="2"
name="test"
checked="#(_selectedGroup == 2)"
#onclick="#(() => _selectedGroup = 2)"/>
</div>
#code {
private int _selectedGroup = 0;
[Parameter]
public int BindingValue
{
get => _selectedGroup;
set
{
if (_selectedGroup == value )
{
return;
}
else
{
_selectedGroup = value;
}
BindingValueChanged.InvokeAsync(value);
}
}
[Parameter]
public EventCallback<int> BindingValueChanged { get; set; }
}
ParentComp.razor
<div>
<ChildComp #bind-BindingValue="testNumber" />
<h5>#testNumber</h5>
</div>
#code {
int testNumber = 0;
}
As you probably noticed bind does not work with radio buttons. On GitHub you can see the discussion about it here. It's sad that Blazor doesn't support these simple features...
I had the same problem and came across this solution:
#code {
public int EditionCode = 1;
// "Edition" class has "int Code" and "string Text" properties.
public Edition[] Editions = new [] {
new Edition { Code = 1, Text = "Home" },
new Edition { Code = 2, Text = "Pro" },
new Edition { Code = 3, Text = "Enterprise" },
};
}
#foreach (var edition in this.Editions)
{
<label>
<input type="radio"
name="edition"
checked="#(EditionCode == edition.Code)"
onchange="#(() => EditionCode = edition.Code)"/>
#edition.Text
</label>
}
If this solution doesn't solve your needs, then have a look here (a bit more complex).
Related
I try to show and disable a button by adding "disabled" class in a component (pre-hidden) but failed - it's not working. Where I did wrong ?
Component Button :
<div class="form-group">
<button class="btn btn-primary #disabled">Disable Me</button>
</div>
#code {
string _password;
string disabled = "";
public void Disable()
{
disabled = "disabled";
}
}
Index.razor :
#page "/"
<h1>How to disable button in component ?</h1>
<button class="btn btn-primary" #onclick="ShowAndDisableButton">Show and disable button</button>
#if (show)
{
<ButtonComponent #ref="button"/>
}
#code
{
ButtonComponent button = new();
bool show = false;
void ShowAndDisableButton()
{
show = true;
button.Disable();
}
}
UPDATED : if I change the ShowAndDisableButton code to
async Task ShowAndDisableButton()
{
show = true;
await Task.Delay(TimeSpan.FromMilliseconds(10)); // add this, wait for a while
button.Disable();
}
and change button code in index.razor to
<button class="btn btn-primary" #onclick="()=>ShowAndDisableButton()">Show and disable button</button>
it works. but I don't know why and don't want to use such way, are there any proper way?
The problem is that button.Disable(); does not cause the normal rerendering.
And it is an overcomoplicated way of doing things.
In the page:
#if (show)
{
<ButtonComponent Disabled="!show" />
}
#code
{
//ButtonComponent button = new();
bool show = false;
void ShowAndDisableButton()
{
show = true;
//button.Disable();
}
}
and the button itself:
<div class="form-group">
<button class="btn btn-primary" disabled="Disabled">Disable Me</button>
</div>
#code {
string _password;
// string disabled = "";
[Parameter] public bool Disabled {get; set; }
}
But you won't be able to use this button.
Use disabled="#disabledState"
Where disabledState is a boolean
I am trying to collect all the options that the user have selected for a checkbox list. The checkbox list is built using a foreach loop and I have a int[] that I am trying to put the id into. Any help would be great.
View
#{
int idxFormats = 0;
foreach (var item in Model.ListOfFormats)
{
<div class='col-md-6'>
<input type="checkbox" value=#item.Value name="chkFormat" />
<label asp-for=#item.Selected>#Html.Raw(#item.Name)</label>
#Html.HiddenFor(m => Model.selectedFormats[idxFormats]);
</div>
idxFormats++;
}
#Html.ValidationMessageFor(model => model.selectedFormats[idxFormats])
}
Model
public List<GenericValues> ListOfFormats { get; set; }
[Display(Name = "At least one 'Format' must be selected")]
public int[] selectedFormats { get; set; }
Change the Checkbox name to selectedFormats
<input type="checkbox" value=#item.Value name="selectedFormats" />
Test example:
Model:
public class Test
{
public List<GenericValues> ListOfFormats { get; set; }
public int[] selectedFormats { get; set; }
}
public class GenericValues
{
public int Value { get; set; }
public string Name { get; set; }
public bool Selected { get; set; }
}
View:
#model Test
#{
ViewData["Title"] = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Index</h1>
<form method="post">
#{
foreach (var item in Model.ListOfFormats)
{
<div class='col-md-6'>
<input type="checkbox" value=#item.Value name="selectedFormats" />
<label asp-for=#item.Selected>#Html.Raw(#item.Name)</label>
</div>
}
}
<input type="submit" value="submit" />
</form>
Controller:
public IActionResult Index()
{
Test test = new Test
{
ListOfFormats = new List<GenericValues>
{
new GenericValues
{
Name = "A",
Value = 1,
},
new GenericValues
{
Name = "B",
Value = 2,
},
new GenericValues
{
Name = "C",
Value = 3,
}
}
};
return View(test);
}
[HttpPost]
public IActionResult Index(Test test)
{
return Ok();
}
Result:
if you are looking to put id as value of your idxFormats then use this code in your checkbox:
<input type="checkbox" value=#item.Value name="chkFormat" id="#idxFormats" />
Edit:
I am not so familiar with c#, I tested with minimum code :
// Replace the model correct path by yours
#model IEnumerable<WebApplication1.Models.MyModels.ListOfFormats>
#{
int idxFormats = 0;
foreach (var item in Model)
{
<div class='col-md-6'>
<input type="checkbox" value=#item.Value name="chkFormat" id="#idxFormats"/>
<label>#Html.Raw(#item.Name)</label>
</div>
idxFormats++;
}
}
I have a created a grid using devexpress blazor. I want to implement an inline editing for this grid, although devexpress haven't implemented any inline editing functionality.
Here is ht code i have used for this Grid.
#if (dischargeBoards == null)
{
<p><em>Loading...</em></p>
}
else
{
<div class="card demo-card-wide border-bottom-0">
<div class="card-header border-bottom-0">
ClientVisitGuid: <b>#(selectedRow == null ? (object)"(none)" : selectedRow.ClientVisitGuid)</b>
CurrentLocationGUID: <b>#(selectedRow == null ? (object)"(none)" : selectedRow.CurrentLocationGUID)</b>
PatientName: <b>#(selectedRow == null ? "(none)" : selectedRow.PatientName)</b>
</div>
</div>
<DxDataGrid Data="#dischargeBoards"
ShowFilterRow="false"
#bind-SingleSelectedDataRow="#SelectedRow"
ShowPager="true"
ShowGroupPanel="true"
PageSize="19">
<DxDataGridColumn Field="#nameof(DischargeBoardVisit.LocationGroup)" Caption="L/C Group" AllowGroup="true"></DxDataGridColumn>
<DxDataGridColumn Field="#nameof(DischargeBoardVisit.Location)" Width="100px"></DxDataGridColumn>
<DxDataGridColumn Field="#nameof(DischargeBoardVisit.PatientName)" SortIndex="0" Width="240px"></DxDataGridColumn>
<DxDataGridColumn Field="#nameof(DischargeBoardVisit.Service)" Width="240px"></DxDataGridColumn>
<DxDataGridDateEditColumn Field="#nameof(DischargeBoardVisit.DischargeDateExp)"
DisplayFormatString="MM/dd/yyyy"
EditFormatString="d"></DxDataGridDateEditColumn>
<DxDataGridColumn Field="#nameof(DischargeBoardVisit.DischargeTimeExp)" Caption="Time Exp"></DxDataGridColumn>
<DxDataGridColumn Field="#nameof(DischargeBoardVisit.Family)" Caption="Family">
<DisplayTemplate>
#{
var checkboxFamily = (context as DischargeBoardVisit).Family;
if (checkboxFamily)
{
<button class="btn btn-success btn-circle btn-circle-sm m-1">#*<i class="fa fa-check"></i>*#</button>
}
else
{
<button class="btn btn-danger btn-circle btn-circle-sm m-1"></button>
}
}
</DisplayTemplate>
</DxDataGridColumn>
<DxDataGridColumn Field="#nameof(DischargeBoardVisit.Rehab)">
<DisplayTemplate>
#{
var checkboxRehab = (context as DischargeBoardVisit).Rehab;
//<input type="checkbox" checked="#checkboxRehab" disabled readonly />
if (checkboxRehab)
{
<button class="btn btn-success btn-circle btn-circle-sm m-1">#*<i class="fa fa-check"></i>*#</button>
}
else
{
<button class="btn btn-danger btn-circle btn-circle-sm m-1"></button>
}
}
</DisplayTemplate>
</DxDataGridColumn>
<DxDataGridColumn Field="#nameof(DischargeBoardVisit.Comment)" Width="240px"></DxDataGridColumn>
</DxDataGrid>
}
#code {
DischargeBoardVisit[] dischargeBoards;
// readonly string _id = Guid.NewGuid().ToString();
[Parameter]
public string DisplayFormatString { get; set; }
protected override async Task OnInitializedAsync()
{
dischargeBoards = await DischageBoard.GetDischargeAsync();
SelectedRow = dischargeBoards.FirstOrDefault();
}
public DischargeBoardVisit context { get; set; }
DischargeBoardVisit selectedRow;
public DischargeBoardVisit SelectedRow
{
get
{
return selectedRow;
}
set
{
selectedRow = value;
InvokeAsync(StateHasChanged);
}
}
}
I haved tried in different ways. But i couldn't find any proper solution for that.
thanks in advance. All appreciation would be highly appreciated.
Currently, there is no straightforward way to do so. That's why I suggest that you wait until this feature is implemented since it is in the Backlog of the DevExpress Blazor team. Please follow the updates in the blogs.
I have been trying to find out why submitting a form in my partialview makes some components of my model null. Just before calling the partialview, I have a model with count of AgainstWhoms and TimesPlaces each equal to one.
Even with a simplified partialview where only a column is added, on submitting to the controller, my AgainstWhoms and TimesPlaces collections are now null.
public class ComplaintViewModel
{
[Key]
public int Id { get; set; }
.........
public List<AgainstWhomViewModel> AgainstWhoms { get; set; }
public List<TimesPlacesViewModel> TimesPlaces { get; set; }
public List<WitnessesViewModel> Witnesses { get; set; }
}
public async Task<ActionResult> GetNewComplaint(int intComplainantId)
{
var complaint = new ComplaintViewModel
{
ComplainantId = intComplainantId,
StatusId = 1,
ReceivedDate = DateTime.Now,
AgainstWhoms = new List<AgainstWhomViewModel> { },
TimesPlaces = new List<TimesPlacesViewModel> { },
Witnesses = new List<WitnessesViewModel> { }
};
var newtime = new TimesPlacesViewModel { IncidentDate = DateTime.Today, IncidentLocation = "aaaaaaaaa" };
complaint.TimesPlaces.Add(newtime);
var complainee = new AgainstWhomViewModel { CountryId = 1, Email = "aaaaaaa#yahoo.com"};
complaint.AgainstWhoms.Add(complainee);
..................
return PartialView("_ComplaintFormModal", complaint);
}
Below is my simplified view.
#model ComplaintViewModel
<div>
<form id="Complaintform" asp-controller="Complaint" asp-action="RegisterComplaint" method="post">
<div class="form-row">
<div class="form-group col-lg-8 required">
<label asp-for="ComplaintTitle" class="control-label"></label>
<input type="text" class="form-control" required asp-for="ComplaintTitle">
<span asp-validation-for="ComplaintTitle" class="text-danger"></span>
</div>
</div>
<button type="submit" value="Submit">Submit</button>
</form>
</div>
In my controller post method, newComplaint.AgainstWhom and newComplaint.TimePlaces are now null, while other fields that do not belong to any of the linked lists are returned correctly:
[HttpPost]
public ActionResult RegisterComplaint(ComplaintViewModel newComplaint)
{
..............
You didn't render the TimesPlaces/AgainstWhoms so that data will lose since they are not in form collection .
If you want to edit the TimesPlaces/AgainstWhoms items , you can render like :
#for (int i = 0; i < Model.TimesPlaces.Count; i++)
{
<tr>
<td>
#Html.TextBoxFor(model => model.TimesPlaces[i].IncidentDate)
</td>
<td>
#Html.TextBoxFor(model => model.TimesPlaces[i].IncidentLocation)
</td>
</tr>
}
If you don't want to edit them , you can use hidden field :
#for (int i = 0; i < Model.TimesPlaces.Count; i++)
{
#Html.HiddenFor(model => model.TimesPlaces[i].IncidentDate)
#Html.HiddenFor(model => model.TimesPlaces[i].IncidentLocation)
}
But it's better to avoid that . If you don't want to edit them , i would prefer to query database with ID again for up-to-date records , and avoid posting large data in a request .
This is first time I have tried to make an API using MVC4. So far it is working ok.
For practice I want to try and send my model using a queryString in the GET method instead of my current POST send method.
As I have no clue how to start, and whats need to be done ? Can you come with some advices ?
Can I have the Index view as it is ? or anything need to be changed ?
I also would like to keep the curent GET method I have to show the list, I guess that will interfere if I add a new GET method fot sending querystring ?
All advices is helpful here ^_^
namespace MessageHandler.Models
{
public class Message
{
public int Id { get; set; }
public double Amount { get; set; }
public string PaymentMessage { get; set; }
public string Name { get; set; }
public string Adress { get; set; }
}
}
namespace MessageHandler.Services
{
public class MessageRepository
{
private const string CacheKey = "MessageStore";
public MessageRepository()
{
var ctx = HttpContext.Current;
if (ctx != null)
{
if (ctx.Cache[CacheKey] == null)
{
var messages = new Message[]
{
new Message
{
Id = 1, PaymentMessage = "payment for order 23434",
Name = "Christer Glenning", Adress = "Grenvagen 24",
Amount = 2300
},
new Message
{
Id = 2, PaymentMessage = "payment for order 24354",
Name = "Carl Ingemar", Adress = "Regnbagen 446",
Amount = 44
}
};
ctx.Cache[CacheKey] = messages;
}
}
}
public Message[] GetAllMessages()
{
var ctx = HttpContext.Current;
if (ctx != null)
{
return (Message[])ctx.Cache[CacheKey];
}
return new Message[]
{
new Message
{
Id = 0,
Name = "placeHolder"
}
};
}
public bool SaveMessage(Message message)
{
var ctx = HttpContext.Current;
if (ctx != null)
{
try
{
var currentData = ((Message[])ctx.Cache[CacheKey]).ToList();
currentData.Add(message);
ctx.Cache[CacheKey] = currentData.ToArray();
return true;
}
catch (Exception exp)
{
Console.WriteLine(exp.Message);
return false;
}
}
return false;
}
}
}
using MessageHandler.Models;
using MessageHandler.Services;
namespace MessageHandler.Controllers
{
public class MessageController : ApiController
{
private MessageRepository repo;
public MessageController()
{
this.repo = new MessageRepository();
}
public Message[] Get()
{
return repo.GetAllMessages();
}
public HttpResponseMessage Post(Message message)
{
this.repo.SaveMessage(message);
var response = Request.CreateResponse<Message>(System.
Net.HttpStatusCode.Created, message);
return response;
}
}
}
<header>
<div class="content-wrapper">
<div class="float-left">
<p class="site-title">
API</p>
</div>
</div>
</header>
<div id="body">
<ul id="messages"></ul>
<form id="saveMessageForm" method="post">
<h3>Create a new Message</h3>
<p>
<label for="messageId">Id:</label>
<input type="text" name="Id" />
</p>
<p>
<label for="messagePaymentMessage">Message:</label>
<input type="text" name="PaymentMessage" />
</p>
<p>
<label for="messageName">Name:</label>
<input type="text" name="Name" />
</p>
<p>
<label for="messageAdress">Adress:</label>
<input type="text" name="Adress" />
</p>
<p>
<label for="messageAmount">Amount:</label>
<input type="text" name="Amount" />
</p>
<input type="button" id="saveMessage" value="Save" />
</form>
</div>
#section scripts
{
<script type="text/javascript">
$(function()
{
$.getJSON('/api/message', function (messagesJsonPayload) {
$(messagesJsonPayload).each(function (i, item) {
$('#messages').append('<li>' + item.PaymentMessage + '</li>' +
'<li>' + item.Name + '</li>' +
'<li>' + item.Adress + '</li>' +
'<li>' + '$' + item.Amount.toFixed(2) + '</li>' + '<br>');
});
});
});
</script>
<script type="text/javascript">
$('#saveMessage').click(function()
{
$.post("api/message",
$("#saveMessageForm").serialize(),
function(value)
{
$('#messages').append('<li>' + value.PaymentMessage + '</li>' +
'<li>' + value.Name + '</li>' +
'<li>' + value.Adress + '</li>' +
'<li>' + '$' + value.Amount.toFixed(2) + '</li>');
},
"json"
);
});
</script>
}
Well, I'm not expert for build an API, but I think you need to step back and learning concept for building an API (specially the REST one).
here's the link that maybe useful for you:
build-restful-apis-with-aspnet-web-api
REST API Tutorial