beeCoder
beeCoder

Reputation: 485

Update one Wicket Panel from clicking an item in another Wicket Panel

I have looked at many update Panel answers in SO but could not solve my problem. It is very straight forward and I don't know why I dont get the panel updated.

I have two panel created in the RadioChoicePage.java:

public class RadioChoicePage extends ApplicationPageBase{

    private static final long serialVersionUID = 1L;

    public TestPanel tp;

    public static TextPanel txp;

    public RadioChoicePage(){

    tp = new TestPanel("testPanel");
    txp = new TextPanel("textPanel");

    txp.setMsg("Before");

    add(tp);
    add(txp);

    }

}

The markup file looks like the following:RadioChoicePage.html

<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" >
<body>
    <wicket:extend>

        <div wicket:id="testPanel" style="position:absolute; left:10px ; width:50%; z-index:10;">
        </div> 
        <div wicket:id="textPanel" style="position:absolute; left:450px; width:50%; z-index:5">
        </div>

    </wicket:extend>
</body>
</html>

The two panel are TestPanel.java and TextPanel.java. I have a TestPanel.js file adding svg using d3.js and clicking on a circle I want to update the text panel.

I am able to call the wicket method from javascript and print that the circle was clicked on the console. But I am not able to update the text Panel.

Below is the code for TestPanel.java, TestPanel.html, TestPanel.js , TextPanel.java and TextPanel.html.

TestPanel.java

public class TestPanel extends Panel{

    public static final JavaScriptResourceReference TEST_JS = new JavaScriptResourceReference(
            TestPanel.class, "TestPanel.js");

    TextPanel ttxp = new TextPanel("textPanel");

    public TestPanel(String id) {
        super(id);

        final AbstractDefaultAjaxBehavior behave = new AbstractDefaultAjaxBehavior() {

            private static final long serialVersionUID = 1L;

            public void renderHead(Component component,IHeaderResponse aResponse){
                super.renderHead(component, aResponse);

                String componentMarkupId = component.getMarkupId();
                String callbackUrl = getCallbackUrl().toString();

                aResponse.render(JavaScriptReferenceHeaderItem.forReference(TEST_JS));
                aResponse.render(JavaScriptReferenceHeaderItem.forReference(D3Reference.D3_JS));

                aResponse.render(OnDomReadyHeaderItem.forScript("draw(" + componentMarkupId  + ",\"" + callbackUrl + "\")"));

            }   

            protected void respond(final AjaxRequestTarget target) {
                //target.add(new Label("msg", "Yeah I was just called from Javascript!"));
                System.out.println("I was succesfully clicked");
                ttxp.setMsg("After");
                target.add(ttxp);
            }

        };
        add(behave);
    }

}

TestPanel.html

<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" >
  <head>
    <wicket:head>
    </wicket:head>
  </head>
  <body>
    <wicket:panel>
    <div id="chart" style="position:absolute; width:400px; height:400px; border:2px solid blue;"></div>
    </wicket:panel>
  </body>
</html>

TestPanel.js

function draw(componentMarkupId,callbackUrl){

            console.log(" Draw is called!");

            //Width and height
            var w = 300;
            var h = 100;

            //Data
            var dataset = [ 5, 10, 15, 20, 25 ];

            //Create SVG element
            var svg = d3.select("#chart")
                        .append("svg")
                        .attr("width", w)
                        .attr("height", h);

            var circles = svg.selectAll("circle")
                .data(dataset)
                .enter()
                .append("circle");

            circles.attr("cx", function(d, i) {
                        return (i * 50) + 25;
                    })
                   .attr("cy", h/2)
                   .attr("r", function(d) {
                        return d;
                   })
                   .attr("fill", "red")
                   .attr("stroke", "orange")
                   .attr("stroke-width", function(d) {
                        return d/2;
                   });

            circles.on("click",function(d){
                  this.style.stroke = "steelblue";
                  $(function() {
                      var wcall = Wicket.Ajax.get({ u:callbackUrl });
                      //var wcall = wicketAjaxGet('$callbackUrl$'); 
                      alert(wcall);
                  });
            });
}

TextPanel.java

public class TextPanel extends Panel{

    String msg;

    boolean initialize = true;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public TextPanel(String id) {
        super(id);
        // TODO Auto-generated constructor stub

        System.out.println(getMsg());

        if(initialize){
            setMsg("Before");
            initialize = false;
        }

        Label mmsg = new Label("msg", getMsg());
        add(mmsg);

        setOutputMarkupId(true);
    }
}

TextPanel.html

<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" >
  <head>
    <wicket:head>
    </wicket:head>
  </head>
  <body>
    <wicket:panel>
     <div wicket:id="msg" style="border: 2px solid blue;"></div>
    </wicket:panel>
  </body>
</html>

Please do give me a solution with explanation. As I have read so many solutions and explanations on SO and other resources but I feel im missing something basic here.

You can copy the code exactly and run it to check whats the real problem. I do not get any errors but Panels simple dont get updated.

Thank you for taking time to read this huge question with a small problem.

Upvotes: 1

Views: 2304

Answers (1)

svenmeier
svenmeier

Reputation: 5681

RadioChoicePage's textPanel should not be static, otherwise the component will be shared between multiple sessions:

public TextPanel txp;

Why is TestPanel creating its own instance of TextPanel?

TextPanel ttxp = new TextPanel("textPanel");

Remove that! Add a hook method to TestPanel instead:

protected void onClicked(AjaxRequestTarget target) {
}

final AbstractDefaultAjaxBehavior behave = new AbstractDefaultAjaxBehavior() {

   protected void respond(final AjaxRequestTarget target) {
       onClicked(target);
   }
}

Let RadioChoicePage decide what to do when anything is clicked:

tp = new TestPanel("testPanel") {
    protected void onClicked(AjaxRequestTarget target) {
        target.add(txp);
    }
};
txp = new TextPanel("textPanel");
txp.setOutputMarkupId(true);

Upvotes: 2

Related Questions