Grails, Delete-button on same form as Update in edit-view - ajax

I'm trying to add a delete-button to my edit-form but have not found anything that works. Suggestions I've seen, is using AJAX, but I don't know how to make it.
I don't like to make another form below the existing one for "update" but it looks impossible to have the delete-button to the right of the update-button.
Any one having an idea...?
I tested this:
$( document ).ready( function() {
$('#delete_prod').on('click',function(event) {
alert('DELETE!!!');
var id=$(this).data('id');
var url="${createLink(controller: 'prodBuffer',action:'delete')}/"+id
$.ajax({
type: 'POST',
url: url,
success: function(data){
$('#results').html(data);
}
});
});
});
</script>
<span id="delete_prod" data-id="1">Delete<span>
But the alert will not be hit.

A button within existing form will act as submit button, you can look into <g:actionSubmit and submit it as a delete action that you then control in the contorller or use something like this - make something behave as a button then action it using ajax
<span id="deleteButton" data-id="${instance.id}">Delete<span>
<script>
$('#deleteButton').on('click',function() {
var id=$(this).attr('data-id');
var url="${createLink(controller: 'controller',action:'delete')}/"+id
$.ajax({
type: 'POST',
url: url,
success: function(data){
$('#results').html(data);
}
});
})
<script>

You could do the following.
Change your span to an <a> tag. It might be easier to handle the
different states it has, and easier to style if you use bootstrap or
similar frameworks.
Now to the code:
<form id="myForm">
<!-- your form fields here-->
<div>
<button type="submit">My update button</button> <!-- The normal buttons you´d use-->
Delete button <!-- your actual delete button -->
</div>
</form>
<div id="results"></div>
The html is quite simple and quite similar to what you might have. The difference being that I would prefer to reference my <a> via class instead of ID. Using <a> instead of <span> might make your code more manageable.
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script>
$(document).ready(function(){
$('.delete-button').on('click', function(event){
event.preventDefault(); //1
var deleteTarget = $(this).prop('href'); //2
if(confirm("Are you sure?")){ //3
$.post( //4
deleteTarget,
function successhandler(responseData){
$('#results').html(responseData);
}
);
}
});
});
</script>
As for the javascript, the following applies:
Prevent the default action for your <a>
Obtain the href of the clicked link
Add a confirmation, just in case
Send your data and manage your response

You can use a button group (bootstrap) and a single javascript ajax call to handle both buttons. We're using the id of the button to distinguish which action to call.
Your form will be different with regard to the data present, I've just used a hidden id field as an example below.
<script type="text/javascript">
$( document ).ready( function() {
$( '.itemAction' ).click(function (event) {
if ( confirm( 'Are you sure?' )) {
$.ajax({
url: "/prodBuffer/" + this.id,
type: "POST",
data: $( '#myForm' ).serialize(),
success: function ( data ) {
$( '#resultdiv' ).html( 'Success' );
window.setTimeout( function(){ location = '/prodBuffer/index' }, 2000 )
},
error: function(j, status, eThrown) { console.log( 'Error ' + eThrown ) },
complete: function() { console.log( 'Complete' ) }
});
}
});
});
</script>
<div id="resultdiv"></div>
<g:form name="myForm">
<g:hiddenField name="id" value="1" />
<div class="btn-group" role="group">
<button type="button" name="myUpdate" id="myUpdate" value="Update" class="itemAction btn btn-primary">Update</button>
<button type="button" name="myDelete" id="myDelete" value="Delete" class="itemAction btn btn-danger">Delete</button>
</div>
</g:form>
Controller:
def myUpdate() {
myService.update( params )
render (['success'] as JSON )
}
def myDelete() {
myService.delete( params )
render (['success'] as JSON )
}

I think you do not need to use Ajax for deletion, you can make a Delete button and code on your Domain's show page and controller (for show) like below which also give you a confirm alert. this call the delete method. Have a look.
Show page Code (show.gsp)
<g:form>
<fieldset class="buttons">
<g:hiddenField name="id" value="${prodBufferInstance?.id}" />
<g:link class="edit" action="edit" id="${prodBufferInstance?.id}"><g:message code="default.button.edit.label" default="Edit" /></g:link>
<g:actionSubmit class="delete" action="delete" value="${message(code: 'default.button.delete.label', default: 'Delete')}" onclick="return confirm('${message(code: 'default.button.delete.confirm.message', default: 'Are you sure?')}');" />
</fieldset>
</g:form>
Controller Code (for show page)
def show(Long id) {
def prodBufferIns = ProdBuffer.get(id)
if (!prodBufferIns) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'prodBufferIns.label', default: 'CustMeterReadingTemp'), id])
redirect(action: "list")
return
}
[prodBufferInstance: prodBufferIns]
}
Controller Code (Delete method)
def delete(Long id) {
def prodBufferIns= ProdBuffer.get(id)
if (!prodBufferIns) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'prodBuffer.label', default: 'prodBuffer'), id])
redirect(action: "list")
return
}
try {
prodBufferIns.delete(flush: true)
flash.message = message(code: 'default.deleted.message', args: [message(code: 'prodBuffer.label', default: 'prodBuffer'), id])
redirect(action: "list")
}
catch (DataIntegrityViolationException e) {
flash.message = message(code: 'default.not.deleted.message', args: [message(code: 'prodBuffer.label', default: 'prodBuffer'), id])
redirect(action: "show", id: id)
}
}

Related

Ajax call is being accidently triggered

I'm creating a login page and at the bottom of the pop-up form, there is another button that takes you to the registration page. The issue appears to be that when navigating to the new page it all sits under the original sign-in form which uses an ajax call to check if the user exists so when they try to submit the registration form it then calls that ajax call from the sign-in form.
Sign-in form
<div id="myForm">
<form onsubmit="return false;" id="loginForm">
<h1>Login</h1>
<label for="email"><b>Email</b></label>
<input type="email" id="email" placeholder="Enter Email" name="email" required>
<label for="psw"><b>Password</b></label>
<input type="password" id="psw" placeholder="Enter Password" name="psw" required>
<div id="message" class="alert-danger"></div>
<br />
<button type="submit" id="submit" class="btn">Login</button>
<button type="button" class="btn cancel" onclick="closeForm();">Close</button>
</form>
<div class="d-inline">
<button class="btn-info">#Html.ActionLink("User Registration", "SignUp", "SignUp_SignIn")</button>
</div>
</div>
Then the ajax call is
$(document).ready(function () {
$("form").on('submit', function (event) {
var data = {
'email': $("#email").val(),
'psw': $("#psw").val()
};
$.ajax({
type: "POST",
url: 'SignUp_SignIn/CredentialCheck',
data: data,
success: function (result) {
if (result == true) {
$("#message").text("Login attempt was successful");
}
else {
$("#message").text("Email/Password didn't match any results");
}
},
error: function () {
alert("It failed");
}
});
return false;
});
});
After looking at the comments I realized that the reason that the login form was being called from the layout.cshtml so when the ajax call was being called it was grabbing all the form tags that existed on any page that was loaded up. After changing the ajax so it was calling a specific id for the login form instead of form it allowed for proper actions to take place.
An example of what I'm refusing to
$(document).ready(function () {
$("form").on('submit', function (event) {
$.ajax({
type: "POST",
url: url,
data: data,
success: function (result) {
//Do stuff
}
});
});
});
The above will try to redirect you on the submit of any form that is loaded up, but if we go through and change the way it accesses the form like below then it will only work if the one specific form is submitted.
$(document).ready(function () {
$("#loginForm").on('submit', function (event) {
$.ajax({
type: "POST",
url: url,
data: data,
success: function (result) {
//Do stuff
}
});
});
});

Form post from partial view to API

I am trying to create an SPA application using Sammy. When I call #/entitycreate link, I return a partial view from Home controller which contains an html form to submit. Partial view comes as I expect but rest of it doesn't work. Below are my problems and questions, I'd appreciate for any help.
KO binding doesn't work in partial view, even though I did exactly how it's done in the default SPA project template (see home.viewmodel.js).
This one is the most critical: when I submit this form to my API with ajax/post, my model always comes back with a null value, therefore I can't create an entity via my API. I have tried with [FromBody] and without, model always comes null.
In some sense a general question, should I include Html.AntiForgeryToken() in my form and [ValidateAntiForgeryToken] attribute in my API action?
Partial View:
#model namespace.SectorViewModel
<!-- ko with: sectorcreate -->
<div class="six wide column">
<div class="ui segments">
<div class="ui segment">
<h4 class="ui center aligned header">Create New Sector</h4>
</div>
<div class="ui secondary segment">
<form id="entity-create-form" class="ui form" action="#/sectorcreatepost" method="post" data-bind="submit: createEntity">
<!-- I am not sure if I should include AntiForgeryToken for WebAPI call -->
<!-- Html.AntiForgeryToken() -->
<fieldset>
<div class="field required">
#Html.LabelFor(m => m.Name)
#Html.TextBoxFor(m => m.Name, new { data_bind = "value: name" })
</div>
<div class="ui two buttons">
<button class="ui positive button" type="submit">Create</button>
<button class="ui button" type="button" id="operation-cancel">Cancel</button>
</div>
</fieldset>
</form>
</div>
</div>
</div>
<!-- /ko -->
JS View Model:
function SectorCreateViewModel(app, dataModel) {
var self = this;
self.name = ko.observable("ko binding doesn't work");
self.createEntity = function () {
console.log("ko binding doesn't work");
}
Sammy(function () {
this.get("#sectorcreateget", function () {
$.ajax({
url: "/home/getview",
type: "get",
data: { viewName: "sectorcreate" },
success: function (view) {
$("#main").html(view);
}
});
return false;
});
this.post("#/sectorcreatepost",
function () {
$.ajax({
url: "/api/sectors",
type: "post",
data: $("#entity-create-form").serialize(),
contentType: "application/json; charset=utf-8",
success: function (response) {
console.log(response);
},
error: function (xhr, status, error) {
console.log(xhr);
console.log(status);
}
});
return false;
});
this.get("#/yeni-sektor", function () {
this.app.runRoute("get", "#sectorcreateget");
});
});
return self;
}
app.addViewModel({
name: "SectorCreate",
bindingMemberName: "sectorcreate",
factory: SectorCreateViewModel
});
API Action:
public HttpResponseMessage Post([FromBody]SectorViewModel model)
{
// model is always null, with or without [FromBody]
if (!ModelState.IsValid)
return Request.CreateResponse(HttpStatusCode.BadRequest);
// repository operations...
return response;
}
I have removed contentType: "application/json; charset=utf-8", from ajax request based on the article here. #2 is now resolved, #1 and #3 still remains to be answered.

AJAX Post to MVC Controller model every time empty

I am trying to send some data from a modal dialog to my controller with Ajax. But my modelfields are always null, but I enter my actionmethod in the controller.
This is a shortend version of my cshtml-file.
#model anmespace.MyModel
<form method="post" id="formID">
...
<div class="row">
<div class="col-md-5">#Resource.GetResource("MyModal", "Firstname")</div>
<div class="col-md-7"><input type="text" class="form-control" id="firstname" value="#Html.DisplayFor(model => model.FirstName)"></div>
</div>
...
<input type="submit" class="btn btn-primary" value="Submit" />
</form>
<script>
$("#formID").on("submit", function (event) {
var $this = $(this);
var frmValues = $this.serialize();
$.ajax({
cache: false,
async: true,
type: "POST",
url: "#Url.Action("ActionName", "Controller")",
data: frmValues,
success: function (data) {
alert(data);
}
});
});
</script>
Sorry MVC/Ajax are really new for me.
If you want to bind the form data to model then, the names of HTML elements should match with Model properties.
Note: name attribute value of html input field should match to the property of a model.
When you use form and submit button then it will try to reload the page by posting data to the server. You need to prevent this action. You can do this by returning false on onSubmit event in the Form element.
When you use jquery, do not forget to keep the ajax call/events inside the $(document).ready(function(){}) function.
I have written a simple code which takes First Name as input and makes an ajax call on clicking on submit button.
Html & Jquery Code:
<script>
$(document).ready(function() {
$("#formID").on("submit", function(event) {
var $this = $(this);
var frmValues = $this.serialize();
$.ajax({
cache: false,
async: true,
type: "POST",
url: "#Url.Action("PostData", "Home")",
data: frmValues,
success: function(data) {
alert(data.FirstName);
}
});
});
});
</script>
<div>
<form method="post" id="formID" onsubmit="return false;">
<input id="FirstName" name="FirstName"/>
<input type="submit" value="submit" />
</form>
</div>
My Model :
public class Person
{
public string FirstName { get; set; }
}
Action Method:
public ActionResult PostData(Person person)
{
return Json(new { Success = true, FirstName = person.FirstName });
}
Output:

React.js how to I go about getting data from my form and posting it

I'm currently learning React.js and am having trouble using a jquery or ajax call that returns the information in my form to a post. Basically what ever info is in the form, after submit, make a post of the data in a tag.
Here is my code:
var BasicInputBox = React.createClass({
render: function() {
return (
<div>
<label>{this.props.label}</label>
<br/>
<input type="text" onChange={this.props.valChange} value={ this.props.val} />
<br/>
</div>
);
}
});
var CommentBox = React.createClass({
render: function() {
return (
<div>
<label>Have a question?</label>
<br/>
<textarea type="text" onChange={this.props.valChange} value={ this.props.val} />
<br/>
</div>
);
}
});
var SubmitButton = React.createClass({
render: function() {
return (
<div>
<button type="submit" onClick={this.props.submit}>
Submit
</button>
</div>
);
}
});
var Contact = React.createClass({
getInitialState: function() {
return {}
},
submit: function(e) {
e.preventDefault()
console.log(this.state);
this.setState({
name: "",
email: "",
comment: ""
})
},
nameChange: function(e) {
this.setState({
name: e.target.value
})
},
emailChange: function(e) {
this.setState({
email: e.target.value
})
},
commentChange: function(e) {
this.setState({
comment: e.target.value
})
},
render: function() {
return (
<form>
<BasicInputBox label="Name:" valChange={this.nameChange} val={this.state.name}/>
<BasicInputBox label="Email:" valChange={this.emailChange} val={this.state.email}/>
<CommentBox valChange={this.commentChange} val={this.state.comment}/>
<SubmitButton submit={this.submit}/>
</form>
);
}
});
React.render(
<Contact></Contact>,
document.body
);
As #BinaryMuse noted the problem here is that your submit method is not really doing any submitting. You mentioned that the way you want to do this is via AJAX, and thus you need to 1) include jQuery (or Zepto) on your page, and 2) make the ajax call. Here is one way to accomplish the second part:
1)
First, you don't really need to provide the submit method as a property to the submit button. When the submit button is clicked inside a form, it will trigger the form's onSubmit event, so you can simply attach the this.submit method there.
Also, you don't really need I don't think to create a separate component for the Submit button. That kind of granularity may not be justified here since you can accomplish the same thing with far fewer lines of code. So I'd remove your SubmitButton component and update your Contact component render function to be:
render: function(){
return (
<form onSubmit={this.submit}>
<BasicInputBox label="Name:" valChange={this.nameChange} val={this.state.name}/>
<BasicInputBox label="Email:" valChange={this.emailChange} val={this.state.email}/>
<CommentBox valChange={this.commentChange} val={this.state.comment}/>
<button type="submit">Submit</button>
</form>
);
}
2) Next you can change your submit method in this way, adding an AJAX call. Depending on the details of the server/API to which you are sending the form you may need to modify the AJAX call a bit, but what I have put here is a fairly generic form that has a good chance of working:
submit: function (e){
var self
e.preventDefault()
self = this
console.log(this.state);
var data = {
name: this.state.name,
email: this.state.email,
comment: this.state.comment
}
// Submit form via jQuery/AJAX
$.ajax({
type: 'POST',
url: '/some/url',
data: data
})
.done(function(data) {
self.clearForm()
})
.fail(function(jqXhr) {
console.log('failed to register');
});
}
Note: that I also encapsulated the code you had previously for clearing the form inside its own function, which is called if the AJAX call returns a success.
I hope this helps. I put the code in a jsFiddle where you could test it a bit: https://jsfiddle.net/69z2wepo/9888/

generating pop up when button is clicked

when a submit button is clicked i want to generate a pop up showing the list of items. The code i tried to create pop up is as follows:`
Index View:
<script type="text/javascript">
$('#popUp').Hide();
$('#button').click(function () {
$('#popUp').click();
});
</script>
<div class="left-panel-bar">
#using (Html.BeginForm(FormMethod.Post))
{
<p>Search For: </p>
#Html.TextBox("companyName",Model);
<input id="button" type="submit" value="Submit" />
}
</div>
<div id="popUp">
#Html.ActionLink("Get Company List", "CreateDialog", "Company", null, new
{
#class = "openDialog",
data_dialog_id = "emailDialog",
data_dialog_title = "Get Company List"
});
</div>
but i got trouble using this code.. when i click the submit button it opens another page instead of popup. The controller code is as follows:
[HttpPost]
public ActionResult Index(Companies c)
{
Queries q1 = new Queries(c.companyName);
if (Request.IsAjaxRequest())
return PartialView("_CreateDialog", q1);
else
return View("CreateDialog", q1);
}
You could use AJAX:
<script type="text/javascript">
$(function() {
$('form').submit(function() {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function(result) {
$('#popUp').html(result);
}
});
return false;
});
});
</script>
<div class="left-panel-bar">
#using (Html.BeginForm())
{
<p>Search For: </p>
#Html.TextBox("companyName", Model);
<input id="button" type="submit" value="Submit" />
}
</div>
<div id="popUp">
</div>
Now ehn the form is submitted, an AJAX request will be sent to the Index POST action and since inside you test if the request was an AJAX request it will return the _CreateDialog.cshtml partial view and insert it into the #popUp div. Also it is important to return false from the form submit handler in order to cancel the default even which is to redirect the browser away from the current page.

Resources