Use server side form submission and validation for role crud

This commit is contained in:
Ramon Gutierrez 2018-01-10 04:42:13 +08:00
parent 277ac8e05b
commit aece8408e8
3 changed files with 139 additions and 37 deletions

View file

@ -8,6 +8,7 @@ use App\Entity\Role;
use Doctrine\ORM\Query;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\Validator\ValidatorInterface;
class RoleController extends BaseController
{
@ -103,10 +104,8 @@ class RoleController extends BaseController
return $this->render('role/form.html.twig', $params);
}
public function createSubmit(Request $req)
public function createSubmit(Request $req, ValidatorInterface $validator)
{
// TODO: validation
// create new row
$em = $this->getDoctrine()->getManager();
$row = new Role();
@ -115,17 +114,34 @@ class RoleController extends BaseController
$row->setID($req->request->get('id'))
->setName($req->request->get('name'));
$em->persist($row);
$em->flush();
// validate
$errors = $validator->validate($row);
// set success
$this->addFlash(
'success',
'Changes have been saved!'
);
// initialize error list
$error_array = [];
// response
return $this->redirectToRoute('role_list');
// add errors to list
foreach ($errors as $error) {
$error_array[$error->getPropertyPath()] = $error->getMessage();
}
// check if any errors were found
if (!empty($error_array)) {
// return validation failure response
return $this->json([
'success' => false,
'errors' => $error_array
], 422);
} else {
// validated! save the entity
$em->persist($row);
$em->flush();
// return successful response
return $this->json([
'success' => 'Changes have been saved!'
]);
}
}
public function update($id)
@ -136,6 +152,7 @@ class RoleController extends BaseController
$em = $this->getDoctrine()->getManager();
$row = $em->getRepository(Role::class)->find($id);
// make sure this row exists
if (empty($row))
throw $this->createNotFoundException('The item does not exist');
@ -146,14 +163,13 @@ class RoleController extends BaseController
return $this->render('role/form.html.twig', $params);
}
public function updateSubmit(Request $req, $id)
public function updateSubmit(Request $req, ValidatorInterface $validator, $id)
{
// TODO: validation
// get row data
$em = $this->getDoctrine()->getManager();
$row = $em->getRepository(Role::class)->find($id);
// make sure this row exists
if (empty($row))
throw $this->createNotFoundException('The item does not exist');
@ -161,16 +177,33 @@ class RoleController extends BaseController
$row->setID($req->request->get('id'))
->setName($req->request->get('name'));
$em->flush();
// validate
$errors = $validator->validate($row);
// set success
$this->addFlash(
'success',
'Changes have been saved!'
);
// initialize error list
$error_array = [];
// response
return $this->redirectToRoute('role_list');
// add errors to list
foreach ($errors as $error) {
$error_array[$error->getPropertyPath()] = $error->getMessage();
}
// check if any errors were found
if (!empty($error_array)) {
// return validation failure response
return $this->json([
'success' => false,
'errors' => $error_array
], 422);
} else {
// validated! save the entity
$em->flush();
// return successful response
return $this->json([
'success' => 'Changes have been saved!'
]);
}
}
public function destroy($id)

View file

@ -32,25 +32,25 @@
</div>
</div>
</div>
<form class="m-form m-form--fit m-form--label-align-right m-form--group-seperator-dashed" method="post" action="{{ row is defined ? url('role_update_submit', {'id': row.getId()}) : url('role_create_submit') }}">
<form id="row-form" class="m-form m-form--fit m-form--label-align-right m-form--group-seperator-dashed" method="post" action="{{ row is defined ? url('role_update_submit', {'id': row.getId()}) : url('role_create_submit') }}">
<div class="m-portlet__body">
<div class="form-group m-form__group row{{ error.id is defined ? ' has-danger' }}">
<label class="col-lg-3 col-form-label">Role ID:</label>
<div class="form-group m-form__group row no-border">
<label class="col-lg-3 col-form-label" data-field="id">
Role ID:
</label>
<div class="col-lg-9">
<input type="text" name="id" class="form-control m-input{{ error.id is defined ? ' form-control-danger' }}" value="{{ values.id is defined ? values.id : (row is defined ? row.getId()) }}">
{% if error.id is defined %}
<div class="form-control-feedback">{{ error.id }}</div>
{% endif %}
<input type="text" name="id" class="form-control m-input" value="{{ values.id is defined ? values.id : (row is defined ? row.getId()) }}">
<div class="form-control-feedback hide" data-field="id"></div>
<span class="m-form__help">Unique identifier for this role</span>
</div>
</div>
<div class="form-group m-form__group row{{ error.name is defined ? ' has-danger' }}">
<label class="col-lg-3 col-form-label">Name:</label>
<div class="form-group m-form__group row">
<label class="col-lg-3 col-form-label" data-field="name">
Name:
</label>
<div class="col-lg-9">
<input type="text" name="name" class="form-control m-input{{ error.id is defined ? ' form-control-danger' }}" value="{{ values.name is defined ? values.name : (row is defined ? row.getName()) }}">
{% if error.name is defined %}
<div class="form-control-feedback">{{ error.name }}</div>
{% endif %}
<input type="text" name="name" class="form-control m-input" value="{{ values.name is defined ? values.name : (row is defined ? row.getName()) }}">
<div class="form-control-feedback hide" data-field="name"></div>
<span class="m-form__help">Display name for this role</span>
</div>
</div>
@ -70,4 +70,73 @@
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
$(function() {
$("#row-form").submit(function(e) {
var form = $(this);
e.preventDefault();
$.ajax({
method: "POST",
url: form.prop('action'),
data: form.serialize()
}).done(function(response) {
// remove all error classes
removeErrors();
swal({
title: 'Done!',
text: 'Your changes have been saved!',
type: 'success',
onClose: function() {
window.location.href = "{{ url('role_list') }}";
}
});
}).fail(function(response) {
var errors = response.responseJSON.errors;
var firstfield = false;
// remove all error classes first
removeErrors();
// display errors contextually
$.each(errors, function(field, msg) {
var formfield = $("[name='" + field + "']");
var label = $("label[data-field='" + field + "']");
var msgbox = $(".form-control-feedback[data-field='" + field + "']");
// add error classes to bad fields
formfield.addClass('form-control-danger');
label.addClass('has-danger');
msgbox.html(msg).addClass('has-danger').removeClass('hide');
// check if this field comes first in DOM
var domfield = formfield.get(0);
if (!firstfield || (firstfield && firstfield.compareDocumentPosition(domfield) === 2)) {
firstfield = domfield;
}
});
// focus on first bad field
firstfield.focus();
// scroll to above that field to make it visible
$('html, body').animate({
scrollTop: $(firstfield).offset().top - 200
}, 100);
});
});
// remove all error classes
function removeErrors() {
$(".form-control-danger").removeClass('form-control-danger');
$("[data-field]").removeClass('has-danger');
$(".form-control-feedback[data-field]").addClass('hide');
}
});
</script>
{% endblock %}

View file

@ -124,7 +124,7 @@
swal({
title: 'Confirmation',
text: 'Are you sure you want to delete ' + id + '?',
html: 'Are you sure you want to delete <strong>' + id + '</strong>?',
type: 'warning',
showCancelButton: true
}).then((result) => {