The problem is if the check box is not checked request can not find the correct mapping function in springMVC controller.Because it seems like it only send true values if it is checked,but it does not send false value if it not checked.
<form action="editCustomer" method="post">
<input type="checkbox" name="checkboxName"/>
</form>
#RequestMapping(value = "/editCustomer" , method = RequestMethod. POST)
public void editCustomer(#RequestParam("checkboxName")String[] checkboxValue)
{
if(checkboxValue[0])
{
System.out.println("checkbox is checked");
}
else
{
System.out.println("checkbox is not checked");
}
}
I solved a similar problem specifying required = false in #RequestMapping.
In this way the parameter checkboxValue will be set to null if the checkbox is not checked in the form or to "on" if checked.
#RequestMapping(value = "/editCustomer" , method = RequestMethod. POST)
public void editCustomer(#RequestParam(value = "checkboxName", required = false) String checkboxValue) {
if (checkboxValue != null) {
System.out.println("checkbox is checked");
} else {
System.out.println("checkbox is not checked");
}
}
Hope this could help somebody :)
I had the same problem and I finally found a simple solution.
Just add a default value to false and it will work out perfectly.
Html code :
<form action="path" method="post">
<input type="checkbox" name="checkbox"/>
</form>
Java code :
#RequestMapping(
path = "/path",
method = RequestMethod.POST
)
public String addDevice(#RequestParam(defaultValue = "false") boolean checkbox) {
if (checkbox) {
// do something if checkbox is checked
}
return "view";
}
I had to add hidden input with same name of the checkbox. Value must be "checked".Then I can check the length of the string array within controller or in my service class.
<form action="editCustomer" method="post">
<input type="hidden" name="checkboxName" value="checked">
<input type="checkbox" name="checkboxName"/>
</form>
#RequestMapping(value = "/editCustomer" , method = RequestMethod. POST)
public void editCustomer(#RequestParam("checkboxName")String[] checkboxValue)
{
if(checkboxValue.length==2)
{
System.out.println("checkbox is checked");
}
else
{
System.out.println("checkbox is not checked");
}
}
I think the proper answers are Paolo's and Phoste's ones.
ITOH, if you have many checkboxes/params/lasrge forms you can use a Map<T,T> RequestParam, so if the property does not exists - Map.get() return null - the checkbox is not checked.
#RequestMapping(value = "/editCustomer" , method = RequestMethod. POST)
public void editCustomer(#RequestParam Map<String,String> params)
{
String checkboxValue = map.get("checkboxName");
if(checkboxValue != null)
{
System.out.println("checkbox is checked");
return;
}
System.out.println("checkbox is not checked");
}
Related
Please send me in the right direction here - I'm really confused.
See, I have this App.Shell:
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
x:Class="ExpensesMobile.AppShell"
x:DataType="Login_VM:Login_VM"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:Approvals="clr-namespace:ExpensesMobile.View.Approvals"
xmlns:Settings="clr-namespace:ExpensesMobile.View.AppSettings"
xmlns:Login_VM="clr-namespace:ExpensesMobile.ViewModel.Login"
xmlns:Login="clr-namespace:ExpensesMobile.View.Login"
xmlns:Globals="clr-namespace:ExpensesMobile"
xmlns:ExpenseReports="clr-namespace:ExpensesMobile.View.ExpenseReports"
xmlns:res="clr-namespace:ExpensesMobile.Resources.Strings"
Title="{x:Static res:AppRes.ExpenseReports}"
Shell.FlyoutBehavior="Disabled">
<Shell.Items>
<ShellContent x:Name="Login" ContentTemplate="{DataTemplate Login:Login}" Route="Login" Shell.FlyoutBehavior="Disabled" Shell.NavBarIsVisible="False" ></ShellContent>
</Shell.Items>
<TabBar Route="Login">
<ShellContent ContentTemplate="{DataTemplate Login:Login}" Shell.FlyoutBehavior="Disabled" Shell.NavBarIsVisible="False" ></ShellContent>
</TabBar>
<TabBar x:Name="MyTabBar" Shell.NavBarHasShadow="true" Route="Home">
<Tab
x:Name="tabExpenseReports"
Title="{x:Static res:AppRes.ExpenseReports}"
Icon="ExpenseReports"
Shell.BackgroundColor="#001933"
Shell.ForegroundColor="#AB1300">
<ShellContent
x:Name="Pending"
ContentTemplate="{DataTemplate ExpenseReports:Pending}"
Route="Pending"
Title="{x:Static res:AppRes.Pending}"
Icon="pending.svg"
Shell.NavBarIsVisible="False">
</ShellContent>
<ShellContent
x:Name="Finalized"
ContentTemplate="{DataTemplate ExpenseReports:Finalized}"
Route="Finalized"
Title="{x:Static res:AppRes.Finalized}"
Icon="finalized.svg"
Shell.NavBarIsVisible="False">
</ShellContent>
</Tab>
<Tab
x:Name="tabApprovals"
Title="{x:Static res:AppRes.Approvals}"
Icon="approvals"
IsEnabled="{Binding TabApprovalsIsEnabled}"
Shell.BackgroundColor="#AB1300"
Shell.ForegroundColor="#001933">
<ShellContent
x:Name="Approvals"
ContentTemplate="{DataTemplate Approvals:Approvals}"
Shell.NavBarIsVisible="False"
Route="Approvals"
Title="{x:Static res:AppRes.Approvals}"
Icon="approvals.svg">
</ShellContent>
<ShellContent
x:Name="Approved"
ContentTemplate="{DataTemplate ExpenseReports:Approved}"
Shell.NavBarIsVisible="False"
Route="Approved"
Title="{x:Static res:AppRes.Approved}"
Icon="approved.svg">
</ShellContent>
</Tab>
<Tab
Title="{x:Static res:AppRes.Settings}"
Icon="settings" Shell.BackgroundColor="#193300"
x:Name="tabSettings">
<ShellContent
ContentTemplate="{DataTemplate Settings:Settings}"
Route="Settings" />
</Tab>
</TabBar>
</Shell>
In the Login page I decide whether the logged-in user is an admin or not. If he isn't, then he shouldn't have access to the tab "Approvals".
I have tried in several ways to make the tab disabled in this case. This is what I have right now:
In the class "Globals" I have this (I have them in the Globals class because I will need to refer to these values across the application):
using ExpensesMobile.Model;
namespace ExpensesMobile
{
public static class Globals
{
public static ExpensesMobileDB ExpensesMobileDB;
public static LoginStatus loginStatus;
public enum LoginStatus
{
loginRefused,
loginAcceptedAdmin,
loginAcceptedRegularUser
}
}
}
In Login_VM I have this code:
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using ExpensesMobile.Resources.Strings;
using ExpensesMobile.Services;
using ExpensesMobile.Utils;
using ExpensesMobile.View.ExpenseReports;
using System.Diagnostics;
using static ExpensesMobile.Globals;
namespace ExpensesMobile.ViewModel.Login
{
[QueryProperty(nameof(Login), "Login")]
public partial class Login_VM : Base_VM
{
public readonly LoginService loginService;
private readonly IConnectivity connectivity;
[ObservableProperty]
private string password;
[ObservableProperty]
private bool tabApprovalsIsEnabled = false;
[ObservableProperty]
private string username;
public Login_VM(LoginService loginService, IConnectivity connectivity)
{
this.loginService = loginService;
this.connectivity = connectivity;
//TEMP CODE - DEBUG
username = ".....";
password = ".....";
}
private static async Task ShowToast(LoginStatus loginStatus)
{
string text;
if (loginStatus == LoginStatus.loginAcceptedAdmin)
text = AppRes.LoginConfirmationManager;
else
text = AppRes.LoginConfirmationUser;
await Utils.Utils.ShowToast(text);
}
[RelayCommand]
private async Task LoginAsync()
{
if (IsBusy)
{
return;
}
try
{
if (connectivity.NetworkAccess != NetworkAccess.Internet)
{
await Shell.Current.DisplayAlert(AppRes.MsgConnectivity1, AppRes.MsgConnectivity2, "OK"); //No connectivity, Please check your internet connection and then try again;
return;
}
IsBusy = true;
LoginStatus loginStatus = LoginService.Login(username, password);
if (loginStatus == LoginStatus.loginAcceptedAdmin)
{
TabApprovalsIsEnabled = true;
await ShowToast(loginStatus);
await Shell.Current.GoToAsync($"//{nameof(Pending)}");
}
else if (LoginService.Login(username, password) == LoginStatus.loginAcceptedRegularUser)
{
TabApprovalsIsEnabled = false;
await ShowToast(loginStatus);
await Shell.Current.GoToAsync($"//{nameof(Pending)}");
}
else if (LoginService.Login(username, password) == LoginStatus.loginRefused)
{
await Shell.Current.DisplayAlert(AppRes.Login, AppRes.LoginWrongUsernameOrPass, "OK"); //Wrong username and/or password !
}
Globals.loginStatus = loginStatus;
}
catch (Exception ex)
{
Debug.WriteLine($"Unable to login: {ex.Message}");
ErrorHandling.HandleError(ex);
}
finally
{
IsBusy = false;
}
}
}
}
If I login as a regular user, the line 'tabApprovalsIsEnabled = false;' executes.
I have added this line because I wanted App.Shell to bind to Login_VM and not to Globals directly (that is a regular class, and has no knowledge of ObservableProperties).
However, although the tab Approvals has the xaml 'IsEnabled="{Binding TabApprovalsIsEnabled}"', this is not taken into consideration and my tab remains enabled.
Obviously I am missing something, and probably I am ignorant enough of the sequence of operations in MAUI - probably the code above executes and sets the property "tabApprovalsIsEnabled" to false AFTER the binding in AppShell has been done, I don't know....
How could I solve this problem, please ?
Thank you very much,
Alex.
You should reset the value of property TabApprovalsIsEnabled not tabApprovalsIsEnabled .
Please refer to the following code:
[RelayCommand]
private async Task LoginAsync()
{
// other code
try
{
// other code
LoginStatus loginStatus = LoginService.Login(username, password);
if (loginStatus == LoginStatus.loginAcceptedAdmin)
{
// replace `tabApprovalsIsEnabled` with `TabApprovalsIsEnabled`
//tabApprovalsIsEnabled = true;
TabApprovalsIsEnabled = true;
//........
}
else if (LoginService.Login(username, password) == LoginStatus.loginAcceptedRegularUser)
{
// replace `tabApprovalsIsEnabled` with `TabApprovalsIsEnabled`
// tabApprovalsIsEnabled = false;
TabApprovalsIsEnabled = true;
}
else if (LoginService.Login(username, password) == LoginStatus.loginRefused)
{
//Wrong username and/or password !
await Shell.Current.DisplayAlert(AppRes.Login, AppRes.LoginWrongUsernameOrPass, "OK");
}
Globals.loginStatus = loginStatus;
}
catch (Exception ex)
{
Debug.WriteLine($"Unable to login: {ex.Message}");
ErrorHandling.HandleError(ex);
}
finally
{
IsBusy = false;
}
}
Note:
We need set BindingContext for AppShell.xaml.cs. Then if we change the value of property TabApprovalsIsEnabled of the current ViewModel, the UI could refresh automatically.
public partial class AppShell : Shell
{
Login_VM _VM;
public AppShell()
{
InitializeComponent();
Routing.RegisterRoute("DetailPage", typeof(DetailPage));
_VM = new Login_VM();
this.BindingContext = _VM;
}
[Obsolete]
protected override void OnAppearing()
{
base.OnAppearing();
Device.StartTimer(TimeSpan.FromSeconds(5), () =>
{
_VM.TabApprovalsIsEnabled = false;
return false;
});
}
}
I am a newbie to spring boot and thymeleaf,
I have a list of books ina table with checkboxes, I am not sure how to pass selected booksId s from the view to the controller and use them by the borrow or Return bttons? could you please help?
Here is my Html file https://wtools.io/paste-code/b5g4
and this is the relevant part from my bookService implementation :
public void borrowBook(String userEmail, String bookIds, Model model) {
if (!CollectionUtils.isEmpty(books)) {
User user = userRepository.findByEmail(userEmail);
List<String> requestedBooks = getRequestedBookIds(bookIds);
List<Book> borrowedBooks = new ArrayList<>();
List<Book> invalidBooks = new ArrayList<>();
for (Book book : books) {
if (requestedBooks.contains(book.getId()) && !book.isBorrowed() && user != null) {
book.setBorrowed(true);
book.setBorrowedBy(user.getFirstName());
borrowedBooks.add(book);
model.addAttribute("bookStatus", "Book BOrrowed By " + user.getFirstName());
} else {
invalidBooks.add(book);
model.addAttribute("bookStatus", "No Books are available");
}
}
model.addAttribute("inValidBooks", invalidBooks);
model.addAttribute("bookList", borrowedBooks);
}
}
#SuppressWarnings("unchecked")
private List<String> getRequestedBookIds(String bookIds) {
List<String> requestedBookIds = null;
try {
requestedBookIds = new ObjectMapper().readValue(bookIds, ArrayList.class);
} catch (Exception e) {
e.printStackTrace();
}
return !CollectionUtils.isEmpty(requestedBookIds) ? requestedBookIds : new ArrayList<>();
}
and this is from the controller:
#GetMapping(value = "/available", produces = MediaType.APPLICATION_JSON_VALUE)
public String getAvailableFreeBooks(Model model) {
List<Book> availableBooks= bookService.getAllAvailaBooks();
model.addAttribute("listBooks", availableBooks);
return "available_books";
}
In your html you would probably:
<input type="checkbox" th:field="*{requestedBooks}" value="${book.getId}">
omit the id (if you don't need it).
use th:field (instead of name).
set value to the id of the current book.
In your controller: requestedBooks (#ModelAttribute("requestedBooks") List<String> requestedBooks) will (should) contain all checked book ids.
Ref: https://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#checkbox-fields
A sample repository:
https://github.com/xerx593/soq67602860
Uppdate:
To process the checkboxes client-sided (jquery),
you can obtain an array of ids like:
<script language="javascript" type="text/javascript">
$(document).ready(function () {
$("#btnBorrow").click(function() {
var reqBookIds = new Array();
$('input[name="requestedBooks"]:checked').each(function() {
reqBookIds .push(this.value);
});
alert("Number of selected Books: "+reqBookIds .length+"\n"+"And, they are: "+reqBookIds);
// do stuff with reqBookIds ...
)};
});
</script>
With the mentioned <input type="checkbox" .../> (consider that <input/> should be inside a <form/>!!) and a button like:
<button id="btnBorrow">Borrow</button>
..the userEmail must come from client side???
This weekend a lot of struggle with a View Component.
I try to add a dropdownlist that does an auto postback onchange. This dropdownlist is on a view component.
I have 2 problems:
I don't get the asp-page-handler after the post, does it work like I implemented it on the form-tag?
Post calls method public void OnPost on razor page containing view
component. I would think it would be better to have a method on the
View Component like OnChangeProject?
The code of my View (View Component):
<form asp-page-handler="ChangeProject" method="post">
#Html.AntiForgeryToken()
#Html.DropDownList("id", new SelectList(Model, "Id", "Id"), new { onchange = "this.form.submit()" })
</form>
Thanks in advance!!
I exprienced the same problem and the way i fixed it is already answered in your question.
The form call is made at the page where you got your View Component embedded. I don't think it would be even possible to call a handler in your View Component with asp-page-handler as this is Razor Pages tag helper.
The way i got it work is simply putting the page-handler method on the PageModel that is embedding the View Component. In your case you can simply implement this handler on your Razor Page:
public IActionResult OnPostChangeProject()
{
// ... do Something
}
I don't know though how it would work to trigger a controller method in your View Component. Possibly create a new Controller class and route to it with asp-controller and asp-action in your form tag.
You should remember that the Page handlers could be viewed as convenience methods.
All the ASP.Net Core framework does is looks at the Query string parameters and Form data and translates it into Page handler calls.
And even though the Handlers are not available in View Components or Partial Views you still can get access to all the required ingredients by injecting IHttpContextAccessor into the View.
It will provide you with HttpContext.Request which contains both the Query and the Form properties.
You can then create your own Handler mapper. Here is one, for example:
public class HandlerMapping
{
public string Name { get; set; }
public System.Delegate RunDelegate { get; set; }
public HandlerMapping(string name, Delegate runDelegate)
{
RunDelegate = runDelegate;
Name = name;
}
}
public class PartialHandlerMapper
{
IHttpContextAccessor _contextAccessor;
public PartialHandlerMapper(IHttpContextAccessor contextAccessor)
{
_contextAccessor = contextAccessor;
}
public void RouteHandler(List<HandlerMapping> handlerMappings, string PartialDescriminatorString = null)
{
var handlerName = _contextAccessor.HttpContext.Request.Query["handler"];
var handlerMapping = handlerMappings.FirstOrDefault(x => x.Name == handlerName);
if (handlerMapping != null)
{
IFormCollection form;
try
{
form = _contextAccessor.HttpContext.Request.Form;
}
catch
{
return;
}
if (!string.IsNullOrWhiteSpace(PartialDescriminatorString) && form[nameof(PartialDescriminatorString)] != PartialDescriminatorString)
return;
List<Object> handlerArgs = new List<object>();
var prmtrs = handlerMapping.RunDelegate.Method.GetParameters();
foreach (var p in prmtrs)
{
object nv = null;
var formValue = form[p.Name];
if (!StringValues.IsNullOrEmpty(formValue))
{
try
{
nv = TypeDescriptor.GetConverter(p.ParameterType).ConvertFromString(formValue);
}
catch (FormatException)
{
//throw new FormatException($"Could not cast form value '{formValue}' to parameter {p.Name} (type {p.ParameterType}) of handler {handlerName}. Make sure you use correct type parameter. ");
nv = Activator.CreateInstance(p.ParameterType);
}
catch (ArgumentException)
{
nv = Activator.CreateInstance(p.ParameterType);
}
}
else
nv = Activator.CreateInstance(p.ParameterType);
handlerArgs.Add(nv);
}
handlerMapping.RunDelegate.DynamicInvoke(handlerArgs.ToArray());
}
}
}
And inject it into the service container:
services.AddScoped<PartialHandlerMapper>();
And here is a shopping cart partial view code section example:
#inject ShoppingManager shoppingManager
#inject PartialHandlerMapper partialHandlerMappping
#{
string ToggleCartItemTrialUseHandler = nameof(ToggleCartItemTrialUseHandler);
string DeleteCartItemHandler = nameof(DeleteCartItemHandler);
List<HandlerMapping> handlerMappings = new List<HandlerMapping> {
new HandlerMapping (ToggleCartItemTrialUseHandler, (Guid? PicID, bool? CurrentValue) => {
if (PicID == null || CurrentValue == null)
return;
shoppingManager.UpdateTrial((Guid)PicID, !(bool)CurrentValue);
}),
new HandlerMapping (DeleteCartItemHandler, (Guid? PicID) => {
if (PicID == null)
return;
shoppingManager.RemoveProductFromCart((Guid)PicID);
})
};
partialHandlerMappping.RouteHandler(handlerMappings);
var cart = shoppingManager.GetSessionCart();
}
Form element example from the same view:
<td align="center" valign="middle">
<form asp-page-handler="#DeleteCartItemHandler">
<input name=PicID type="hidden" value="#i.PicID" />
<button>
Delete
</button>
</form>
</td>
Where #i is an Item in the shopping cart
It's possible to create a combo (Controller/ViewComponent) by decorating the controller with a ViewComponent(Name="myviewcomponent").
Then create the invokeasync as usual, but because the controller doesn't inherit from a ViewComponent, the return result would be one of the ViewComponent result (ViewViewComponentResult, et).
The form in the viewcomponent can then have a button with asp-controller/action tag helpers targetting the controller/action.
I want to make the filtering using radio button event. And I've searched about calling java method into html, and found this link. And try to implement it.
HTML file
<form action="${pageContext.request.contextPath}/servlet" method="post">
<input type="radio" value="1" name="radioFilter1"/> <br/>
<input type="radio" value="2" name="radioFilter2"/> <br/>
<input type="radio" value="3" name="radioFilter3"/> <br/>
</form>
SomeClass.java
public class SomeClass{
public String value;
public String filter1() {
return value= "1";
}
public String filter2() {
return value= "2";
}
public String filter3() {
return value= "3";
}
}
Controller.java
#RequestMapping("/servlet")
public String filterServlet(HttpServletRequest request, HttpServletResponse response) throws Exception {
SomeClass s = new FilterSorting();
if (request.getParameter("radioFilter1") != null) {
s.value= s.filter1();
} else if (request.getParameter("radioFilter2") != null) {
s.value= s.filter2();
} else if (request.getParameter("radioFilter3") != null) {
s.value= s.filter3();
}
return "/newhtml.html";
}
#RequestMapping("/newhtml.html")
public String newhtml(Model model, HttpServletRequest request, HttpServletResponse response) throws Exception {
FilterSorting s = new FilterSorting();
list = Common.getList(dbSessionId, s.value);
model.addAttribute("asnlist", asnList);
return "/newhtml.html";
}
I'm using Spring framework version 4.0.0. And also I already tried using servlet, but it seems didn't work.
What I want is, when I click radioFilter2 then it will call filter2() which is set the parameter value is 2, and so on. And then the value will use as parameter to load content. But from what I've tried, it didn't work. Please help me, thanks!
I need to write HTML from my .java page. Here is what I have tried
This is my tml code fragment
${testFunction()}
This is my java code fragment
public String testFunction()
{
return "<input type='checkbox' name='leaf' id='leaf' value='leaf'/>"
}
The result I want is a checkbox. What I get is a string "input type='checkbox' name='leaf' id='leaf' value='leaf'".
Any help would be appreciated Thanks.
If you want to render string as html you need to use MarkupWriter#writeRaw() method:
void beginRender(MarkupWriter writer) {
writer.writeRaw("<input type='checkbox' name='leaf' id='leaf' value='leaf'/>");
}
Or you can use OutputRaw component:
<t:outputraw value="testFunction()"/>
Or you can use Renderable to write markup:
#Property(write = false)
private final Renderable checkbox = new Renderable() {
public void render(MarkupWriter writer) {
writer.element("input",
"type", "checkbox",
"id", "leaf",
"name", "leaf",
"value", "leaf");
writer.end();
// if you need checked attribute
// writer.getElement().attribute("checked", "checked");
}
};
And on template:
<t:delegate to="checkbox"/>