I have tables: Products and Shop.(I generate controllers using grails generate-all) Shop hasmany products
I'm trying to do is List all the shops in and save to database selected shop when creating a new product.
I listed all values using
<g:form controller="product" action="save" role="form">
<div class="form-horizontal" role="form">
<div class="form-group">
<label class="col-lg-3 control-label">Product Name:</label>
<div class="col-lg-8">
<g:textField name="productName" class="form-control" value="${product.productName}"/>
</div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">Product Barcode</label>
<div class="col-lg-8">
<g:textField name="date expired" class="form-control" value="${product.productBarcode}"></g:textField>
</div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">Product Shop</label>
<g:select class="selectpicker" name="products.id" from="${tr.com.netiket.lkkstoreapp.Shop.list()}" value="shop?.products.id" optionValue="shopName"></g:select>
</div>
</g:form>
when i click create button it says
Property [shop] of class [class tr.com.nur.storeapp.Product] cannot be null
This bit doesn't look right:
<g:select class="selectpicker" name="products.id" from="${tr.com.netiket.lkkstoreapp.Shop.list()}" value="shop?.products.id" optionValue="shopName"></g:select>
The name should be the id of the Shop and the value should be the product's shop id, if present:
<g:select class="selectpicker" name="shop.id" from="${tr.com.netiket.lkkstoreapp.Shop.list()}" value="${product?.shop?.id}" optionValue="shopName"></g:select>
#Transactional
def save(Shop shop) {
//println "in shop save"
def currentUser=(User)springSecurityService.currentUser
shop.user=currentUser
shop.validate()
if (!shop) {
//println "I have no shop"
transactionStatus.setRollbackOnly()
notFound()
return
}
//if (shop.hasErrors()) {
if (shop.save(flush:true)) {
//println "shop has errors"
transactionStatus.setRollbackOnly()
respond shop.errors, view:'create'
shop.errors.allErrors
return
}
//shop.save flush:true
//println "shop has saved"
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message', args: [message(code: 'shop.label', default: 'Shop'), shop.id])
//println "redirecting"
redirect shop
}
'*' { respond shop, [status: CREATED] }
}
}
This is my save method. Actuaally I didint write anything here. Generate domain .
Related
I am working on this ASP.NET MVC project where I am performing simple CRUD operations. On clicking Edit button, I want to get the data from the database and populate it in the Create View (same view with the help of which I entered the data).
The issue that I have is that, though I am able to enter the data into the database using the Create.cshtml view, I am not able to populate the data back into the fields to the same View upon clicking Edit. On checking, I see that I am able to get the data from the database from the Controller and I am sending it to the View - Create. But, the fields are not getting populated in the View.
Where am I going wrong?
View - Create.cshtml
<form method="post" action="/Books/Create" id="formBooks">
<div class="form-group">
<div class="form-row">
<div class="form-group col-md-6">
<div>
<label asp-for="Title" class="label">Title</label>
<input asp-for="Title" class="form-control" id="title" name="title" required />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div>
<label asp-for="Author" class="label">Author</label>
<input asp-for="Author" class="form-control" id="author" name="author" required />
<span asp-validation-for="Author" class="text-danger"></span>
</div>
...
</div>
<div class="form-group col-md-6">
<button type="submit" value="Save" class="btn bgm-orange waves-effect mybtn">SAVE</button>
</div>
</div>
</div>
</form>
Controller - BooksController.cs
public ActionResult Create(int? Id)
{
if(Id == null)
{
return View();
}
else
{
var bookData = _context.Books
.Where(b => b.ID == Id)
.FirstOrDefault();
return View(bookData);
}
}
public ActionResult Create(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Books books= db.Books.Find(id);
if (books== null)
{
return HttpNotFound();
}
return View(books);
}
//Try this i hope this will work
The name attribute plays a vital role in binding the data to the <input></input> field. Also, value attribute gets the value to display in the Edit view.
<input asp-for="Title" class="form-control" id="title" name="title" placeholder="Enter title..." value="#(Model != null ? Model.Title : "")" required />
Model property which I intend to use inside two forms
public class TestModel
{
[Display(Name = "Terms Accepted")]
[Range(typeof(bool), "true", "true", ErrorMessage = "You need to accept terms and conditions to proceed!")]
public bool TermsAccepted { get; set; }
}
view Page
<form id="form1">
<div class="row">
<div class="col-md-3">
#Html.CheckBoxFor(m => m.TermsAccepted) I accept terms and conditions
#Html.ValidationMessageFor(m => m.TermsAccepted, new { #id = "chk1" })
</div>
<div class="col-md-3">
<input type="submit" id="button1" onclick="return isFormValid('form1');" value="Submit Form 1"/>
</div>
</div>
</form>
<form id="form2">
<div class="row">
<div class="col-md-3">
#Html.CheckBoxFor(m => m.TermsAccepted, new { #id = "chk2" }) I accept terms and conditions
#Html.ValidationMessageFor(m => m.TermsAccepted)
</div>
<div class="col-md-3">
<input type="submit" id="button2" onclick="return isFormValid('form2');" value="Submit Form 2"/>
</div>
</div>
</form>
When this UI is rendered on the page, checkbox inside the 1st form do contains attributes for RangeDataAnnotation while checkbox inside 2nd form doesn't have any attributes for data annotation. So this results into 2nd form doesn't throw any validation on submission.
Html of checkboxes which get rendered on UI
Inside form 1:
<input name="TermsAccepted" class="input-validation-error" id="chk1" aria-describedby="TermsAccepted-error" type="checkbox" value="true" data-val="true" data-val-range-min="True" data-val-range-max="True" data-val-range="You need to accept terms and conditions to proceed!">
Inside form 2:
<input name="TermsAccepted" id="chk2" type="checkbox" value="true">
Any suggestions to make this work in both forms?
I was trying to make a signup page, which takes the username and password as from the user and stores it in my database, but the problem here is, the data is not going to the database only
you can see the image here
[https://drive.google.com/file/d/0B9gjSzsLSnClR1VvU0RUa3liRWs/view?usp=sharing][1]
save method look likes this
#Transactional
def save(){
if(params == null){
redirect(action:"index")
flash.message=''
return
}
def employee = findByUsername(params.username);
System.out.println(employee.username);
if(employee!=null){
flash.message="username already exist"
render(view:"signup")
}
else{
def newEmp = new Employee();
newEmp.username=params.username
newEmp.password=params.password
if(newEmp.save(flush:true)){
flash.message="Employee created"
render(view:"index")
}
else{
flash.message="Please enter valid data"
render(view:"signup")
}
if(newEmp.save(flush:true)) {
flash.message = "User Created. Please Login"
render(view:"index")
} else {
flash.message = "Please enter valid data";
render(view:"signup")
}
}
}
View page look like this
<form id="signupform" action="./save" method="POST" class="form-horizontal" role="form">
<g:if test="${flash.message}">
<div class="alert alert-danger" role="alert">${flash.message}</div>
</g:if>
<div class="form-group">
<label for="username" class="col-md-3 control-label">Username</label>
<div class="col-md-9">
<input type="text" class="form-control" name="username" placeholder="Username">
</div>
</div>
<div class="form-group">
<label for="password" class="col-md-3 control-label">Password</label>
<div class="col-md-9">
<input type="password" class="form-control" name="password" placeholder="Password">
</div>
</div>
<div class="form-group">
<!-- Button -->
<div class="col-md-offset-3 col-md-9 text-center">
<button id="btn-signup" type="submit" class="btn btn-info"><i class="icon-hand-right"></i>Sign Up</button>
</div>
</div>
</form>
Replace this:
def employee = findByUsername(params.username);
with:
def employee = Employee.findByUsername(params.username);
All dynamic finder methods must be called statically on the type you expect them to return
I have gsp with two textfield for firstname-lastname and reCaptcha. What I want is for every wrong captcha code the user's input for firstname and last name won't be erased.
snippet for controller:
***captcha_code****
if (result) {
def person = new Person(params)
person.save()
render "Success!"
} else {
flash.message = message(code: 'forgotPassword.captcha.wrong')
redirect(controller:'person', action:'form')
}
snipper for form.gsp
***captcha_code_here***
<g:form controller="person" action="save">
<label>First Name: </label>
<g:textField name="firstName"/><br/>
<label>Last Name: </label>
<g:textField name="lastName"/><br/>
<g:if test="${flash.message}">
<div class="message" role="status" style="font-size: medium;color: green;">${flash.message}</div>
</g:if>
***captcha_code_here***
<g:actionSubmit value="Save"/>
To repopulate the fields you can use the same flash scope you're using for the message. On error, add the first and last name to the flash scope, and then in your GSP use those values when they are available:
PersonController
class PersonController {
def save() {
...
if(/* recaptcha failed */) {
flash.firstName = params.firstName
flash.lastName = params.lastName
}
...
}
}
GSP
<label>First Name: </label>
<g:textField name="firstName" value="${flash.firstName ?: ''}"/><br/>
<label>Last Name: </label>
<g:textField name="lastName" value="${flash.lastName ?: ''}"/><br/>
In Controller Action, send back fields that you want to be repopulated.
I'm trying to create simple form for saving post with it's relations.
Here is my domain models;
Post Model;
class Post {
String title
String teaser
String content
static belongsTo = [author: Person, category: Category]
static hasMany = [tags: Tag]
static constraints = {
}
}
Tag Model;
class Tag {
String name
static belongsTo = Post
static hasMany = [posts: Post]
static constraints = {
}
}
I've created a form for saving post object through html form;
<g:form controller="posts" action="save" method="post">
<div class="input">
<label for="post.title">Title:</label>
<g:textField name="post.title" />
</div>
<div class="input">
<label for="post.teaser">Teaser:</label>
<g:textField name="post.teaser" />
</div>
<div class="input">
<label for="post.content">Content:</label>
<g:textArea name="post.content" />
</div>
<div class="input">
<label for="post.content">Category:</label>
<g:select optionKey="id" optionValue="name" name="post.category" from="${categories}" noSelection="['':'-Choose Category-']"/>
</div>
<div class="input">
<label for="post.tags">Tags:</label>
<g:select optionKey="id" optionValue="name" name="post.tags" from="${tags}" noSelection="['':'-Choose Tags-']" />
</div>
<div class="input">
<g:submitButton name="Create" value="Create" />
</div>
</g:form>
And here is the controller logic;
def save() {
def post = new Post(params.post)
post.author = springSecurityService.currentUser
if(post.save()){
flash.message = "Post created successfully..."
redirect(action: "index", method: "GET")
}
else{
flash.error = "Something went wrong, please check the form again!"
[tags: Tag.list(), categories: Category.list()]
render(view: "create")
}
}
With this way i can't save tags for post object.
I solved the problem with
post.save(flush: true)
here is the documentation about
gorm save