In a wicket application, I have two dependent dropdowns using Select2. Now, I want to set the default value of both dropdowns. The default value should be the first element of the choiceList.
Second dropdown's default value should be updated accordingly if I select other option from the choice in the first dropdown.
I have used Placeholder but didn't succeed. How can I update the placeholder value dynamically?
I tried the below code but the second dropdown's default value is not updating automatically.
private static class ValueEditor extends Select2Choice<String> {
private static final long serialVersionUID = SingleFiniteValueEditor.serialVersionUID;
ValueEditor(String id, EditableSingleFiniteModel<?> model, ChoiceProvider<String> provider) {
super(id, model.valueModel(), provider);
setOutputMarkupId(true);
getSettings().setDropdownAutoWidth(true);
getSettings().setCloseOnSelect(true);
getSettings().setPlaceholder("");
getSettings().setAllowClear(!model.mandatory());
if(!model.choices().getObject().isEmpty()) {
model.valueModel().setObject(model.choices().getObject().get(0));
}
}
#Override
protected void onInitialize() {
super.onInitialize();
add(new OnChangeAjaxBehavior() {
private static final long serialVersionUID = SingleFiniteValueEditor.serialVersionUID;
#Override
protected void onUpdate(AjaxRequestTarget target) {
target.add(getComponent().getParent());
target.prependJavaScript(JQuery.execute("$('#%s').select2('destroy');", getJquerySafeMarkupId()));
target.appendJavaScript(JQuery.execute("$('#%s').select2('focus');", getJquerySafeMarkupId()));
send(getComponent(), Broadcast.BUBBLE, new ValueChangedEvent());
}
});
// FIXME append a class and style in stylesheet?
add(AttributeModifier.append("style", "min-width:200px;"));
}
#Override
protected void onComponentTag(ComponentTag tag) {
tag.setName("select");
super.onComponentTag(tag);
}
}
I am new to the wicket framework so please help me with this problem.
First, two dropdowns are dependent dropdowns as shown in the fig enter image description here. Second dropdown's choice list is depend on first dropdown's selected value.
Related
Other SO answers suggest overriding ApplicationServlet.writeAjaxPageHtmlHeader, but I cannot find those classes and methods in Vaadin 8.
I cannot find anything similar in com.vaadin.server.VaadinServlet or com.vaadin.ui.UI.
There is the #JavaScript annotation, but if I put that on my UI class, the script would be loaded for every page of my application. I need it only on one specific page.
The initial HTML page is called bootstrap page in Vaadin. There is some documentation that hints you to right direction in Book of Vaadin.
In Vaadin 8, you need to add BootstrapListener to session. You can get created sessions by adding SessionInitListener in VaadinServlet.
Register Session
This example is using Vaadin with Spring Boot but the same principle applies when not using Spring Boot.
#Component("vaadinServlet")
#WebServlet(urlPatterns = "/*", name = "BootstrapVaadinServlet", asyncSupported = true)
#VaadinServletConfiguration(ui = BoostrapUi.class, productionMode = false)
public class BootstrapVaadinServlet extends SpringVaadinServlet {
private static final Logger logger = LoggerFactory.getLogger(BootstrapVaadinServlet.class);
#Override
protected void servletInitialized() throws ServletException {
super.servletInitialized();
getService().addSessionInitListener(this::addBoostrapListenerOnSessionInit);
}
private void addBoostrapListenerOnSessionInit(SessionInitEvent sessionInitEvent) {
sessionInitEvent.getSession().addBootstrapListener(new AppBootstrapListener());
}
}
Implement html head tag modification
public class AppBootstrapListener implements BootstrapListener {
#Override
public void modifyBootstrapFragment(BootstrapFragmentResponse bootstrapFragmentResponse) {
}
#Override
public void modifyBootstrapPage(BootstrapPageResponse res) {
Elements headTags = res.getDocument().getElementsByTag("head");
Element head = headTags.get(0);
head.appendChild(metaExample(res.getDocument()));
}
private Node metaExample(Document document) {
Element meta = document.createElement("meta");
meta.attr("author", "Me");
return meta;
}
}
If using add-on is ok, try HeaderTags
Overview
Using this add-on, you can define tags to add to the host page by
adding annotation to your UI class.
Sample from add ons usage example
#MetaTags({
// Replaces the Vaadin X-UA-Compatible header
#Meta(httpEquiv = "X-UA-Compatible", content = "hello"),
#Meta(name = "test", content = "test") })
// And showing how to create a link tag as well
#Link(rel = "foobar", href = "about:blank")
public class DemoUI extends UI {
...
}
We have been using the CheckBoxSelectionModel in a Grid of GXT. We want to have a particularly checkbox of some row to be checked and disabled, that is, the checkbox of CheckBoxSelectionModel will be selected and grayed-out, and user couldn't select or deselect it.
CheckBoxSelectionModel sm = new CheckBoxSelectionModel<ModelData>();
ColumnConfig checkBoxColumn = sm.getColumn();
checkBoxColumn.setStyle("vertical-align: middle;");
checkBoxColumn.setRenderer(new GridCellRenderer<ModelData>()
{
#Override
public Object render(ModelData model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<ModelData> store, Grid<ModelData> grid)
{
// if the code property of model is 1 then select and disable it
if (model.get("code").equals(1))
{
sm.select((BaseModel) model, true);
return "<div> </div>";
} else { // others case
return "<div class=\"x-grid3-row-checker\"> </div>";
}
}
});
columnConfigs.add(checkBoxColumn);
We have tried the above code from this link suggested, but this will hide the checkbox which is not what we needed.
Don't know if there has any other more properly way to disable the checkbox of the CheckBoxSelectionModel?
Any help is appreciated.
CheckBoxSelectionModel sm has boolean locked property which takes one argument. So in renderer set either value you want;
DOC:
True to lock the selection model. When locked, all selection changes are disabled.
#param locked true to lock
sm.setLocked(true) or sm.setLocked(false)
Hey when I run my program, I want to dynamically add Panels to the mainpage and therfore work with "setVisible(boolean)".
But not I get the error:
ERROR: Cannot bind a listener for event "click" on element "institutCheck7" because the element is not in the DOM
In the Ajax Debugger.
I saw that it has something to do with the visibility in this
post, but I didn't get what I have to do, it says, that this is being resolved in Wicket 7, but I'm still running 6.20.
adminUIForm.add(myPanel= new MyPanel("myPanel", allThings));
myPanel.setOutputMarkupId(true);
myPanel.setVisible(false);
//Note: Setting the OutputMarkupId allows actions such as setting components in/visible
List<IColumn<ContactInfo, String>> columns = new ArrayList<IColumn<ContactInfo, String>>();
columns = initializeColumns(columns);
DataTable<ContactInfo, String> datatable = new DataTable<ContactInfo, String>("datatable", columns, provider, 10){
private static final long serialVersionUID = 1L;
#Override
protected Item<ContactInfo> newRowItem(final String id, final int index,
final IModel<ContactInfo> model) {
Item<ContactInfo> rowItem = new Item<ContactInfo>(id, index, model);
rowItem.add(new AjaxEventBehavior("onclick") {
private static final long serialVersionUID = 1L;
#Override
protected void onEvent(AjaxRequestTarget target) {
System.out.println("click");
myPanel.setSelectedKontakt(model);
myPanel.setVisible(true);
target.add(myPanel);
}
});
return rowItem;
}
};
setTableProperties(datatable);
adminUIForm.add(datatable);
}
I override the newRowItem method to add an onClick event. I get "click" in the console each time I hit a column, but I get this error log:
ERROR: Wicket.Ajax.Call.processComponent: Component with id [[institutTablePanel6]] was not found while trying to perform markup update. Make sure you called component.setOutputMarkupId(true) on the component whose markup you are trying to update.
ERROR: Cannot bind a listener for event "click" on element "institutCheck7" because the element is not in the DOM
ERROR: Cannot bind a listener for event "click" on element "cont8" because the element is not in the DOM
ERROR: Cannot bind a listener for event "click" on element "institutCheck9" because the element is not in the DOM
ERROR: Cannot bind a listener for event "click" on element "conta" because the element is not in the DOM
ERROR: Cannot bind a listener for event "click" on element "institutCheckb" because the element is not in the DOM
ERROR: Cannot bind a listener for event "click" on element "contc" because the element is not in the DOM
ERROR: Cannot bind a listener for event "click" on element "institutCheckd" because the element is not in the DOM
ERROR: Cannot bind a listener for event "click" on element "conte" because the element is not in the DOM
Those error all bind with components in "myPanel", I don't know how to resolve this. If I set it to visible earlier I get the same problem, including all elements, which will be hidden later in the workflow.
Edit:
public class MyPanel extends Panel {
private static final long serialVersionUID = 1L;
private Form<Void> institutForm = new Form<Void>("institutForm");
private ListView<Institut> listView;
private IModel<ContactInfo> selectedKontakt;
private Set<Institut> allInstitut;
#Override
protected void onModelChanged() {
//TODO maybe here
super.onModelChanged();
}
public InstitutTablePanel(String id, final Set<Institut> allInstitut) {
super(id);
this.allInstitut = allInstitut;
this.add(institutForm);
List<Institut> allInstitutList = new ArrayList<Institut>(allInstitut);
institutForm.add(listView = new ListView<Institut>("listView", allInstitutList) {
private static final long serialVersionUID = 1L;
protected void populateItem(final ListItem<Institut> item) {
final IModel<Boolean> checked = Model.of(Boolean.FALSE);
final IModel<String> expandState = Model.of("+");
#SuppressWarnings("unused")
final Label institutLabel;
final Institut institut = item.getModelObject();
// Define variables which concern only one item in populateItem
final WebMarkupContainer div = createMarkUpContainer("cont");
final WebMarkupContainer container = createMarkUpContainer("container");
container.setEnabled(false);
compareInstitute(checked, institut, container);
item.add(container);
div.add(new AjaxEventBehavior("onclick") {
private static final long serialVersionUID = 1L;
#Override
protected void onEvent(AjaxRequestTarget target) {
expandOrCollapse(expandState, container);
target.add(institutForm);
}
});
item.add(div);
div.add(new AjaxCheckBox("institutCheck", checked) {
private static final long serialVersionUID = 1L;
#Override
protected void onUpdate(AjaxRequestTarget target) {
//Not Important for this
target.add(institutForm);
}
});
container.add(new ErhebungMatrixPanel("erhebungMatrix", institut, selectedKontakt));
container.setVisible(false);
div.add(institutLabel = new Label("institutLabel", new PropertyModel<Institut>(institut, "langName")));
}
});
listView.setOutputMarkupId(true);
listView.setReuseItems(true);
institutForm.setOutputMarkupId(true);
}}
I edited my setSelectedKontakt method like this:
public void setSelectedKontakt(IModel<ContactInfo> model) {
this.selectedKontakt = model;
modelChanged();
}
to trigger the change if necessary.
The problem is target.add(myPanel); won't trigger populateItem again.
The error message says it pretty clearly and a look into the DOM tells that the markup for the panel is not there. Thats because setVisible(false) doens't even render the component with CSS display: none; as expected. It's just not there so it can't be modified afterwards. But you can tell Wicket to render a placeholder instead with setOutputMarkupPlaceholderTag(true). Wicket then creates an invisible markup e.g. <span style="display: none;" id="mypanel1a"></span>, which then is swaped with the real component when setting the visiblity to true later.
Just a tip to those that do get this error that a common mistake is to use:
<wicket:container wicket:id="panel"/>
...instead of...
<div wicket:id="panel"/>
...for where you put the panel. The method call setOutputMarkupId will not inform you that it is unable to add an id to a wicket:container, and hence your target.add(panel) will also fail.
Description: In my mainActivity class I have added one header and ribbon with text and send it to other secondActivity class to add some more rows (by setting onclick listeners) by using addRow(rootLayout, length,buttonHeight). My requirement is, If we click on any of the row which we added in secondActivity class, I have to change the ribbon text which we added in the mainActivity class.
Could any one please help out of this?
code:
MainActivity.java
-----------------
/*Main Activity Class which consists ribbon text and called method for creating the second row*/
public class MainActivity extends Acitvity{
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.mainView); **//Main view**
final FrameLayout rootLayout = (FrameLayout)findViewById (R.id.mainViewRootLayout);
FrameLayout ribbonLayout = (FrameLayout)findViewById(R.id.mainribbonLayout);
TextView ribbonText = (TextView)findViewById(R.id.mainribbonLayoutText);
ribbonText.setText("MainRibbonViewBeforeClick");
LayoutInflater inflater = (LayoutInflater)getSystemService (context.Layout_Inflater_service);
addRow(rootLayout);
}
}
/*Here is the calling method in same class which adds one more text view, if we click on text view the ribbon text of oncreate method has to be changed*/
public void addRow(FrameLayout rootLayout)
{
Rect rect = new Rect();
rootLayout.getDrawingRect(rect);
FrameLayout ribbonLayout = (FrameLayout)findViewById(R.id.subRibbonLayout);
TextView subText = (TextView)findViewById(R.id.subribbonLayoutText);
subText.setText("ClicktoChangeTheRibbon");
subText.setOnclickListener(new onClickListener() **//Setting up the listener
{
public vid onclick(View v){
/*Here I need to implement a code that changes the ribbon text which I have added in onCreate method*/
}
});
}
}
Please have a look on the above code and suggest me the solution.
Create a static variable assign the text value of the ribbon to it.On the clickevent of any rows in the secondActivity class change the value of the variable to the value you want to display for the ribbon text.
I have a Web Part that dynamically inserts div tags written in VS2010 using C#. I want to implement mouseover events for these div's. When the Web Part is deployed onto SP2010, my JavaScript is not able to find these div's when I just search for them with the control id that I have specified.
When I checked the page source, I found that some tags like ct100_m_g_ are prefixed to the control id that I have specified.
How can I guess these ids?
The ctlxxx stuff is automatically prepended to the control's ID by ASP.NET, to generate the client ID.
If you want to set a deterministic client ID, you can set the ClientID property instead of the ID property. See http://msdn.microsoft.com/en-us/library/system.web.ui.control.clientid.aspx
In webparts you can use the client ID to find your controls in javascript. Take a look at this example and it will become clear:
using System;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
namespace MyDemo.WebParts
{
public class MyWebPart : WebPart
{
private TextBox txtInput;
private TextBox txtOutput;
private Button btnDoSomething;
protected override void CreateChildControls()
{
base.CreateChildControls();
txtInput = new TextBox();
Controls.Add(txtInput);
txtOutput = new TextBox();
txtOutput.ReadOnly = true;
Controls.Add(txtOutput);
btnDoSomething = new Button();
btnDoSomething.Text = "Do Something";
btnDoSomething.OnClientClick = string.Format("DoSomething('{0}', '{1}'); return false;", txtInput.ClientID, txtOutput.ClientID);
Controls.Add(btnDoSomething);
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
// Check if the script is already registered, this is necessary because the webpart can be
// added multiple times to the same page
if (!Page.ClientScript.IsClientScriptBlockRegistered("MyWebPartScript"))
{
StringBuilder sb = new StringBuilder();
sb.Append("function DoSomething(inputControlID, outputControlID){");
sb.Append(" var inputControl = document.getElementById(inputControlID);");
sb.Append(" var outputControl = document.getElementById(outputControlID);");
sb.Append(" outputControl.value = inputControl.value;");
sb.Append("}");
Page.ClientScript.RegisterClientScriptBlock(GetType(), "MyWebPartScript", sb.ToString(), true);
}
}
protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
{
EnsureChildControls();
writer.Write("<table>");
writer.Write("<tr><td>");
txtInput.RenderControl(writer);
writer.Write("</td><td>");
txtOutput.RenderControl(writer);
writer.Write("</td></tr><tr><td colspan=\"2\">");
btnDoSomething.RenderControl(writer);
writer.Write("</td></tr></table>");
}
}
}
You could give each of your DIVs a class when generating them. THen, just use the class name to select them and add the event handler.