Java custom tag with JS - java

I have custom tag which contains form with text input and submit. I want to validate this text input using JS, so my custom tag output should look like:
<script type="text/javascript">
function validate(form) {
var text = form.textInput;
// validation code
}
</script>
<form onsubmit='return validate(this);'>
<input type='text' name='textInput'/>
<input type='submit'/>
</form>
(Note, this code simplified!)
My problem appears when I want to use this tag twice or more times at page - I want to print form at page again, but not JS validation code! Validation code must be unique at the page. How can I archive that? My custom tag extends javax.servlet.jsp.tagext.TagSupport

I found the most suitable solution for me.
Class javax.servlet.jsp.tagext.TagSupport contains protected field pageContext which presents... page context! I can easily access context attributes of javax.servlet.jsp.PageContext. So, I put next code in my custom tag:
public int doStartTag() throws JspException {
if (pageContext.getAttribute("validated") == null) {
// validation code writing
pageContext.setAttribute("validated", true);
}
...
}
If condition would be reachable only once per page rendering.
Hope it would be useful for someone.

I suggest you to try to embed that JavaScript function in some .js file an import that file. If you don't want to do that, for some reason you should try to define that function dynamically, if it is not defined:
if (typeof window.validateMyForm === 'undefined') {
window.validateMyForm = function(form) {
var text = form.textInput;
// validation code
}
}
As you guess this should define function only if it is not already defined.
First answer is correct, but that means that programer must know where in code are already inserted custom tags and according to that this whether to set that parameter to true or false. And what about code changes, you will have to always go thought whole page and revise all used tags on a page.

Make the custom tag to accept a parameter that toggles the validation on or off, and of course have it generate different code depending on the value of the parameter.

Related

Call a Javascript function from a JSP Servlet forward

What I'm trying to do today is to directly call a Javascript function from a JSP Servlet response. What does that mean? Here's the code:
Servlet, This is contained in myServlet.java
// Takes an XML already previously parsed as a string as input
CharSequence confirm= "something";
if (xml.contains(confirm)) {
// Carry on
// If it is contained we needn't go further
} else {
// "couldn't find confirms content
errorMessage = "Does not contain confirm";
// "If ^ quit this servlet"
request.setAttribute("rol", this.rol);
request.setAttribute("user", this.user);
request.setAttribute("errorMessage", errorMessage);
forwardToJSP(request, response, "/myJSP.jsp");
}
Now In Javascript I already have defined a function I want to be called. It is something along these lines:
Javascript, This is contained in myJSP.jsp
<script language="JavaScript" type="text/JavaScript">
// Assume all document.getElementById calls are properly implemented,
// they call real variables that exist elsewhere, but not shown
// here due to irrelevance.
window.errorExists = function() {
var errorExists = document.getElementById("terror");
errorExists.setAtribute("terror", "Does not contain confirm");
if (errorExists.attributes == "Does not contain confirm"){
if(confirm("Cannot find content, do you wish to add it?")){
anotherFunctionCall();
} else {
// Don't do anything
}
}
}
</script>
Now, in simple terms what I want to do is to call my Javascript function from the aforementioned JSP. I think cannot do so with work arounds such as:
PrintWriter out = response.getWriter();
out.println("<tr><td><input type='button' name='Button' value='Search' onclick=\"searchRecord('"+ argument + "');\"></td></tr>");
Because the other function wouldn't be called, also there's an update to Javascript variables.
How would one go around this?
Any and all help is greatly appreciated.
You can call that method in onload parameter of body of JSP page.
As you are already calling a JSP page using Forward method, your JSP page is getting loaded when you call it. You can call your method in body tag of JSP page as follows:
<body onload="YourMehodName()">
alternatively, you can put this script at the bottom of your JSP which will get called on loading of your page.

Collect user input in Servlet and return at the same point to continue program: Java

I have a web application in Java that performs title matching.
The Servlet is the controller and in one of the methods of the Servlet, I am comparing two list of titles. The first list is in a HashMap and the second is from a query ResultSet.
What I want to do is to automatically match those with same title and give the user the option to confirm the ones with some similarities (business logic). Basically, I need to get user input and then return at the same point to continue.
I tried JOptionPane dialog box and it didn't work.
Now I am trying to forward to another HTML page to get user input and then return to the Servlet.
Below is the Servlet code:
while (Querylist.next()) {
String title = Querylist.getString(1).trim().toLowerCase();
if (MyMap.containsKey(title))
{
// confirm match
} else
{
//some title2 is like title
request.setAttribute("Title1", title);
request.setAttribute("Title2", title2);
RequestDispatcher view = request.getRequestDispatcher("TitleMatch.jsp");
view.forward(request, response);
ResultMatch= request.getParameter("ResultMatch");
if (ResultMatch.equals("YES"))
{
// confirm match
}
}
}
HTML Page:
<B> <%= request.getAttribute("Title1")%></B>
<B> <%= request.getAttribute("Title2")%></B>
<FORM method="get" action="DataMerge">
<input type = "radio" name="MatchResult" value="YES" /> YES
<input type = "radio" name="MatchResult" value="NO" checked/>NO
<button type = "submit" formaction="DataMerge" > <b>CONFIRM</b>
</FORM>
EDIT: the loop works and I'm having a java.lang.IllegalStateException Exception.
Does anyone can help to figure out how to do that efficiently in plain Java?
I searched all over SO and haven't found something similar. Thanks in advance.
You might want to reconsider your approach as there are number of fundamental problems with the code you have written. For example:
The while loop test it not correct. Assuming that you are using an Iterator then the test should be list.hasNext();
The if test is nested and incorrect. You cannot use the identifier Map as it is the name of the class, you should use the name of the map object.
If the loop worked the view.forward(request, response); would result in an java.lang.IllegalStateException exception, on the second cycle, as its not possible to resend a response.
I suggest that instead of trying to send each title pair one at a time, that you display them all (or some if there are too many) on one JSP with a yes button next to each pair and as the user clicks the yes button an AJAX call is made to another servlet that updates the database (or an array to latter be used to update the database).
There are some good tutorial about using AJAX and JSP here of SOF and in YouTube.

How do I customize the output of the <s:fieldError /> tag?

How do I get the validation messages I set using the struts2 validation:
public void validate() {
addFieldError("user", "Invalid User");
}
I want to get the "Invalid User" and "user" strings from a custom tagLib to print like:
public int doStartTag() {
pageContext.getOut().print( "Invalid User - user" )
}
UPDATE:
The example was a reduced and non-functional usage just explaining how I would like the values to be returned not exactly how I would use it, but here is the use case:
I want to create a custom tagLib that prints the error from struts validation. In a single tagLib I want to verify if the page contains a validation error for a given input then print in the screen the content of the error.
Scriptlet, <logic:*, javascript -> it is all out of question.
If the jsp is meant to hold the structure of the document a taglib with internal specific rules makes much more sense than flooding the page with logic comparisons.
I am not using <s:fieldError /> (or smth like that) because it create an ul and li structure I cant get rid of, even setting the default template as "simple"
Aleksandr M is correct. If you only want to change the markup spit out by the tag, you definitely don't want to create a tag, you only want to override the template that is rendering it. This is quite easy. You will get a copy of the template from the struts core jar, edit it, and put it in your project. Here's a link to the docs:
http://struts.apache.org/2.3.4.1/docs/template-loading.html
Note, depending on what you want to do, you could just get the error messages yourself. They are all exposed as JavaBeans properties on ActionSupport, which your actions should inherit from, and you can reach them with OGNL expressions, such as in the property tag.
Note, ActionSupport implementst these to fullfil the contract of the ValidationAware interface which it implements.

How do I inject another JSP page into a <div> when clicking a link?

I have two different divisions in a JSP page. One contains a menu of links, when clicked the div2 (id-content) loads different pages accordingly. I am doing something like -
<div id="menu">
<ul class="navbar">
<li><a name="login" href="Login.jsp" onclick="changeContent()">Login</a>
</li></div>
and in the script I have something as -
<script language="JavaScript">
function changeContent() {
document.getElementById('content').load('Login.jsp');
}
</script>
I also tried -
document.getElementById('content').innerHTML=
"<jsp:include page="Login.jsp">";
None of the ways worked. Please suggest how should I
Try jquery..
function changeContent() {
$('#content').load('Login.jsp');
}
The solution is to use Ajax, which will asynchronously retrieve your page content that can be pasted in with the innerHTML method. See my answer to a similar question of how an Ajax call works and some introductory links.
As to why your examples in your answer don't work, in the first case there is no load() method on an Element object (unless you've defined one yourself and not shown it). In the second example, as one of the question comments says, there is probably something causing a syntax error in the javascript.
As an FYI, when there is a syntax error in some javascript in a web page, the current expression being parsed and the rest of the <script></script> block will be ignored. Since this is inside a function declaration, that function will never get defined.
For instance, an embedded quote in the included page will end the string for the innerHTML assignment. Then the javascript parser will try to parse the remainder of the HTML causing a syntax error as the HTML will not be valid javascript.
We use jquery. Add a click event handler to the anchor elements. In the click handler call $('#content').load(your_url);. You might want to use the load(url, function() { ...}) version. More info here http://api.jquery.com/load/
Your initial page comes down from the server. It's displayed by the browser. When you click on a link (or a button) in the browser, you want to fill the second div with new HTML. This is is a perfect job for an AJAX request. What the AJAX object in the browser does, is to send a POST (or whatever) string to the server. And then the Ajax object receives the HTML response back from the server. And then you can display that response data which the AJAX object contains, anywhere you want.

Call a controller method within Play! template

How can I call a controller method from within a Play! template?
I have a default controller, Application, and the hasliked() method inside that controller.
The method returns whether the logged in user has liked the post ID.
It returns "none" if the user has liked the post, otherwise it returns "block" (for the CSS)
I have added the following route: GET /hasliked/{id} Application.hasliked
I tried the following:
#{list items:postList, as:'post'}
%{
display = Application.hasliked(post.id);
%}
<div style="display: ${display}">...</div>
#{/list}
But I get this error:
Template execution error
Execution error occured in template /app/views/Application/dashboard.html. Exception raised was NullPointerException : Cannot invoke method hasliked() on null object.
Try using a fully qualified name like:
controllers.Application.hasliked()
EDIT on comment:
The issue with your exception is that you are accessing the controller to get a value. That's wrong.
Controllers in Play are used to navigate. They are static, they return "void", and they do a call to another controller method or to a render method. What you try to do may have unexpected results.
What you want to do is to get the value inside the controller and pass it as a parameter:
//On controller
public static void yourRequest() {
//...
Object display = getDisplay(); //get your value
render(display);
}
//On template
<div style="display: ${display}">...</div>
That's the recommended way.
The exception you get is (most likely) caused because your Application.hasLiked() ends up with a redirect call (either render() or call to another controller's method) and that's happening while you render the page corresponding to the initial call. So it breaks.
It would probably be a better way to do fill the information that is required into the list of items instead of calling back the controller:
Your template doesn't need to know about your controllers. It should just convert data to HTML and not acquire data from somewhere else. That's the task of the controller.
It would also be more efficient in terms of database access to fetch the like status for all items at once instead of doing several calls.
When doing refactoring (e.g. renaming methods etc of your controller) the IDE cannot help you if you call controllers from the template (unless it's aware of how Play! templates work).
If you really must do this (and again, you shouldn't) you need to fully qualify the name of the controller:
controllers.Application.hasLiked()
just like Pere Villega pointed out.
An alternative to this may be to issue an AJAX call to set the style, rather than using the controller.
Set the style of your "liked" element to display: none by default, and when your view has rendered, issue an GET request to /hasliked/ with the ID as a parameter and update your CSS styles accordingly: when the user has not already liked this, output false (or whatever you want), so that you can use JavaScript to re-define the style.
The easiest way to do this would be to use jQuery to issue a request to your controller when the view has loaded. Have a look at the Play! documentation on AJAX for some inspiration. Note that you don't have to use #{jsAction /} at all - personally I find it easier to define the jQuery calls myself.
Try the following:
<script type="text/javascript" language="javascript">
var url = "#{Application.hasliked}" + "/" + yourId;
window.location.replace(url);
</script>

Categories

Resources