plamb
plamb

Reputation: 5636

Play framework write Action with Ok(...) that doesn't load new page

Play framework 2.4.x. A button is pressed on my home page that executes some code via Ajax, and returns its results beneath the button without loading a new page. The results wait for a user to input some text in a field and press "submit". Those results Look like this:

<li class="item">
        <div>
            <h3>Email: </h3>
            <a>@email.tail.init</a>
            <h3>Name: </h3>
            <a>@name</a>
        </div>
        <div>
            <h3>Linkedin: </h3>
            <form class="linkedinForm" action="@routes.Application.createLinkedin" method="POST">
                <input type="number" class="id" name="id" value="@id" readonly>
                <input type="text" class="email" name="email" value="@email" />
                <input type="text" class="emailsecondary" name="emailsecondary" value="" />
                <input type="text" class="name" name="email" value="@name" />
                <input type="text" class="linkedin" name="linkedin" value="" />
                <input type="submit" value="submit" class="hideme"/>
            </form>
        </div>
        <div>
            <form action="@routes.Application.delete(id)" method="POST">
                <input type="submit" value="delete" />
            </form>
        </div>
    </li>

Along with some jquery that slides up a li after submission:

 $(document).ready(function(){
        $(".hideme").click(function(){
               $(this).closest('li.item').slideUp();
                });
            });

However, since a form POST goes inside an Action that must a return an Ok(...) or Redirect(...) I can't get the page to not reload or redirect. Right now my Action looks like this (which doesn't compile):

newLinkedinForm.bindFromRequest.fold(
errors => {
  Ok("didnt work" +errors)
},
linkedin => {
  addLinkedin(linkedin.id, linkedin.url, linkedin.email, linkedin.emailsecondary, linkedin.name)
    if (checkURL(linkedin.url)) {
      linkedinParse ! Linkedin(linkedin.id, linkedin.url, linkedin.email, linkedin.emailsecondary, linkedin.name)
      Ok(views.html.index)
    }else{
     Ok(views.html.index)
    }
  }
)

Is it possible to return Ok(...) without redirecting or reloading? If not how would you do a form POST while staying on the same page?

EDIT: Here is my attempt at handling form submission with jquery so far:

 $(document).ready(function(){
        $(".linkedinForm").submit(function( event ) {
            var formData = {
                'id'                : $('input[name=id]').val(),
                'name'              : $('input[name=name]').val(),
                'email'             : $('input[name=email']).val(),
                'emailsecondary'    : $('input[name=emailsecondary]').val(),
                'url'               : $('input[name=url]').val()
            };

            jsRoutes.controllers.Application.createLinkedin.ajax({
                type     :'POST',
                data     : formData

            })

            .done(function(data) { 

                console.log(data);

            });

            .fail(function(data) {

                console.log(data);
            });

            event.preventDefault();
            };
        });

Upvotes: 1

Views: 1554

Answers (3)

plamb
plamb

Reputation: 5636

In order to accomplish this task, i had to use play's javascriptRouting

This question's answer helped a lot.

I'm not experienced with jquery so writing that correctly was difficult. For those that find this, here is my final jquery that worked:

 $(document).ready(function(){
        $("div#results").on("click", ".hideme", function(event) {
         var $form = $(this).closest("form");
               var id = $form.find("input[name='id']").val();
               var name = $form.find("input[name='name']").val();
               var email = $form.find("input[name='email']").val();
               var emailsecondary = $form.find("input[name='emailsecondary']").val();
               var url = $form.find("input[name='url']").val();


            $.ajax(jsRoutes.controllers.Application.createLinkedin(id, name, email, emailsecondary, url))
            .done(function(data) {
                console.log(data);
                $form.closest('li.item').slideUp()
            })
            .fail(function(data) {
                console.log(data);
            });

            });

        });

Note that my submit button was class="hideme", the div that gets filled with results from the DB was div#results and the forms were contained within li's that were class="item". So what this jquery is doing is attaching a listener to the static div that is always there:

<div id="results">

It waits for an element with class="hideme" to get clicked. When it gets clicked it grabs the data from the closest form element then sends that data to my controller via ajax. If the send is successful, it takes that form, looks for the closest li and does a .slideUp()

Hope this helps

Upvotes: 0

waterscar
waterscar

Reputation: 876

What you need is use ajax to submit a form, check this: Submitting HTML form using Jquery AJAX

In your case, you can get the form object via var form = $(this), and then start a ajax with data from the form by form.serialize()

    $.ajax({
        type: form.attr('method'),
        url: form.attr('action'),
        data: form.serialize(),
        success: function (data) {
            alert('ok');
        }
    });

Upvotes: 0

Zeimyth
Zeimyth

Reputation: 1395

This is an issue with the browser's behavior on form submission, not any of Play's doing. You can get around it by changing the behavior of the form when the user clicks submit.

You will first want to attach a listener to the form's submission. You can use jQuery for this. Then, in that handler, post the data yourself and call .preventDefault() on the event. Since your javascript is now in charge of the POST, you can process the data yourself and update your page's HTML rather than reloading the page.

Upvotes: 1

Related Questions