Wicket 6.1 AjaxEventBehavior and form components with Models - ajax

final Address address = new Addres();
Form form = new Form("addressInputForm");
this.add(form);
form.setOutputMarkupId(true);
FormComponent fc;
fc = new RequiredTextField("street", new AddressModel(new Model(address), AddressModelType.STREET_MODEL));
fc.add(StringValidator.maximumLength(30));
fc.setLabel(new ResourceModel("label.street"));
form.add(fc);
form.add(new AjaxButton("submitAddressInput", form){
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form){
System.out.println(address.toString());
}
#Override
protected void onError(AjaxRequestTarget target, Form<?> form){
//
}
});
AjaxEventBehavior behavior = new AjaxEventBehavior("keyup"){
#Override
protected void onEvent(AjaxRequestTarget target) {
System.out.println(address.toString());
}
};
form.add(behavior);
I created a little example about the problem.
Basically when the person inserts a value into the field called "street" then as you can expect from the code it activates behavior and runs the method onEvent(). onEvent() there will be print out of variable address. Unfortunately address.street value is NULL. So it prints out "Street: NULL".
But when the person clicks on the ajax button, which submits the data, then Wicket loads all the data from the form through AddressModel into address variable. In there the end result will be for example "Street: Bond street".
My question is that how I could init the process of saving data into the address variable in AjaxEventBehavior case?

Use AjaxFormComponentUpdatingBehavior which will submit the component's value.

Related

Call several different JavaScript within AjaxLink one after the other

When I click on an AjaxLink, I would like to have a validation via JavaScript on the client side first (because the LocalStorage is queried) and then depending on the result, further JavaScript calls are made. How can i achieve this?
In a pseudo code it would look like this:
new AjaxLink<>("myId", myModel) {
#Override
public void onClick(AjaxRequestTarget target) {
boolean isCounterValid = target.appendJavaScript(checkCounter()); // i know that this is not possible, therefore pseudo code
if(isCounterValid) {
target.appendJavaScript(someOtherJavaScript());
}
else {
target.appendJavaScript(anotherJavaScript());
}
}
private String checkCounter() {
return "var count = window.localStorage.getItem('myCounter'); return count !== 1;";
}
private String someOtherJavaScript() {
return "change something";
}
private String anotherJavaScript() {
return "change other thing";
}
};
You need to send extra request parameters with the Ajax call when the link is clicked. For that you should override updateAjaxAttributes(AjaxRequestAttributes attributes) method of AjaxLink:
#Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes)
{
attributes.getDynamicExtraParameters().add("var count = window.localStorage.getItem('myCounter'); return [{\"name\":\"count\", \"value\": count}]");
}
This way inside AjaxLink#onClick() you can read the count via:
int count = getRequest().getRequestParameters().getParameterValue("count").toInt();
AJAX components and behaviors can customize AJAX attributes overriding updateAjaxAttributes and using a custom implementation of AjaxCallListener which exposes different method to hook into the AJAX request cycle. In you case you could use AjaxCallListener#getBeforeSendHandler.
For a full introduction to this topic (with examples) see user guide:
https://ci.apache.org/projects/wicket/guide/8.x/single.html#_ajax_request_attributes_and_call_listeners

How to handle changes in a form with a model-update using Wicket and AJAX

I have a form with many input-fields and need to handle a change to any of those input-fields; so I add a AjaxEventBehavior to the form, like:
Form<MyX> myForm = new Form<>("X", getModel());
myForm.add(new AjaxEventBehavior("onchange") {
#Override
protected void onEvent(AjaxRequestTarget target) {
handleFormChange(...);
}
});
The method handleFormChange gets called everytime I change some content in the input-fields of the form. But the model is not getting updated with the new value of the changed input-field of the form.
How can I get thoose model-updates? I tried AjaxFormComponentUpdatingBehavior. It updates the model, but I cannot use it for forms, just for FormComponents.
Does anybody has an ideas how to handle that? TIA!
With AjaxFormSubmitBehavior you can submit the whole form on each change.
First for on change use the dedicated OnChangeAjaxBehavior.
Then you can use the Iterator of the form to get all children and add then add the OnChangeAjaxBehavior to all FormComponents which will call your handleFormChange() on every change like this:
for (Iterator it = form.iterator(); it.hasNext();) {
Object o = it.next();
if (o instanceof FormComponent) {
((FormComponent) o).add(new OnChangeAjaxBehavior() {
#Override
protected void onUpdate(AjaxRequestTarget target) {
handleFormChange(...);
}
});
}
}

windows phone 7 how to pass Array value from one scree to another screen

///first I have crated Popular class for storing values
public class Popular
{
public string trk_mnetid,trk_title , art_mnetid, art_name, image_url;
}
/// create popularplaylist class
public partial class PopularPlaylist : PhoneApplicationPage
{
Popular popobj = new Popular();
List<Popular> pop = new List<Popular>();
/* call json parsing it and show only "titles" in List form when i m click on perticular title i need to show details in next screen which i paser and store in popular popularplaylist class.
i use navigationservice call new screen
*/
NavigationService.Navigate(new Uri("/Popular_Module/PopularPlaylist.xaml", System.UriKind.Relative));
}
// plz tell me how to get list data in next screen
Use querystring.
Passing Value: In MainPage.xaml.cs add the following
The easiest way to pass a parameter is just to use a string, something like:
private void btnNavigate_Click(object sender, RoutedEventArgs e)
{
string url=String.Format("/Page1.xaml?parameter={0}",popular);
NavigationService.Navigate(new Uri(url, UriKind.Relative));
}
Getting Value: In Page.xaml.cs add the following
Note: It is important to override the OnNavigatedTo and after that you can use the NavigationContext to get the passed parameter.
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
List<string> parameterValue = NavigationContext.QueryString["parameter"];
}
Another popular syntax to get the value of the parameter is:
List<string> parameter = string.Empty;
if (NavigationContext.QueryString.TryGetValue("parameter", out parameter))
{
//do something with the parameter
}

Wicket - How to reload/refresh reusable components correctly?

I have a java class:
public Task {
private int id;
private Company sender;
private Company receiver;
//Getter and Setter
...
}
As you can see, I have 2 other custom classes in the task class. And a company has for example Adress and Directory.
I have a CompanyPanel which will reusable be used on the Page. Here is some code from the panel.
public class CompanyPanel extends Panel {
protected List<Company> companies;
public CompanyPanel(String id, IModel<Company> model) {
super(id,new CompoundPropertyModel<Company>(model));
companies = new ArrayList<Company>();
Company company_1 = new Company();
//Setting default predefined values for the company, so I can select it from the dropdown and to set fields automatically
company_1.setFtpAdress("adress1.com");
company_1.setFtpDir("/MusterDir/");
companies.add(company_1);
//SAME for another company
...
companies.add(comany_2);
...
final DropDownChoice<Company> companyList = new DropDownChoice<Company>("companies", model,
new LoadableDetachableModel<List<Company>>() {
#Override
protected List<Company> load() {
return companies;
}
}){
protected boolean wantOnSelectionChangedNotifications() {
return true;
}
};
add(companyList);
final TextField<String> ftpAdress = new TextField<String>("ftpAdress");
ftpAdress.setOutputMarkupId(true);
add(ftpAdress);
final TextField<String> ftpDir = new TextField<String>("ftpDir");
ftpDir.setOutputMarkupId(true);
add(ftpDir);
//added Ajax to dropdown to update textfields automatically, based on selection of dropdown
companyList.add(new AjaxFormComponentUpdatingBehavior("onchange")
{
#Override
protected void onUpdate(AjaxRequestTarget target)
{
target.add(ftpAdress);
target.add(ftpDir);
}
});
}
}
In the Page I use reuseable CompanyPanels.
...
CompanyPanel senderPanel = new CompanyPanel("senderPanel", new PropertyModel(task,"sender"));
senderPanel.setOutputMarkupId(true);
form.add(senderPanel);
CompanyPanel receiverPanel = new CompanyPanel("receiverPanel", new PropertyModel(task,"receiver"));
receiverPanel.setOutputMarkupId(true);
form.add(receiverPanel);
...
When I submit the form I do:
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
//doSomething
target.add(senderPanel);
target.add(receiverPanel);
}
The problem: The company panel is not being rerendered. And I don't really know why.
Workflow:
I select a company from the dropdown panel
The TextFields(which are inside the companyPanel) will be set correctly, based on the dropdown
I modify a textField (which belongs to a company)
I submit the form
I change the company from the dropdown list
I change back to the first company -> PROBLEM: the modified textfields displays still the modified text inside. It was not reseted to the default values.
Any help very appreciated.
Of course they will display the modified values. You create a list of companies in the CompanyPanel constructor. When you modify a company's data, the object is modified inside that list.
A quick way to fix this would be to replace the CompanyPanel panel with a new instance of CompanyPanel in your onSubmit method. That would recreate the list of companies with your default values. You would of course lose the modified values.
Another possibly better fix is to move the companies list creation into the loadabledetachablemodel:
final DropDownChoice<Company> companyList = new DropDownChoice<Company>("companies", model,
new LoadableDetachableModel<List<Company>>() {
#Override
protected List<Company> load() {
List<Company>companies = new ArrayList<Company>();
Company company_1 = new Company();
//Setting default predefined values for the company, so I can select it from the dropdown and to set fields automatically
company_1.setFtpAdress("adress1.com");
company_1.setFtpDir("/MusterDir/");
companies.add(company_1);
//SAME for another company
...
companies.add(comany_2);
...
return companies;
}
This way the list of companies is recreated on every request with the default values.
Make sure you implement a proper equals() and hashCode() method in Company though for DropDownChoice to show the proper selected element though - because in this scenario the object in your model and the objects in the list may never be ==.
You have to provide more code. If you submit the correctly so that the model changes try:
senderPanel.modelChanged();
receiverPanel.modelChanged();
target.add(senderPanel);
target.add(receiverPanel);

Wicket: form submit with reusable components and AjaxButton

I'm using wicket version 6.
I have a form. as contents of the form, I have a FormComponentPanel that contains two DateTimeField's (org.apache.wicket.extensions.yui.calendar).
In the class containing the form I have one AjaxButton, and one AjaxLink, both doing the same: reading the models, creating a new object and sending it to some server for processing.
Anyhow,
when clicking on the Link my new object is created with the correct values except those newly dates selected with the datepicker
when clicking the Button I get some error ([AjaxRequestHandler#1701777932 responseObject [org.apache.wicket.ajax.AjaxRequestHandler$1#3e1]) but no further information on the error
well, I addressed the first issue (Link) with trying to add ajax update behavior to it, as suggested here , but the selected date is not updated in the model
the AjaxButton is created and onSubmit overwritten with just calling another method and target.add(form); also setOutputMarkupId is set to true, but it seems that still something is missing
In order to get it to work I'd just need to solve one of the problems, but it would be great if someone has a solution for both problems. Thanks in advance.
edit
public MyPanelIncludingForm() {
// ...
form.add(getRangePanel()); // creates a new TimeRangePanel and returns the instance
form.add(getSubmitButton());
// ...
}
private FormComponent<String> getSubmitButton() {
FormComponent<String> submitBtn = new AjaxButton("submitBtn", form) {
private static final long serialVersionUID = 3005L;
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
System.out.println("submit QT ajax button");
setResponsePage(HomePage.class);
sendQuery();
target.add(form);
}
#Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
System.err.println("error occurred. " + target);
target.add(feedback);
}
};
submitBtn.setOutputMarkupId(true);
return submitBtn;
}
// separate FormComponentModel for timeRange
public class TimeRangePanel extends FormComponentPanel<MyRange> {
MyRange range;
PropertyModel<Date> dpFromPM = new PropertyModel<Date>(this, "range.start");
PropertyModel<Date> dpToPM = new PropertyModel<Date>(this, "range.stop");
public RangePanel(String id, IModel<MyRange> model) {
super(id, model);
dpFrom = new DateTimeField("dpFrom", dpFromPM) {
private static final long serialVersionUID = 3006L;
#Override
protected DateTextField newDateTextField(String id, PropertyModel<Date> model) {
DateTextField dtf = super.newDateTextField(id, model);
AjaxFormComponentUpdatingBehavior a = new AjaxFormComponentUpdatingBehavior("onChange") {
private static final long serialVersionUID = 3006L;
#Override
protected void onUpdate(AjaxRequestTarget target) {
System.out.println("here u " + dpFrom.getModelObject().toString());
}
};
dtf.add(a);
return dtf;
}
};
// second DateTimeField as dpFrom
} // end of constructor
#Override
protected void onBeforeRender() {
range = getModelObject();
super.onBeforeRender();
}
} // end of class
edit2
this is what the wicket ajax debug window is printing:
INFO: focus removed from
INFO: focus set on submitBtn11
INFO: Received ajax response (299 characters)
INFO:
<div wicket:id="feedbackQuery" class="feedback" id="feedbackQuery1c"><wicket:panel>
<ul wicket:id="feedbackul" class="feedbackPanel">
<li wicket:id="messages" class="feedbackPanelERROR">
<span wicket:id="message" class="feedbackPanelERROR"></span>
</li>
</ul>
</wicket:panel></div>
INFO: returned focused element: [object HTMLInputElement]
INFO: returned focused element: [object HTMLInputElement]
INFO: Response processed successfully.
INFO: refocus last focused component not needed/allowed
INFO: focus removed from submitBtn11
edit3
As I wrote in a comment:
I removed the re-usable components (FormComponentPanel) and now I don't get an error with the AjaxButton . anyhow, it's weird, I thought re-usable components should work, even with Ajax; also the models were assigned properly.
when clicking the Button I get some error
([AjaxRequestHandler#1701777932 responseObject
[org.apache.wicket.ajax.AjaxRequestHandler$1#3e1]) but no further
information on the error
=> You should run Wicket in DEVELOPMENT mode to get a more detailed trace.
You might simply add in your form a field called:
range.start
range.stop
and use the Object MyRange as property model instead create a new one for each field.
There is actually no need for that extra cycle. And I don't think Wicket will write the information back to the MyRange object if you create new PropertyModels for every attribute.
For example: http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/admin/users/UserForm.java?view=markup
Line 276
and the corresponding HTML
http://svn.apache.org/viewvc/incubator/openmeetings/trunk/singlewebapp/src/org/apache/openmeetings/web/components/admin/users/UsersPanel.html?view=markup
Line 82
Sebastian

Resources