Retrieving a parameter from GSP in Controller, Grails - model-view-controller

I do have this code on my demo.gsp file. But I´m new to grails and I don´t really know very well how to retrieve the value of the input on my Controller to validate it like i.e "inputResult=="hi" then ok else bad".
<g:form action='${postUrl}' method='post' id='loginForm' class='cssform' autocomplete='off'>
<p>
<label for="password">
<g:message code="access.code"/>:
</label>
</p>
<p>
<input name="j_password" class="loghominput" id="password" type="password"/>
</p>
<div class="greenbutton2">
<a href="#" onclick="document.getElementById('loginForm').submit(); return false">
<g:message code="home.enter"/></a><input type="submit" style="display:none" value="Enter"/>
</div>
</g:form>
My Controller is like this.
class AskDemoController {
def demo = {
}
}
Thanks!

You can access parameters submitted by your form in the controller by using the params object. Something like this...
def somethingInTheForm = params.nameOfTheParam;
if (somethingInTheForm){
render 'good'
}else{
render 'bad'
}
Take a look here for documentation.
However - i would suggest going through some to the Tutorials to gain a better understanding of the power of grails.

Related

Thymeleaf form array with default values

I'm using Spring+Thymeleaf to see and modify the users in a database. I would like to set the input fields to the actual values of an original user but I've tried with different styles and it doesn't work.
With the present configuration I can update information of users and see the id of original user (it's not in a input field) but I can't show the actual configuration in input field as default.
CONTROLLER:
#GetMapping(value = {"/", ""})
public String subusersPage(HttpSession session, Model model) {
String idUser = BaseController.getLoggedUser(session);
UserDTO userDTO = userService.getUserById(idUser);
model.addAttribute("subusersDTO", userService.getSubusersDTO(userDTO.getSubusers()));
model.addAttribute("populations", userDTO.getPopulations());
model.addAttribute("configurations", userDTO.getConfigurations());
model.addAttribute("attributes", userDTO.getAttributes());
model.addAttribute("subuserDTO", new SubuserDTO());
return "subusers";
}
HTML:
<th:block th:each="subuserDTO_original : ${subusersDTO}">
<hr>
<form action="#" th:action="#{/subusers/__${subuserDTO_original.id}__}" th:object="${subuserDTO}" method="post">
<div>
<p th:text="${'Id: ' + subuserDTO_original.id}"></p>
<p>Name: <input type="text" th:field="*{name}" th:name="name" th:value="${subuserDTO_original.name}"/></p>
<p>Population: <input type="text" th:field="*{population}" th:name="population" th:value="${subuserDTO_original.population}"/></p>
<p>Configuration: <input type="text" th:field="*{configuration}" th:name="configuration" th:value="${subuserDTO_original.configuration}"/></p>
<p>Attributes: <input type="text" th:field="*{attributes}" th:name="attributes" th:value="${subuserDTO_original.attributes}"/></p>
<p>
<button type="submit" th:name="action" th:value="update">Update</button>
<button type="submit" th:name="action" th:value="delete">Delete</button>
<button type="reset" th:name="action" th:value="clear">Clear</button>
</p>
</div>
</form>
<form action="#" th:action="#{/subusers/__${subuserDTO_original.id}__}" method="get">
<button type="submit">Default</button>
</form>
</th:block>
Any help will be very appreciated, thank you!
If you want to edit an existing user, then your th:object (which is ${subuserDTO} in this case) needs to be populated with the values of the original user. This is because when you use the attribute th:field="*{name}", it actually overwrites the name, id, and value of the html tag (which is why th:value="${subuserDTO_original.name}" isn't working.
Two other options you could do:
You could also set name="name" and use th:value instead.
Or another option, you could use ${subuserDTO_original} as your th:object.

How to POST an object to controller

I'm having a difficulty passing my 'product' object to the controller. How can I do it? I'm not getting errors. The problem is that the 'product' object is null on my controller.
html:
<section th:each="menu : ${allMenus}">
<button
<h1 th:text="${menu.name}"></h1>
</button>
<div>
<div th:each="product : ${menu.productList}">
<a data-toggle="modal" th:href="'#' + ${product.name} + 'Modal'">
h5 th:text="${product.name}"></h5>
<small th:text="${product.price} + '$'"></small>
<p th:text="${product.description}"></p>
</a>
<div th:replace="/productModal :: productModal(product=${product})"></div>
</div>
</section>
Modal:
<div th:fragment="productModal(product)">
<div role="document">
<form method="post" th:action="#{/addItemToCart}">
<div th:each="topping : ${product.toppings}">
<input type="checkbox" th:id="${topping} + ${product.id}" name="checkedToppings" th:value="${topping}" />
<label th:for="${topping} + ${product.id}" th:text="${topping}"></label>
</div>
<div>
<button type="submit">Add to Shopping Cart</button>
</div>
</form>
</div>
</div>
controller:
#RequestMapping(value="/addItemToCart", method=RequestMethod.POST)
public String addItemToCart(#ModelAttribute("product") Product product, #RequestParam("checkedToppings") List<String> toppings)
{
//product is null;
//checkedToppings are retrieved correctly
return "redirect:/menu";
}
Short answer:
you don't post objects to controllers using HTML.
Details:
You will never be able to post a "product" object to your controller from an HTML page.
Instead,
you should send identifying information about the desired "product" to the controller,
perhaps a product-id or some other product-unique-identity-blammy.
Response to options in comments:
Hackers love hidden fields and JavaScript;
I recommend against using those for this situation.
I believe that you only have one option: identifying info.
This does not need to be a "real" product number.
You can generate a UUID and store a map in the choose one: (Servlet Session, Database, Application Session, somewhere else on the server) that maps from the UUID to the desired product.

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

Loading a codeigniter view with a form from inside another view

Using codeigniter, I've been trying to load a view inside of a foreach loop, as follows:
$posts = $this->postslibrary->getAllPosts();
foreach($posts as $post){
$home['content'][$i] = $this->load->view('post', $post['data'], true);
$i++;
}
$this->load->view('head');
$this->load->view('home', $home);
$this->load->view('footer');
Each of those post views looks a little like this:
<div class="postnum<?=$post_num?>">
<p>Posted by: <?=$poster_name?></p>
<p>Reply to: <?=$poster_name?></p>
<form>
<input type='text' />
<input type='submit' />
</form>
</div>
And they're being loaded mostly successfully in the 'home' view (which is below for thoroughness).
<div ="posts">
<?php
for($i=0;$i<$count;$i++)
{
echo($content[$i]);
}
?>
<div class="clear"></div>
<a href='/posts/browse/'>Load more items</a>
</div>
But my output ends up looking like:
<div class='posts'>
<div class='postnum1'>
<p>Posted By: Jim</p>
<p>Reply to Jim</p>
<input type='text' />
<input type='submit' />
</div>
</div>
Why are my form tags not coming through?
Check if you already have a form around the current form. Chrome is one of the browsers which doesn't accept this and removes the second form. Using a form in a form is bad practice and I suggest you find a different solution to do the form handling.
Slightly left-of-field answer, but have a look at CodeIgniter Form Generator. I've used it a couple of times and it seems pretty good for generating forms from an array. It's a bit tricky to get your head around it to begin with, but it works well once you've gotten into it.
The basic idea is that you implement a form controller from your ordinary controller, and then just output it in your view file. It might be a more elegant (and sustainable) solution to what you're trying.

Form Submit using a Javascript to invoke webflow transition, doesn't take the updated value on form

I am trying to invoke a form submit using javascript (jquery) to invoke a webflow transition. It works and the submit invokes the desired transition. But, the updated radio button values is not reflected on the model object which is posted.
Here is the code:
<form:form method="post" action="#" commandName="infoModel" name="pageForm">
<form:input type="input" path="testMsg" id="success" />
<input type="button" id="clearSelections" value="Clear Selections">
<div class="question">
<h4><c:out value="${infoModel.questionInfo.description}"/> </h4>
<form:radiobuttons path="infoModel.answerId"
itemValue="answerId" itemLabel="answerDescription" items="${infoModel.answers}" delimiter="<br/>" />
</div>
<input type="submit" name="_eventId_saveQualitativeInput" value="Save" id="save" />
$(document).ready(function() {
$('#tabs').tabs();
//Clear selections (copy is server-side)
$('#clearSelections').click(function() {
//$('input[type="radio"]').prop('checked', false);
$('input[type="radio"]').removeAttr('checked');
$('#save').trigger('click');
});
});
</form:form>
The form:radiobutton, generates the below html:
<div class="question">
<h4>Is this a general obligation of the entity representing a full faith and credit pledge? </h4>
<span>
<input type="radio" checked="checked" value="273" name="infoModel.answerId" id="infoModel.answerId1">
<label for="infoModel.answerId1">Yes</label>
</span>
<span><br>
<input type="radio" value="274" name="infoModel.answerId" id="infoModel.answerId2">
<label for="infoModel.answerId2">No</label>
</span>
<br>
<span class="error"></span>
</div>
The input id= "success" value is registered and when the control goes to the server, the value of input id= "success" is updated in the "infoModel" object. But the value of answerId is not updated on the "infoModel" object.
Thoughts if i am missing something in the form:radiobutton element or if there is something else wrong?
Thanks in advance!
EDIT:::::::
Thanks mico! that makes sense. I stripped of some of the code first time to make it precise, but i have a list which is being used for building the radio-buttons, below is the code:
<c:forEach items="${infoModel.list["index"]}" var="qa" varStatus="rowCount">
<div class="question">
<h4><c:out value="${question.questionInfo.description}"/> </h4>
<form:radiobuttons path="list["index"][${rowCount.index}].answerId" itemValue="answerId" itemLabel="answerDescription" items="${question.answers}" delimiter="<br/>" />
<br>
</div>
</c:forEach>
Could you please suggest how i could try this one out?
NOTE: The same code works on a regular form submit on click of a button of type submit. Its the javascript form submit which is not working. I also tried to do whatever i want to do in javascript and then invoke the button.trigger('click'); form got submitted but the changes made on form in my javascript didnt reflect.
With commandName inside a form:form tag you set "Name of the model attribute under which the form object is exposed" (see Spring Documentation). Then in path you should tell the continuation of the path inside the model attribute.
With this said I would only drop the extra word infoModel from path="infoModel.answerId" and have it rewritten as path="answerId" there under the form:radiobutton.

Resources