Load JSP file into Javascript to realize Fragments - javascript

I'm working with SringMVC and I'm searching for an easy solution to load a JSP into a div box of another JSP file. I heard about using Tiles but I would prefer to use ajax/jquery. Can anyone help me with that? I'm trying to get this working for two days now...
My current approach is something like this:
$(document).ready(function() {
var html = '<jsp:include page="searchSites.jsp"/>';
$('#contentbox').load(html);
});
But this is throwing an "Uncaught SyntaxError: Unexpected token ILLEGAL" Error at the second line. I also tried c:import but this isn't working, too.
Thank you very much for your help!
Edit:
#Controller
#RequestMapping("/search")
public class SearchController {
#Autowired private SiteService siteService;
#Autowired private SystemService systemService;
#RequestMapping(value = "")
public String displaySearch(Model model) {
return "displaySearch";
}
#RequestMapping(value = "sites", method = RequestMethod.POST )
public String displaySites(Model model, #RequestParam String searchStr) {
List<RSCustomerSiteViewDTO> sites = siteService.getSitesByName(searchStr);
model.addAttribute("sites", sites);
return "searchSites";
}
#RequestMapping(value = "systems", method = RequestMethod.POST)
public String displaySystems(Model model, #RequestParam String searchStr) {
List<RSServicedSystemViewDTO> systems = systemService.getSystemsByName(searchStr);
model.addAttribute("systems", systems);
return "searchSystems";
}
}
displaySearch.jsp
<html>
<head>
<title>Site</title>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<link rel="stylesheet" href="<c:url value="resources/css/style.css" />" />
<script>
$(document).ready(function() {
var html = '/crsp/search/sites';
$('#contentbox').load(html);
});
</script>
</head>
<body>
<div id="content">
<div id="searchdiv">
<form method="POST" action="search/sites">
<input type=text name=searchStr placeholder="Search Site..."
id="searchSite" class="search" />
</form>
<form method="POST" action="search/systems">
<input type=text name=searchStr placeholder="Search System..."
id="searchSystem" class="search" />
</form>
</div>
<div id="contentbox">
</div>
</div>
</body>
</html>
searchSites.jsp
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# page session="false"%>
<table>
<tr id="header">
<td>Name</td>
<td>Customer</td>
<td>City</td>
<td>Region</td>
</tr>
<c:forEach var="site" items='${sites}' varStatus="loopStatus">
<tr class="${loopStatus.index % 2 == 0 ? 'even' : 'odd'}">
<td>${site.siteName}</td>
<td>${site.customerName}</td>
<td>${site.siteCity}</td>
<td>${site.regionName}</td>
</tr>
</c:forEach>
</table>
Edit:
I came closer. I have to fire something like this from the forms instead of the action which I got until now, then it will work: Suggestions?
function searchSites(searchStr) {
$.ajax({
type: "POST",
url: "sites?searchStr=",
success: function(data) {
$("#contentbox").html(data);
}
});
}

You should remove the JSP tag
var html = 'searchSites.jsp';
$('#contentbox').load(html);

The load method should be provided with a url that corresponds with a mapping to one of your controller methods.
Controller
#Controller
#RequestMapping("/site")
public class MyController{
#RequestMapping("/search")
public String getFragment(){
return "fragment";
}
}
Javascript
$(document).ready(function() {
var html = "/contextRoot/site/search"; //you may need to use jstl c:url for this
$('#contentbox').load(html);
});
Config
Please note this example, assumes you have a ViewResolver setup in your dispatcher configuration file as follows and there is a fragment.jsp file within the root of your WEB-INF directory:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/" />
<property name="suffix" value=".jsp" />
</bean>
The basic concept of request handling in Spring MVC is that a request is "somehow" mapped to a controller method. Spring MVC provides various ways of doing this url, request type, parameter presence, parameter values, etc... But basically it boils down to which controller/method should handle this request. This is most often accomplished using #RequestMapping.
After the method is found data binding occurs, meaning that request parameters are supplied to the method as arguments. Once again there are various ways to match parameters to arguments, including path variables, modelattributes, etc...
Next the body of the method is executed, this is pretty much custom and you provide the implementation.
The next part is where you seem to be getting stuck. The controller method next tells Spring what view should be displayed. Once again there are many ways to do this, but one of the most common is to return a String at the end of your method that corresponds with a view (.jsp). Usually a view resolver is registered to avoid hardcoding the name of a view file in the returned String. The returned String is resolved by the ViewResolver and associated view is returned.
To answer your follow up question if you want to serve the displaySearch.jsp after processing a request for search/systems you simply return that viewName.
#RequestMapping(value = "systems", method = RequestMethod.POST)
public String displaySystems(Model model, #RequestParam String searchStr) {
List<RSServicedSystemViewDTO> systems = systemService.getSystemsByName(searchStr);
model.addAttribute("systems", systems);
return "displaySearch";
}

Related

Prevent javascript firing on load page

I have MVC application with JavaScript in the body of the cshtml page. In Model, I have a method that returns a string, and I want that string to add in some div on a page on click of a button. It works, but, the method is triggered every time I load the page (and I want it to be triggered only on click.
Here is code:
Model:
public class TestJS
{
public string Tekst1 { get; set; }
public string Tekst2 { get; set; }
public TestJS()
{
Tekst1 = "one";
Tekst2 = "two";
}
public string AddTekst()
{
return "three (additional text from method)";
}
}
Controller:
public class TestJSController : Controller
{
// GET: TestJS
public ActionResult Index()
{
Models.TestJS tjs = new Models.TestJS();
return View(tjs);
}
}
View:
#model TestJavaScript.Models.TestJS
#{
ViewBag.Title = "Index";
}
<script type="text/javascript">
function faddtekst() {
whr = document.getElementById("div3");
var t = '#Model.AddTekst()';
whr.innerHTML += t;
}
</script>
<h2>Testing JavaScript Firing</h2>
<p>
First to fields:
#Model.Tekst1;
<br />
#Model.Tekst2;
</p>
<form>
<input type="button" value="Click to show Tekst3" onclick="faddtekst()" />
</form>
<br />
<hr />
<div id="div3">
</div>
I tried to wrap JS in $(document).ready() with same result.
Somebody may think of this as a strange approach, but, a model method that I'm trying to execute takes over 10 seconds in real code, so, I want to prevent waiting every time page loads (waiting should be only if the user clicks button).
The strangest thing is that Model.AddTekst() is executed EVEN if I comment it in javascript function with '//'.
Anyone knows how to avoid unwanted execution of Model.Method?
The behavior you are experiencing is not strange at all. #Model.AddText() executes on the backend once the view is compiled which is normal behaviour.
A comment in razor would look like this
#* Comment goes here *#
But this is not what you want to achieve.
I'm afraid your approach wont work since you can't execute a method on a model asynchronously.
I suggest you take a look at Ajax.BeginForm - more info here
You could implement a controller action on the backend which would return the text you want to display on the submitting of the form.
Try to use e.preventDefault() for button click.
<form>
<input type="button" value="Click to show Tekst3" id="Show" />
</form>
Try with jQuery
$(document).on("click", "#Show", function (e) {
e.preventDefault();
faddtekst();
});

Liferay 7.0 redirect to another jsp page with js click function

I have two jsp, view1 jsp, and view2.jsp. I have a button in view1 jsp and I want that button to redirect me to view2.jsp. I'm following the tutorials in liferay and I just want to know how will I able to do that using click function in jquery
Render Command:
#Component(
immediate = true,
property = {\
"javax.portlet.name=" + HelloWorldPortletKeys.HELLO_WORLD,
"mvc.command.name=/jsp/view2"
},
service = MVCRenderCommand.class
)
public class EditEntryMVCRenderCommand implements MVCRenderCommand {
#Override
public String render(
RenderRequest renderRequest, RenderResponse renderResponse) {
return "/jsp/view2.jsp";
}
}
view2.jsp
<portlet:renderURL var="view2URL">
<portlet:param name="mvcRenderCommandName" value="/jsp/view2" />
<portlet:param name="entryId" value="<%= String.valueOf(entry.getEntryId()) %>" />
</portlet:renderURL>
JS click function
$("#buttonid").click(function() {
$("#div1").load("${view2URL}");
)};
Using Ajax you can achieve this kind of requirement.
In serveresource method add the following line
include("/jsp/loadResult.jsp", resourceRequest, resourceResponse);

What would be the best way to read values from <h:selectOneMenu /> to javascript function?

I have jQuery modal div which displays on an on-click event....
<div id="time_scheduler" style="display: none;" title="Change Event Time" class="dialog">
<div class="block">
<h:form>
<span>Select Shift</span>
<p></p>
<h:selectOneMenu value="#{fieldController.shift}">
<f:selectItems itemLabel=" #{s.shiftName} #{s.startTime} to #{s.endTime}" var="s" value="#{fieldController.allShiftUnfiltered}" />
<f:converter converterId="shconvert" />
</h:selectOneMenu>
<p></p>
<h:commandButton onclick="getShift('#{request.contextPath}/changeEvent?','#{fieldController.shift.startTime}','#{fieldController.shift.endTime}');" styleClass="btn btn-small" value="change" />
</h:form>
</div>
</div>
and also a javascript function in a js file which gets called in a commandButton , the problem is each time the page displays , i get a null on the selectOneMenu after i click, then later i get the value, although its inconsistent,
function getShift(url,start_time,end_time){
console.log('starttime is '+start_time); //start time is null on page first load
console.log('endtime is '+end_time); //end time is null on first page load
$.ajax({
url: url + 'event_id=' + event_id + '&start_time=' + start_time + '&end_time=' + end_time,
cache: false,
success: function(value) {
console.log(value);
}
});
}
I have a converter class
#FacesConverter(value = "shconvert")
public class ShiftConverter implements Converter {
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
AdminEJB adm;
try {
adm = (AdminEJB) new InitialContext().lookup("java:global/ffm/AdminEJB");
return adm.findShift(value);
} catch (NamingException ex) {
return null;
}
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
return value.toString();
}
}
which pretty much does the conversion at a postconstruct level, what could really be the best way to pass this values to the javascript function each time the is changed ?
The way the commandButton is set up will make it use the last submitted values to call the javascript function. Before addressing this issue, we may want to understand the relationship between EL, JSF, and Javascript. JSF takes the facelet code and turns it into HTML. Any EL statements are resolved on the server side at that time. So, when it's all said and done, we have an HTML page that we can inspect in our favorite browser. Now comes Javascript, which has no awareness of JSF, so it works solely on the rendered HTML page.
With that in mind, we can see why the code above wouldn't work. The EL statements used as argument to the getShift Javascript function will only be resolved when that part of the page is rerendered by the server.
It look like the objective here is to call a non-JSF servlet asynchronously when the button is clicked. I would go about this a little differently. Have the commandButton call a JSF method asynchronously, and the method can reach out to the custom servlet.
<div id="time_scheduler" style="display: none;" title="Change Event Time" class="dialog">
<div class="block">
<h:form>
<span>Select Shift</span>
<p></p>
<h:selectOneMenu value="#{fieldController.shift}">
<f:selectItems itemLabel=" #{s.shiftName} #{s.startTime} to #{s.endTime}" var="s" value="#{fieldController.allShiftUnfiltered}" />
<f:converter converterId="shconvert" />
</h:selectOneMenu>
<p></p>
<h:commandButton styleClass="btn btn-small" value="change">
<f:ajax execute="#form" listener="#{someBean.callServlet()} />
</h:commandButton>
</h:form>
</div>
Then, create a backing bean with a method to call the servlet
#Named
public class SomeBean {
#Inject FieldController fieldController;
public String callServlet() {
Object startTime = fieldController.shift.startTime;
Object endTime = fieldController.shift.endTime;
//Call the servlet here
return null;
}
}
Here's an example on calling a servlet from java.

Form with JQuery Steps using aui:form tag in Liferay submits no data

I built a portlet and added a entity named Idea. There are two JSPs, one is the view and one the edit.
In the view there is only a button to create a new Idea and a table showing all ideas. Clicking on the button shows the edit jsp.
There is a form with two fieldsets and input stuff.
The "problem" is i cannot use the <aui:form ... stuff because it won't work with JQuery steps (or better, i cannot get it working). So i am using normal tag and also JQuery steps is providing the submit button which is only a <a href="#finish" ...>. So that wont bring the form to submit and the data being in the database.
So I tried to do it within the javascript code of the definition of jquery steps like here:
$(document).ready(function(){
var form = $("#wizard").show();
form.steps(
{
headerTag : "h3",
bodyTag : "fieldset",
transitionEffect : "slideLeft",
onFinishing: function (event, currentIndex) {
alert("Submitted!");
var data = jQuery("#wizard").serialize();
alert(data);
jQuery("#wizard").submit();
form.submit();[/b]
},
onFinished: function (event, currentIndex) {
//I tried also here..
},
});
});
But even if i declare the data explicitely it wont put it in the db.
So my idea was that the "controller" class which calls the "addIdea" function is never called.
How am I solving the problem?
Here is also my jsp code for the form part:
<aui:form id="wizard" class="wizard" action="<%= editIdeaURL %>" method="POST" name="fm">
<h3>Idea</h3>
<aui:fieldset>
<aui:input name="redirect" type="hidden" value="<%= redirect %>" />
<aui:input name="ideaId" type="hidden" value='<%= idea == null ? "" : idea.getIdeaId() %>'/>
<aui:input name="ideaName" />
</aui:fieldset>
<h3>Idea desc</h3>
<aui:fieldset>
<aui:input name="ideaDescription" />
</aui:fieldset>
<aui:button-row>
<aui:button type="submit" />
<aui:button onClick="<%= viewIdeaURL %>" type="cancel" />
</aui:button-row>
</aui:form>
Is there a way to "teach" JQuery Steps the <aui:*** tags? I tried it already while initializing the form but it won't work. To get it working using the aui tags would be great. Because otherwise the Liferay portal wont get the data or it would get it only with hacks right?
€dit: What I forgot, when I submit the form using javascript submit, it creates a new dataentry in the db but no actual data in it.
€dit2:
The editIdeaURL is referenced a bit over the form here:
<portlet:actionURL name='<%=idea == null ? "addIdea" : "updateIdea"%>'
var="editIdeaURL" windowState="normal" />
and the addIdea code looks as follows:
In the IdeaCreation class first this:
public void addIdea(ActionRequest request, ActionResponse response)
throws Exception {
_updateIdea(request);
sendRedirect(request, response);
}
Where _updateIdea() is:
private Idea _updateIdea(ActionRequest request)
throws PortalException, SystemException {
long ideaId = (ParamUtil.getLong(request, "ideaId"));
String ideaName = (ParamUtil.getString(request, "ideaName"));
String ideaDescription = (ParamUtil.getString(request, "ideaDescription"));
ServiceContext serviceContext = ServiceContextFactory.getInstance(
Idea.class.getName(), request);
Idea idea = null;
if (ideaId <= 0) {
idea = IdeaLocalServiceUtil.addIdea(
serviceContext.getUserId(),
serviceContext.getScopeGroupId(), ideaName, ideaDescription,
serviceContext);
} else {
idea = IdeaLocalServiceUtil.getIdea(ideaId);
idea = IdeaLocalServiceUtil.updateIdea(
serviceContext.getUserId(), ideaId, ideaName, ideaDescription,
serviceContext);
}
return idea;
}
And to finally put the data using IdeaLocalServiceImpl:
public Idea addIdea(
long userId, long groupId, String ideaName, String ideaDescription,
ServiceContext serviceContext)
throws PortalException, SystemException {
User user = userPersistence.findByPrimaryKey(userId);
Date now = new Date();
long ideaId =
counterLocalService.increment(Idea.class.getName());
Idea idea = ideaPersistence.create(ideaId);
idea.setIdeaName(ideaName);
idea.setIdeaDescription(ideaDescription);
idea.setGroupId(groupId);
idea.setCompanyId(user.getCompanyId());
idea.setUserId(user.getUserId());
idea.setCreateDate(serviceContext.getCreateDate(now));
idea.setModifiedDate(serviceContext.getModifiedDate(now));
super.addIdea(idea);
return idea;
}
Any ideas?

Asp.net mvc passing a C# object to Javascript

I have c# class say options more like AjaxOptions.
public class options
{
public string Url {get;set;}
public string httpMethod {get;set}
}
and a javascript function like this
function dosomething(obj)
{
if (obj.Url!="" and obj.HttpMethod=="something")
loadsomething();
}
Now in my Controller action
public class mycontroller : controller
{
public ActionResult WhatToDo()
{
options obj = new options{Url="someurl"};
return PartialView(obj);
}
}
in my view I need this object kind of string which i should be able to pass to my method.
#model options
<script>
dosomething(#model.SomeFunctionToConverToString())
</script>
So I need this SomeFunctionToConverToString method which i will convert this object to string.
Thanks
You should be able to use it like you would any other output of a model property in your view. Just reference the property that you want to pass in the JS function.
#model options
<script>
dosomething('#(model.Url)');
</script>
See this post for more information on using Razor inside of JS
EDIT - Something that might catch you is that if your URL get's broken from the HTML encoding that Razor does using the above, you can use the #Html.Raw() function which will pass the Url property without HTML encoding it.
<script>
dosomething('#Html.Raw(model.Url)');
</script>
EDIT 2 - And another SO post to the rescue! You are going to most likely want to convert your model to JSON in order to use in a Javascript function. So...in order to do that - you will need something in your view model to handle a JSON object.
public class optionsViewModel
{
public options Options{get;set;}
public string JsonData{get;set;}
}
and in your controller:
public class mycontroller : controller
{
public ActionResult WhatToDo()
{
options obj = new options{Url="someurl"};
var myViewModel = new optionsViewModel;
myViewModel.options = obj;
var serializer = new JavaScriptSerializer();
myViewModel.JsonData = serializer.Serialize(data);
return PartialView(myViewModel);
}
}
And finally the view:
#model optionsViewModel
<script>
dosomething('#model.JsonData')
</script>
Using this method, then your function will work as expected:
function dosomething(obj)
{
if (obj.Url!="" and obj.HttpMethod=="something")
loadsomething();
}
EDIT 3 Potentially the simplest way yet? Same premise as edit 2, however this is using the View to JsonEncode the model. There are probably some good arguments on either side whether this should be done in the view, controller, or repository/service layer. However, for doing the conversion in the view...
#model options
<script>
dosomething('#Html.Raw(Json.Encode(Model))');
</script>
Try this:
<script type="text/javascript">
var obj= #Html.Raw(Json.Encode(Model));
function dosomething(obj){}
</script>
That's work for me
Client side:
function GoWild(jsonData)
{
alert(jsonData);
}
Alert print :
{"wildDetails":{"Name":"Al","Id":1}}
MVC Razor Side:
#{var serializer new System.Web.Script.Serialization.JavaScriptSerializer();}
<div onclick="GoWild('#serializer.Serialize(Model.wildDetails)')"> Serialize It </div>
there is also a syntax error
<script type="text/javascript">
dosomething("#Model.Stringify()");
</script>
note the quotes around #Model.Stringify() are for javascript, so the emitted HTML will be:
<script type="text/javascript">
dosomething("this model has been stringified!");
</script>
I would recommend you have a look at SignalR, it allows for server triggered javascript callbacks.
See Scott H site for details: http://www.hanselman.com/blog/AsynchronousScalableWebApplicationsWithRealtimePersistentLongrunningConnectionsWithSignalR.aspx
In summary thou ...
Javascript Client:
var chat = $.connection.chat;
chat.name = prompt("What's your name?", "");
chat.receive = function(name, message){
$("#messages").append("
"+name+": "+message);
}
$("#send-button").click(function(){
chat.distribute($("#text-input").val());
});
Server:
public class Chat : Hub {
public void Distribute(string message) {
Clients.receive(Caller.name, message);
}
}
So .. Clients.receive in C# ends up triggering the chat.receive function in javascript.
It's also available via NuGet.

Categories