How to enable/disable textfield on checkbox value change in apache wicket? - java

I have an html form containing a check box & a ListView containing some text fields. On checking the checkbox i want the textfields to be disabled & vice versa.
I am using checkbox with AjaxFormComponentUpdatingBehavior. But its not setting the textfields as enabled/disabled. Below is the code snippet -
Checkbox.add(new AjaxFormComponentUpdatingBehavior("onchange") {
private static final long serialVersionUID = 1L;
#Override
protected void onUpdate(AjaxRequestTarget target) {
listView.setEnabled(!Checkbox.getModelObject());
listViewContainer.addOrReplace(listView);
listViewContainer.setOutputMarkupId(true);
target.addComponent(listViewContainer);
}
});
HTML is -
<form wicket:id="geoForm">
Checkbox: <input type="checkbox" wicket:id="unmanagedChk" />
<div id="listViewContainer" wicket:id="listViewContainerId">
<div wicket:id="customGeoForChannel">
<div>
Latitude(decimal):
<input type="text" wicket:id="lat" maxlength="18" />
</div>
<div>
Longitude(decimal):
<input type="text" wicket:id="lon" maxlength="19" />
</div>
<div>
Radius(miles):
<input type="text" wicket:id="radius" maxlength="3" />
</div>
</div>
</div>
</form>
geoForm --- Form
customGeoForChannel --- ListView
lat, lon, radius --- textfields
unmanagedChk --- checkbox

Your listViewContainer has to write out its markup id before you update it via ajax. Do this immediately when you construct it!
listViewContainer.setOutputMarkupId(true);
BTW the following is superfluous, since the listView is already contained in the component tree (at least I hope you added it already):
listViewContainer.addOrReplace(listView);

I added the listviewcontainer to the form & added the form to the target as below. This solved the issue.
protected void onUpdate(AjaxRequestTarget target) {
listView.setEnabled(!Checkbox.getModelObject());
listViewContainer.addOrReplace(listView);
listViewContainer.setOutputMarkupId(true);
target.addComponent(listViewContainer);
form.add(listViewContainer);
target.addComponent(form);
}

Related

Pass an input string to different jsp page base on button clicked using nested form

I'm trying to pass a trackingNo to jsp page based on which button is pressed.
I created 2 buttons, addnew and search.
The addnew is supposed to get the input trackingNo from the input field and pass it to tracking.jsp if it is pressed,
and the search is supposed to get the input trackingNo from the input field and pass it to a home_student_result.jsp.
I'm not sure what is the correct way to do it, so I tried using a nested form with "add" id in one form and "srch" id in another.
After running it, only the top form works. The inner form doesn't work.
Can anyone please help me, or suggest a better way to do it please?
<div>
<form id="add" method="post" action="tracking.jsp">
<i class="fas fa-search"></i>
<form id="srch" method="post" action="home_student_result.jsp">
<input name="target" type="input" placeholder = "Search..." class = "text_search"/>
</form>
</form>
</div>
<button class="button_search" onclick="document.getElementById('add').submit()">
Add New
</button>
<button class="button_search" onclick = "document.getElementById('srch').submit();">
Search
</button>
You can use only one form and click of button you can change the action value to particular value depending on button click and then submit your form.
Demo Code :
function submit(value) {
console.log(value)
//if value is add
if (value == "add") {
//change action of form
document.getElementById('forms').action = 'tracking.jsp'
document.getElementById('forms').submit(); //submit
} else {
document.getElementById('forms').action = 'home_student_result.jsp'
document.getElementById('forms').submit();
}
}
<div>
<!--add id to form-->
<form id="forms" method="post" action="tracking.jsp">
<i class="fas fa-search"></i>
<input name="target" type="input" placeholder="Search..." class="text_search" />
</form>
</div>
<!--add function with parameter(value of button) -->
<button class="button_search" value="add" onclick="submit(this.value)">
Add New
</button>
<button class="button_search" value="srch" onclick="submit(this.value)">
Search
</button>
You can keep both the forms independently and set the value of 'target' field using javascript. something like below .I've added id attributes to your code to work with vanilla javascript.
<div>
<form id="add" method="post" action="tracking.jsp">
<i class="fas fa-search"></i>
<input id="addText" type="input" placeholder = "add text"/>
<button class="button_search" onclick="addToSearch()">
Add New
</button>
</form>
<form id="srch" method="post" action="home_student_result.jsp">
<input name="target" id="searchValue" type="input" placeholder = "Search..." class = "text_search"/>
<button class="button_search" onclick = "document.getElementById('srch').submit();">
Search
</button>
</form>
</div>
<script>
function addToSearch(){
var textValue = document.getElementById('addText').value;
document.getElementById('searchValue').value = textValue;
}
</script>

How to make HTML Button perform action in Java?

Basically I'm creating an upvote/downvote system, Now I've created two buttons in HTML :
<button type="button" name="upvote"></button>
<br>
<input type="number" th:value = "${commentValue}" disabled>
<br>
<button type="button" name="downvote"></button>
First button with name attribute - "upvote" and second with "downvote" , Now I want to catch a click on button and change the commentValue accordingly, If user clicks upvote, comment value must incriment and on downvote it must decrement
I found some topics that said to implement ActionListener, Create JButton objects and etc. but isn't there any simpler way ?
This is my code right now, The buttons do nothing. :
Controller :
private int numberValue = 0;
#GetMapping("/check")
public String nuberCheck(Model model){
model.addAttribute("commentValue", numberValue);
return "numberCheck";
}
#PostMapping("/check")
public String upvote(Model model, #RequestParam String action){
if (action == "upvote"){
numberValue++;
model.addAttribute("commentValue", numberValue);
}else if (action == "downvote"){
numberValue --;
model.addAttribute("commentValue", numberValue);
}
return "numberCheck";
}
numberCheck :
<form action="#" th:action="#{/check}" method="post">
<button type="button" name="action" th:value="upvote" th:text = "upvote"></button>
<br>
<input type="number" th:value = "${commentValue}" disabled>
<br>
<button type="button" name="action" th:value = "dowvnote" th:text = "dowvnote"></button>
</form>
FIXED
Change button types to "submit" and then in controller :
#PostMapping("/check")
public String check(Model model,#RequestParam String action) {
System.out.println(action);
if (action.equals("upvote")) {
numberValue++;
model.addAttribute("numberValue", numberValue);
}
if (action.equals("dowvnote")) {
numberValue--;
model.addAttribute("numberValue", numberValue);
}
return "numberCheck";
}
#RequestParam String action "action" is the name attribute of button and "save" and "cancel" are the "value" attributes :) hope it helps
Sample:
HTML:
<form action="#" data-th-action="#{/action}" data-th-object="${model}" method="post">
<button type="submit" name="upvote"></button>
<button type="submit" name="downvote"></button>
</form>
Java:
#RequestMapping(value="/action", method=RequestMethod.POST)
public ModelAndView onClickAction() {}
Use the following and implement in your code
$(document).ready(function(){
$("#up").click(function(){
var up = $.post("/upvote", {changeBy: 1}, function(dataBack){
$("#upvote").text(dataBack);
});
});
$("#down").click(function(){
var down = $.post("/downvote", {changeBy: 1},
function(dataBack){
$("#downvote").text(dataBack);
});
});
});
You can use jquery for that. first add jquery library in your html page and write function like below inside script tag
function upVote(){
var counter= $('.comment').val();
counter++;
$('.coment').val(counter);
}
function downVote(){
var counter= $('.comment').val();
counter--;
$('.coment').val(counter);
}
<button type="submit" name="upvote" th:onclick="'upVote();'"></button>
<br>
<input type="number" class="comment"th:value = "${commentValue}" disabled>
<br>
<button type="submit" name="downvote" th:onclick="'upVote();'"></button>
There is one best way to solve this. When you click button trigger one event and at that event increase or decrease value. Use that value in an thymeleaf and pass it to the controller.

Wicket Form loads empty values after validation fails

We have a trouble in our wicket 6 project. We have a form which is loading via AJAX.
When our form fails validation we can't load other object into the model correcly (fields that have failed are empty).
I'm trying to create new object (my modelobject value = new MyObject()) and validation fails :
Then if I choose already created object from the tree on the left side I can see empty fields :
But really this object has all the fields setted :
Form markup:
<wicket:panel>
<div wicket:id="feedback"></div>
<form wicket:id="form" role="form" class="form-horizontal">
<div class="form-group">
<label wicket:for="shortName" class="control-label col-sm-4"><wicket:message key="shortName"></wicket:message></label>
<div class="col-sm-8">
<input type="text" class="form-control" wicket:id="shortName" />
</div>
</div>
<div class="form-group">
<label wicket:for="fullName" class="control-label col-sm-4"><wicket:message key="fullName"></wicket:message></label>
<div class="col-sm-8">
<input type="text" class="form-control" wicket:id="fullName" />
</div>
</div>
<div class="form-group">
<label wicket:for="parentServiceGroup" class="control-label col-sm-4"><wicket:message key="parentServiceGroup"></wicket:message></label>
<div class="col-sm-8">
<select type="text" class="form-control width-abs" wicket:id="parentServiceGroup"></select>
</div>
</div>
<div class="form-group">
<label wicket:for="status" class="control-label col-sm-4"><wicket:message key="status"></wicket:message></label>
<div class="col-sm-8">
<select class="form-control width-abs" wicket:id="status"></select>
</div>
</div>
<div>
<a wicket:id="save" class="btn btn-primary"></a>
<a wicket:id="cancel" class="btn btn-default"></a>
</div>
</form>
</wicket:panel>
Form code :
#Override
protected void onInitialize() {
super.onInitialize();
add(new MiraFeedbackPanel("feedback"));
final Form form = new Form("form", CompoundPropertyModel.of(getDefaultModel())) {
#Override
protected void onError() {
super.onError();
this.updateFormComponentModels();
}
};
add(form);
form.add(new TextField("shortName").setRequired(true));
form.add(new TextField("fullName"));
form.add(new DropDownChoice("status", Arrays.asList(CommonStatus.values()),
new ChoiceRenderer<CommonStatus>("name")).setRequired(true));
form.add(new ServiceGroupDropDownChoice("parentServiceGroup", getServiceGroupModelObject()));
form.add(new AjaxSubmitLabeledLink("save", "Save", form) {
#Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
super.onError();
error(getString("savingError"));
target.add(ServiceGroupEditPanel.this.get("feedback"));
}
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
getServiceGroupModelObject().setDateCreated(new Date());
getServiceGroupModelObject().setWorkerCreated(UserSession.get().getWorker());
getServiceGroupModelObject().setDateModification(new Date());
getServiceGroupModelObject().setWorkerModification(UserSession.get().getWorker());
DAOService.ejbCommonBean().saveEntity(getServiceGroupModelObject());
info(getString("serviceGroupSaved"));
target.add(ServiceGroupEditPanel.this.get("feedback"));
target.add(ServiceGroupEditPanel.this.getParent().getParent()
.get("serviceGroupsTree"));
}
});
form.add(new AjaxLabeledLink("cancel", "Cancel") {
#Override
public void onClick(AjaxRequestTarget target) {
getServiceGroupModel().setObject(null);
target.add(ServiceGroupEditPanel.this.getParent().getParent()
.get("serviceGroupsTree"));
target.add(ServiceGroupEditPanel.this.getParent().getParent()
.get("serviceNotSet"));
target.add(ServiceGroupEditPanel.this.getParent().getParent()
.get("selectedServiceGroup"));
target.add(ServiceGroupEditPanel.this.getParent());
}
});
}
We tried the workaround from this issue : Apache wicket: how to update model after validation error but it didn't helped.
UPD: Code of tree from where I'm trying to update model :
add(new DefaultNestedTree<ServiceGroup>("serviceGroupsTree", new ServiceGroupsTreeProvider()) {
#Override
protected Component newContentComponent(String id, IModel<ServiceGroup> node) {
return new Folder<ServiceGroup>(id, this, node) {
#Override
protected Component newLabelComponent(String id, IModel<ServiceGroup> model) {
return new Label(id, PropertyModel.of(model, "shortName"));
}
#Override
protected MarkupContainer newLinkComponent(String id, final IModel<ServiceGroup> model) {
return new AjaxLink(id, model) {
#Override
public void onClick(AjaxRequestTarget target) {
serviceGroupModel.setObject(DAOService.ejbCommonBean()
.getEntityFullFetch(
ServiceGroup.class,
model.getObject().getUidservicegroup()
));
target.add(ServiceGroupListPage.this.get("selectedServiceGroup"));
target.add(ServiceGroupListPage.this.get("serviceNotSet"));
target.add(ServiceGroupListPage.this.get("tabs"));
((ServiceGroupEditPanel)editPanelTab.getPanel("editTab")).onModelObjectChanged(target);
}
};
}
};
}
}
Our form added to the AjaxTabbedPanel :
final ServiceGroupEditPanelTab editPanelTab = new ServiceGroupEditPanelTab("editTab", serviceGroupModel);
List<ITab> tabsList = new ArrayList<>();
tabsList.add(editPanelTab);
tabsList.add(new ServiceGroupServicesPanelTab("servicesTab", serviceGroupModel));
final AjaxTabbedPanel tabs = new AjaxBootstrapTabbedPanel("tabs", tabsList);
tabs.setSelectedTab(0);
add(tabs);
UPD2:
I've added the sample project to Github to show my problem. In README.md there are steps to reproduce the error.
If you're just swapping the object in your model, all your form components will still hold the previous raw input.
Call Form#clearInput() after you've changed your model object, i.e. after you've chosen a different entity from your tree.

Spring MVC Form Submit - Dynamically change the form catching Object

My Spring framework version 3.1.4
Question ??? Is there is any way to dynamically change the form catching Object depending on the some criteria.
Its really tough to explain, I will do my best here
JAVA OBJECTS
I have a Java Object PatientDocument.java
public class PatientDocument{
#Id
protected String documentId;
#Indexed
protected String patientId;
#Indexed
protected Integer documentType;
protected Object document;
}
The field document in above class can have any datatype objects depending upon the value in field documentType Eg : If documentType is 1, the Object representing the field 'document' will be MedicalCertificate.Java and I'm storing the PatientDocument into MongoDB collection.
MedicalCertificate.java looks like
public class MedicalCertificate {
protected String complaint;
protected String suggestedRestingDays;
protected Integer treatingDoctor;
protected Integer medicalDirector;
}
CLIENT SIDE
I'm using Thymeleaf for my client side rendering
My patientDocument.html looks like
<form action="#" id="patientDocument" th:action="#{/emr/patient/document/save}" th:object="${patientDocument}" method="post" class="form-horizontal">
<!-- #### HIDDEN FIELDS #### -->
<input type="hidden" th:field="*{documentId}" class="col-xs-12" readonly="readonly"/>
<input type="hidden" th:field="*{documentType}" class="col-xs-12" readonly="readonly"/>
<input type="hidden" th:field="*{patientId}" class="col-xs-12" readonly="readonly"/>
<!-- Medical Certificate -->
<section th:if="${patientDocument.documentType == 1}" layout:include="#{emr/patient/medicalCertificate} :: main"></section>
<!-- Referal Letter -->
<section th:if="${patientDocument.documentType == 2}" layout:include="#{emr/patient/referalLetter} :: main"></section>
<!-- Acknowledgment Form -->
<section th:if="${patientDocument.documentType == 3}" layout:include="#{emr/patient/acknowledgeForm} :: main"></section>
<form>
medicalCertificate.html looks like
<section layout:fragment="main">
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label class="control-label col-xs-2">Complaint</label>
<div class="col-xs-10">
<textarea rows="5" th:field="*{document.complaint}" class="col-xs-12"></textarea>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-6">
<div class="form-group">
<label class="control-label col-xs-4">Rest For</label>
<div class="col-xs-8">
<input type="text" th:field="*{document.suggestedRestingDays}" class="col-xs-12"/>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-6">
<div class="form-group">
<label class="control-label col-xs-4">Treated By</label>
<div class="col-xs-8">
<input type="hidden" th:field="*{document.treatingDoctor}" readonly="readonly"/>
<input type="text" th:field="*{document.treatingDoctorName}" class="form-control"/>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label class="control-label col-xs-4">Medical Director</label>
<div class="col-xs-8">
<input type="hidden" th:field="*{document.medicalDirector}" readonly="readonly"/>
<input type="text" th:field="*{document.medicalDirectorName}" class="form-control"/>
</div>
</div>
</div>
</div>
</section>
View Controller
#RequestMapping(value="/document/save", method=RequestMethod.POST)
public String savePatientDocument(#ModelAttribute PatientDocument patientDocument, Model model, HttpServletRequest request){
logger.debug("Executing save for Patient Document : {}", patientDocument.toString());
////Logic to the Service Layer
}
Explanation of the Questions : As you can see the patientDocument.html the Client side form content corresponding to field 'document' will be replaced by Thymeleaf Fragments depending on documentType field. So when i submit the form into view controller the Object patientDocument contains the MedicalCertificate fields in place of field 'document'. Thats alright !!!
Now in View Controller, i need to say to the submit handler that "Hey, a PatientDocument.java object is coming as form submit. But the object inside the field 'document' will be 'MedicalCertificate.java'"
Where can i specify that?? Is there is any way to do it in SPRING MVC??
I need to alter the patientDocument.java Object as below before the Catching the client side form submit. But how?
PatientDocument patientDocument = new PatientDocument();
patientDocument.setDocument(new MedicalCertificate());
Thanks in advance
Good Day
Option 1: Change your container class to:
public class PatientDocument{
#Id
protected String documentId;
#Indexed
protected String patientId;
#Indexed
protected Integer documentType;
protected AcknowledgeForm acknowledgeForm;
protected MedicalCertificate medicalCertificate;
protected ReferalLetter referalLetter;
}
Then, form fields in medicalCertificate.html would look like:
<textarea rows="5" th:field="*{medicalCertificate.complaint}" class="col-xs-12"></textarea>
<input type="text" th:field="*{medicalCertificate.suggestedRestingDays}" class="col-xs-12"/>
<input type="hidden" th:field="*{medicalCertificate.treatingDoctor}" readonly="readonly"/>
<input type="text" th:field="*{medicalCertificate.treatingDoctorName}" class="form-control"/>
You will have to make similar changes to the other forms. Then, you can read the required property of PatientDocument based on its documentType.
Option 2: Write a PropertyEditor for PatientDocument to parse the request and set the document based on the request parameters.

Apache Wicket : Onclick of a form button, I need to call a small javascript function

Onclick of a form button, I need to call a small javascript function. This javascript function should validate some fields in the same form and then call the onSubmit() of the form which is in java.
Main Idea is that let validate happen in client side and not in java.
Complete idea :
I have help.html file as shown below :
<form wicket:id="form">
<input type="text" wicket:id="one"/>
<input type="text" wicket:id="two"/>
<input type="submit" wicket:id="save"/>
</form>
In help.java, I created a WebMarkupContainer and added this form with this submit button :
container.add(new Button("save") {
#Override
public void onSubmit() {
//saved
}
});
On click of the button in html, it calls onSubmit() and here we can do a validation on the text box values.
But I need to do all the validations in the HTML page itself.
OnClick of the Button Save, it should call a javascript funciton as shown below :
<form wicket:id="form">
<input type="text" wicket:id="one"/>
<input type="text" wicket:id="two"/>
<input type="submit" wicket:id="save" onclick="validateRange()"/>
</form>
JavaScript :
function validateRange(){
//logic
//Submit the form
}
Can this be done?
You need an AjaxSubmitLink or something like this. The you need to create a new IAjaxCallListener
public class MyAjaxCallListener implements IAjaxCallListener{
#Override
public CharSequence getBeforeHandler(Component component) {
return YOUR_JAVA_SCRIPT;
}
#Override
public CharSequence getBeforeSendHandler(Component component) {
return YOUR_JAVA_SCRIPT;
}
// ... not needed overrides can return null
}
Then in your AjaxSubmitLink you can add this AjaxCallListener
#Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
attributes.getAjaxCallListeners().add(new MyAjaxCallListener());
}
Here you have an example Try if yourself
HTML:
<form id="form" action="#">
<input id="text" type="text"/>
<input type="button" onclick="validate()" value="TEST"/>
</form>
JS:
function validate() {
var value = document.getElementById("text").value;
if (value == "") {
alert("you have to write something");
return false;
}
else
document.getElementById("form").submit();
}

Categories