Gregory Kalabin
Gregory Kalabin

Reputation: 1788

Redirect with anchor in play 2

I'm looking for possibility to add anchor to url returned in controller:

public static Result open(String id) {
  // here I want to add acnhor like #foo to the produced url
  return redirect(routes.MyPage.show(id));
}

I found that it was possible in play 1 using addRef method, but I couldn't find any replacement of the method in play 2.

Of course I can use concatenation like:

public static Result open(String id) {
  // here I want to add acnhor like #foo to the produced url
  return redirect(routes.MyPage.show(id).url + "#foo");
}

But it seems ugly.

Thank you for any help! Have a good day!

Upvotes: 1

Views: 1093

Answers (2)

Ceasar
Ceasar

Reputation: 23083

As of Play 2.4, it's possible to use Call.withFragment().

routes.Application.index.withFragment("some-id").absoluteURL(request)

This was added by PR #4152.

Upvotes: 3

Andy Petrella
Andy Petrella

Reputation: 4345

Before trying to answer that question. I should recommend you change whatever behavior you're currently setting.

Because, an URL fragment's purpose is client side only. Such fragment is never sent to the server, so that it's cumbersome to do the opposite.

However, here is the embryo of a (quite?) elegant solution that you could follow.

What I'll try to do is to leave the browser deal with the fragment, in order to keep potential behaviors (f.i. go to ID or even deal with history...).

To do so, you could add an implicit parameter to your main template which will define the fragment that the URL should have:

@(title: String)(content: Html)(urlFragment:Option[UrlFragment] = None)

As you can see I wrapped the parameter in an Option and default'ed it to None (in order to avoid AMAP pollution).

Also, it simply wraps a String but you could use String alone -- using a dedicated type will enforce the semantic. Here is the definition:

case class UrlFragment(hash:String)

Very simple.

Now here is how to tell the browser to deal with it. Right before the end of the head element, and the start of body, just add the following:

@urlFragment.map { f =>
  <script>
    $(function() {
      //after everything is ready, so that other mechanism will be able to use the change hash event...
      document.location.hash = "@Html(@f.hash)";
    });
  </script>
}

As you can see, using map (that is when the urlFragment is not None) we add a script block that will set the hash available in urlFragment.

This might be a start, however... Think about another solution for the whole scenario.

Upvotes: 3

Related Questions