Frage

I have tried multiple things with no success. At the moment my code looks like this:

HomePage.html:

            <div wicket:id="text3" contenteditable="true">
            </div>

HomePage.java:

    public HomePage(final PageParameters parameters) {
//...

    AjaxEditableMultiLineLabel textArea = 
            new AjaxEditableMultiLineLabel ("text3", new PropertyModel (this, "text3") );


    textArea.add(new AjaxEventBehavior ("keyup") {

        @Override
        protected void onEvent(AjaxRequestTarget target) {
            System.out.println( "on event!" );
            System.out.println( getText3 () );
        }
    });
//...
}

/**
 * @return gets text3
 */
public String getText3() {
    return text3;
}

/**
 * @param text3
 *            the text3 to set
 */
public void setText3(String text3) {
    this.text3 = text3;
}

I want to get the content inside the "div" but it's not being updated on the ajax call. Can I force it to send it somehow?

By the way, what I'm trying to achieve is getting the plain text content of a rich text area every time this is updated, in case there is a simpler way of doing it in wicket.

War es hilfreich?

Lösung

You add an AjaxEventBehavior to a AjaxEditableMultiLineLabel that is NOT CORRECT. The AjaxEditableMultiLineLabel is a Panel that contains two components:

  • Label
  • Editor (textarea)

Any of Ajax behavior has to be add to any of these components. In your case you have to add a behavoir to the editor.

(following full working example is on https://repo.twinstone.org/projects/WISTF/repos/wicket-examples-6.x/browse )

The markup

    <h2>Form</h2>
    <form wicket:id="form">
        <div wicket:id="text"></div>
        <input wicket:id="submit" type="submit" value="Send" />
    </form>

    <hr/>

    <h2>Result</h2>
    <div wicket:id="result">[result placeholder]</div>

The code snippet

    final IModel<String> textModel = Model.of("initial text");

    Form<String> form = new Form<>("form", textModel);
    add(form);

    AjaxEditableMultiLineLabel<String> textArea = new AjaxEditableMultiLineLabel<String>(
            "text", textModel) {

        private static final long serialVersionUID = 1L;

        @Override
        protected FormComponent<String> newEditor(MarkupContainer parent,
                String componentId, IModel<String> model) {
            final FormComponent<String> editor = super.newEditor(parent,
                    componentId, model);

            editor.add(new AjaxFormComponentUpdatingBehavior("keyup") {

                private static final long serialVersionUID = 1L;

                @Override
                protected void onUpdate(AjaxRequestTarget target) {
                    System.out.println("Ajax update for textArea " + editor.getDefaultModelObjectAsString());

                }
            });

            return editor;
        }

    };

    textArea.setCols(50);
    textArea.setRows(20);

    form.add(textArea);
    form.add(new SubmitLink("submit"));

    add(new Label("result", textModel));

WARNING: PREVIOUS CODE IS REALLY VERY SLOW

The code is very slow, becuase each keypress/release makes following:

  1. Call the server with the content of textarea
  2. Invoke code on the server side (update, render, etc.)
  3. Send back the whole result tag as html in an XML response (AJAX)
  4. Replace the whole result tag

It is slow on localhost, in a real internet is definitely not usable.

SOLUTION

Use a simple jQuery updating (JavaScript, jQuery is built in Wicket 6)

The code snippet with jQuery updating

    final IModel<String> textModel = Model.of("initial text");
    final Label result = new Label("result", textModel);
    result.setOutputMarkupId(true);
    add(result);

    Form<String> form = new Form<>("form", textModel);
    add(form);

    AjaxEditableMultiLineLabel<String> textArea = new AjaxEditableMultiLineLabel<String>(
            "text", textModel) {

        private static final long serialVersionUID = 1L;

        private boolean initialized = false;

        private FormComponent<String> editor;

        @Override
        public void onEdit(AjaxRequestTarget target) {
            super.onEdit(target);
            if(!initialized) {
                String editorId = editor.getMarkupId();
                String resultId = result.getMarkupId();
                StringWriter sw = new StringWriter();
                sw.write("$('#");
                sw.write(editorId);
                sw.write("').keyup(function() { var str = $('#");
                sw.write(editorId);
                sw.write("').val(); ");
                sw.write("$('#");
                sw.write(resultId);
                sw.write("').html(str); });");
                String js = sw.toString();
                System.out.println("Appending editor JS " + js);
                target.appendJavaScript(js);
                initialized = true;
            }
        }

        @Override
        protected FormComponent<String> newEditor(MarkupContainer parent,
                String componentId, IModel<String> model) {
            editor = super.newEditor(parent, componentId, model);
            return editor;
        }

    };

    textArea.setCols(50);
    textArea.setRows(20);

    form.add(textArea);
    form.add(new SubmitLink("submit"));

Andere Tipps

You should add the components you want being updated to the AjaxRequestTarget, like this:

target.add(myComponent);

You can do this in your onEvent method, for example like this:

    @Override
    protected void onEvent(AjaxRequestTarget target) {
        System.out.println("on event!");
        System.out.println(getText3());
        target.add(textArea);
    }

On your question regarding the Model of the Rich text area, you can use an ordinary model and your code would look like this:

 public HomePage(final PageParameters parameters) {
    private Model<String> textModel;

    Model<String> textModel = Model.of("");
    AjaxEditableMultiLineLabel textArea = new AjaxEditableMultiLineLabel ("text3", textModel);


    textArea.add(new AjaxEventBehavior ("keyup") {

        @Override
        protected void onEvent(AjaxRequestTarget target) {
            System.out.println(textModel.getObject());
        }
    });
//...
}

Not much of a difference i guess, but you only use one model, instead of a String property and a model.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top