Get data in Angular 2 from Spring - spring

Let's say that I have a page rendered by Spring Framework. It is a page with Angular 2 code. How could I receive data on the page if Spring sends it? I do not want to render a page, then do an HTTP request, then get a response. No, in Spring controller I want to send data and somehow receive it with Angular 2 and show (without additional requests). With JSPs it is obvious how to do, but how to set Angular 2 model from JSON sent by Spring upon rendering the page?
What I have right now is Spring Security managing login. Then, in controller data gets prepared depending on the user, and then I want to send it to Angular 2 page. So, I am stuck with not knowing how to render a page AND attach data for it to be rendered by Angular 2 at the same time.

I'm not sure if I totally understood the question... anyway if I did, I'd do in this way
In spring controller, before rendering the JSP page, i'd all the business logic you need to create the JSON; then I'd create a JSON string and I'd attach it to the model
It means I'd do something like that:
#RequestMapping("/render")
public String renderView(ModelAndView model)
{
//Your JSON String
String json = "{\"foo\":\"bar\"}";
model.addAttribute("json", json);
return "yourJspName";
}
Then in your JSP you can use Angular to access to the json contained in the model (that is in the pageContext); for example, by using JSTL:
<script type="text/javascript">
var theJsonString = '${json}';
</script>
or
<script type="text/javascript">
var theJsonString = '<c:out value="${json}" />';
</script>
At this point you have the JS variable named theJsonString with your JSON string and you can use it as you want... for example by passing it to angular
If you need JSON object you should to something like this:
<script type="text/javascript">
var theJsonString = '${json}';
var theJsonObj = JSON.parse(theJsonString);
</script>
or
<script type="text/javascript">
var theJsonString = '<c:out value="${json}" />';
var theJsonObj = JSON.parse(theJsonString);
</script>
I hope this can help
Angelo

I was able to solve the problem but by redesigning the app and not by finding a real fix. What I was doing is starting Angular 2 app, have some navigation, functionality on the page, then one could click login, and Spring Security came into play. However, after verification I could not figure out how to launch Angular 2 app again: start a completely new one? Or somehow use the already launched to proceed with the development? Not sure.
What I did is just start the app by showing login page always at the very beginning and only after user logs in, Angular 2 comes into play. I guess, I could set up a second website to develop another Angular app, and make a link there that would launch this one, if we need some functionality before user logs in. The problem was that I was trying to split one Angular app into two, I guess.
Just in case, here is my security.xml part (Spring Security version 4.0.4.RELEASE):
<http use-expressions="true">
<intercept-url pattern="/views/**" access="hasAnyRole('ROLE_CUSTOMER', 'ROLE_ADMIN')" />
<form-login
login-page="/login.jsp"
login-processing-url="/views/home"
authentication-failure-url="/login.jsp?error=failed_login"
/>
<logout logout-url="/logout" logout-success-url="/login.jsp" delete-cookies="JSESSIONID" />
<remember-me />
<headers>
<cache-control/>
<xss-protection/>
</headers>
</http>
Login form:
<form class="form-signin" method="POST"
action="${pageContext.servletContext.contextPath}/views/home">
<h2 class="form-signin-heading">Please sign in</h2>
<label for="inputEmail" class="sr-only">Email address</label>
<input type="text" name="username" class="form-control" placeholder="Login" required autofocus>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" name="password" class="form-control" placeholder="Password" required>
<div class="checkbox">
<label>
<input type="checkbox" value="remember-me"> Remember me
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>
And a controller that launches Angular application upon successful log in:
#RequestMapping("/views/home")
public String login() {
return "index";
}
Then, in launched Angular 2 app I am planning to fetch the data by making HTTP requests, and using Springs' controllers to return me JSON. So, after Angular is launched it works by itself just interacting with the server via HTTP. After logging out a user will not get access to Angular app because it is under a protected folder and index.jsp is not in the app root folder, so it can not be launched by accessing / path.

Related

Form POST not working in web-based Task module

In my Web-based Task Module I display a button for the user to click if they accept certain conditions. The page has a form element with several hidden inputs to send a POST request to open a web page in a new browser window. When the user clicks the button on the page, we call a javascript function that calls the submit() method on the form and when the submit() completes calls microsoftTeams.tasks.submitTask() with the success results to close the Task Module.
<html>
<body>
<script>
microsoftTeams.initialize();
function buttonClick() {
// have the form submit to open the external document
document.getElementById("openNewDocument").submit();
// tell the bot the user didn't cancel
microsoftTeams.tasks.submitTask(
{"command":"openDocument", "success":"true"},
[ {my App ID} ]
);
}
</script>
<form
id="openNewDocument"
method="post"
action={url to document server}
target="_blank"
>
<input hidden="true" name="docContext" value={encryptedContext} />
<input hidden="true" name="activityId" value={activityId} />
<input hidden="true" name="participantId" value={participantId} />
<input hidden="true" name="tid" value={tid} />
</form>
<button label="open document" onClick=buttonClick()>
Open document
</button>
</body>
</html>
In the web browser the code works just fine. But in the Desktop Teams app (MacOS) the POST request is sent as a GET and the hidden inputs are ignored.
Is there a secret to getting the Form data send as a POST?
Form POST will not work in Task module. You need to call chaining in task module. Please go through this documentation.

how to handle multiple submit buttons in spring mvc in java. One Submit buttons is for Server side and another is only for Client Side

I am trying to handle multiple submit buttons in spring mvc in java. 1st Submit buttons is for Server side call and 2nd Submit button is only for Client Side call.
But here the problem here I am facing is, for both submit button, control is going to Server side . I am Using plane jsp with spring tag. Here my requirement is one submit button should work for server side & another submit button only works for client side.
CODE Snippet:
<body>
<div>
<form:form commandName="route" method="post" action="routeSave" id="route">
<div class="center">
Start:<form:input path="start" id="start" maxlength="50"/>
End:<form:input path="end" id="end" maxlength="50"/>
City:<form:input path="city" id="city" maxlength="50" onchange="mapcenter()"/>
RouteName:<form:input path="routeName" id="routeName" maxlength="50"/>
StartTime:<form:input path="startTime" id="startTime" maxlength="50"/>
<form:button value="SaveMap">Save Button</form:button>
<form:button value="SaveMap" onclick="save_map()">Save Map</form:button>
A button of type="button" will not submit a form to a URL. A button of type="submit" (the default) will. So use a type="button" button for the client side action.
<form:form>
<button type="button" name="btn1">no submit</button>
<button type="submit" name="btn2">submit</button>
</form:form>
You can try it with for Example jQuery:
$( "#route" ).submit(function( event ) {
event.preventDefault();
});
The event Element has additional Information to handle it in handler-Method. See jQuery Docs.

Cross Domain Form Submission in Laravel

It is my first time to use laravel. I just want to ask a question regarding cross domain form submission best practice.
Let say I have simple HTML form in myfirstdomain.com/form
<form action="http://myseconddomain.com/insert/data/" method="POST">
<input name="fullname" type="text" placeholder="Enter your name" />
<input type="submit" value="submit">
</form>
And I have register "/insert/data" on my route file in other domain, let say myseconddomain.com :
Route::get('/insert/data', function()
{
$fullname = Input::get('fullname');
// Insert the name after this...
});
Is it safe to do that? I mean I'm using POST to submit form and using Route::get to fetch it?
Is there any other better option? I tried Route::post and get the MethodNotAllowed error instead.
Thank you

How to show flash.message in Grails after AJAX call

I want to show some flash message after completion of AJAX call. I am doing like this ..
Controller Action --
def subscribe()
{
def subscribe = new Subscriber()
subscribe.email = params.subscribe
if (subscribe.save())
{
flash.message = "Thanks for your subscribtion"
}
}
View Part --
Subscribe :
<g:formRemote onSuccess="document.getElementById('subscribeField').value='';" url="[controller: 'TekEvent', action: 'subscribe']" update="confirm" name="updateForm">
<g:textField name="subscribe" placeholder="Enter your Email" id="subscribeField" />
<g:submitButton name="Submit" />
</g:formRemote >
<div id="confirm">
<g:if test="${flash.message}">
<div class="message" style="display: block">${flash.message}</div>
</g:if>
</div>
My AJAX working fine but it is not showing me flash.message. After refresh page it displaying message. How to solve it ?
When you use ajax your page content isn't re-parsed, so your code:
<g:if test="${flash.message}">
<div class="message" style="display: block">${flash.message}</div>
</g:if>
will not run again.
So I agree with #James comment, flash is not the better option to you.
If you need to update your view, go with JSON. Grails already have a converter that can be used to this:
if (subscribe.save()) {
render ([message: "Thanks for your subscribtion"] as JSON)
}
And your view:
<g:formRemote onSuccess="update(data)" url="[controller: 'TekEvent', action: 'subscribe']" name="updateForm">
<g:textField name="subscribe" placeholder="Enter your Email" id="subscribeField" />
<g:submitButton name="Submit" />
</g:formRemote >
<script type='text/javascript'>
function update(data) {
$('#subscribeField').val('');
$('#confirm').html(data.message);
}
</script>
You have couple options,
First you can try to return the message from your controller in a form of json or a map and render it on the screen your self using javascript libraries, which is a bit different if you want to use Grails ajax tags.
The other option is using a plugin like one-time-data , which
Summary A safe replacement for "flash" scope where you stash data in
the session which can only be read once, but at any point in the
future of the session provided you have the "id" required.
Description
This plugin provides a multi-window safe alternative to flash scope
that makes it possible to defer accessing the data until any future
request (so long as the session is preserved).
more
Hope it helps

Load Dojo form from ajax call

I am trying to implement something like this.
http://app.maqetta.org/mixloginstatic/LoginWindow.html
I want the login page to load but if you click the signup button then an ajax will replace the login form with the signup form.
I have got this to work using this code
dojo.xhrGet({
// The URL of the request
url: "'.$url.'",
// The success callback with result from server
load: function(newContent) {
dojo.byId("'.$contentNode.'").innerHTML = newContent;
},
// The error handler
error: function() {
// Do nothing -- keep old content there
}
});'
the only problem is the new form just loads up as a normal form, not a dojo form. I have tried to return some script with the phaser but it doesnt do anything.
<div id="loginBox"><div class="instructionBox">Please enter your details below and click <a><strong>signup</strong>
</a> to have an activation email sent to you.</div>
<form enctype="application/x-www-form-urlencoded" class="site-form login-form" action="/user/signup" method="post"><div>
<dt id="emailaddress-label"><label for="emailaddress" class="required">Email address</label></dt>
<dd>
<input 0="Errors" id="emailaddress" name="emailaddress" value="" type="text"></dd>
<dt id="password-label"><label for="password" class="required">Password</label></dt>
<dd>
<input 0="Errors" id="password" name="password" value="" type="password"></dd>
<dt id="captcha-input-label"><label for="captcha-input" class="required">Captcha Code</label></dt>
<dd id="captcha-element">
<img width="200" height="50" alt="" src="/captcha/d7849e6f0b95cad032db35e1a853c8f6.png">
<input type="hidden" name="captcha[id]" value="d7849e6f0b95cad032db35e1a853c8f6" id="captcha-id">
<input type="text" name="captcha[input]" id="captcha-input" value="">
<p class="description">Enter the characters shown into the field.</p></dd>
<dt id="submitButton-label"> </dt><dd id="submitButton-element">
<input id="submitButton" name="submitButton" value="Signup" type="submit"></dd>
<dt id="cancelButton-label"> </dt><dd id="cancelButton-element">
<button name="cancelButton" id="cancelButton" type="button">Cancel</button></dd>
</div></form>
<script type="text/javascript">
$(document).ready(function() {
var widget = dijit.byId("signup");
if (widget) {
widget.destroyRecursive(true);
}
dojo.parser.instantiate([dojo.byId("loginBox")]);
dojo.parser.parse(dojo.byId("loginBox"));
});
</script></div>
any advice on how i can get this to load as a dojo form. by the way i am using Zend_Dojo_Form, if i run the code directly then everything works find but through ajax it doesnt work. thanks.
update
I have discovered that if I load the form in my action and run the __toString() on it it works when i load the form from ajax. It must do preparation in __toString()
Firstly; You need to run the dojo parser on html, for it to accept the data-dojo-type (fka dojoType) attributes, like so:
dojo.parser.parse( dojo.byId("'.$contentNode.'") )
This will of course only instantiate dijits where the dojo type is set to something, for instance (for html5 1.7+ syntax) <form data-dojo-type="dijit.form.Form" action="index.php"> ... <button type="submit" data-dojo-type="dijit.form.Button">Send</button> ... </form>.
So you need to change the ajax contents which is set to innerHTML, so that the parser reckognizes the form of the type dijit.form.Form. That said, I urge people into using a complete set of dijit.form.* Elements as input fields.
In regards to:
$(document).ready(function() {});
This function will never get called. The document, youre adding innerHTML to, was ready perhaps a long time a go.
About Zend in this issue:
Youre most likely rendering the above output form from a Zend_ Dojo type form. If the renderer is set as programmatic, you will see above html a script containing a registry for ID=>dojoType mappings. The behavior when inserting <script> as an innerHTML attribute value, the script is not run under most circumstances (!).
You should try something similar to this pseudo for your form controller:
if request is ajax dojoHelper set layout declarative
else dojoHelper set layout programmatic

Resources