pass id of foreign key to the form via post - javascript

I've created a new field ("responsavel") on my db for this entity ("Multa"), "responsavel" is a foreign key to another table (Usuario) and I want it to be shown on my form as an select with just some objects (that's why the $desligados I'm passing to the front) for the user to choose and then pass it to the back.
I've been able to do it with $.postbut I'm doing other things after the submit is passed to the controller so I've included a $(this).unbind('submit').submit(); but now it's like I'm submitting the form two times, and one of them is not submitting with the "responsavel" value.
This is my form:
class MultaType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('usuario')
->add('departamento')
->add('cliente')
->add('responsavel',null, ['attr'=>['style'=>'display:none;'], 'label'=> false])
->add('razaoSocial', null, ['label'=>'Cliente'])
->add('valor',null, ['label'=>'Valor Pago'])
->add('tipoPagamento', ChoiceType::class, ['choices'=>['Selecionar'=>0,'Integral'=>1,'Somente Encargos'=>2], 'required' => true], ['label' => 'Tipo de Pagamento'])
->add('dtRegistro', DateTimeType::class, ['widget'=>'single_text','input' => 'datetime','html5'=>false, 'label'=>'Data de Registro'])
->add('competencia', null, ['label'=>'Competência'])
->add('motivo', TextareaType::class, ['required'=>true])
->add('dtCiencia', DateTimeType::class, ['widget'=>'single_text','input' => 'datetime','html5'=>false, 'label'=>'Data de Ciência'])
->add('vistoCiencia', CheckboxType::class, ['label'=>'Ciente', 'required'=>false])
->add('nomeCliente', null, ['label'=>'Nome'])
->add('getRegistro', null, ['label'=>'CNPJ/CPF'])
->add('cpfCliente', null, ['label'=>'CPF'])
->add('cnpjCliente', null, ['label'=>'CNPJ'])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Multa::class,
'usuario' => Usuario::class,
]);
}
}
this is what I have on my controller:
/**
* #Route("/novo", name="multa_novo", methods={"GET","POST"})
*/
public function novo(PushNotification $push,
Request $request): Response
{
$multa = new Multa();
$form = $this->createForm(MultaType::class, $multa);
$form->remove('usuario');
$form->remove('departamento');
$form->remove('dtCiencia');
$form->remove('dtRegistro');
$form->remove('razaoSocial');
$form->remove('getRegistro');
if(in_array($this->getUser()->getAcesso(), [1,2,3,4,7,10]))
{
$desligados = $this->getDoctrine()->getRepository(Usuario::class)->findByAtivo(0);
}
else
{
$desligados = [];
}
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager = $this->getDoctrine()->getManager();
$multa->setUsuario($this->getUser());
$entityManager->persist($multa);
$entityManager->flush();
$this->addFlash('success', "Multa registrada com sucesso!");
- "HERE I HAVE OTHER THINGS I'M DOING AFTER THE SUBMIT..." -
return $this->redirectToRoute('multa_index');
}
return $this->render('multa/novo.html.twig', [
'entity' => $multa,
'form' => $form->createView(),
'coordenador' => $coordenador[0], //passando o primeiro objeto usuario encontrado para o front
'desligados' => $desligados
]);
}
what I'm doing on the front:
{% if desligados %}
<div class="col-lg-4 mb-3" data-intro="Nome do coordenador responsável pela ciência da multa." data-step="5">
<label>Responsável <i class=" ml-1 text-info icon-sm mdi mdi-information-outline" title="Caso o responsável pela multa ja tenha sido desligado." data-placement="top" data-toggle="tooltip"></i></label>
<select id="responsavel" name="multa[responsavel]" class="form-control">
<option></option>
{% for responsavel in desligados %}
<option value="{{responsavel.id}}">{{ responsavel.nomeCompleto }}</option>
{% endfor %}
</select>
</div>
{% else %}
...
$(function () {
$("#multaForm").submit(function(e) {
e.preventDefault();
e.stopPropagation();
var form = $("#multaForm").serializeObject(); //Envia todo o formuário
form['multa[responsavel]'] = $('#responsavel').val();
$.post( {% if __rota[1] == 'novo' %} "{{ path('multa_novo') }}" {% elseif __rota[1] == 'editar' %} "{{ path('multa_editar', {'id': entity.id } ) }}" {% else %} "{{ path('multa_aprovacao', {'id': entity.id } ) }}" {% endif %}, form, function( data ) {
}).fail(function(error) {
console.log(error);
});
$(this).unbind('submit').submit();
});
});
A example of one submit on my db:

As Jakumi recommended I used the EntityType::class to create a custom querybuilder, it returned what i wanted and as I'm using the formType to render all the fields I didn't needed to do anything on the frontend to pass it to my controller.

Related

404 error while implementing async function

detail.html
{% if request.user.is_authenticated %}
<form class="like-forms d-inline" data-book-id="{{ book.pk }}" data-review-id="{{ review.pk }}">
{% csrf_token %}
<h4>
{% if request.user in review.like_users.all %}
<button type="submit" id="btn-like-{{ review.pk }}" class="btn-none bi bi-emoji-heart-eyes"></button>
{% else %}
<button type="submit" id="btn-like-{{ review.pk }}" class="btn-none bi bi-emoji-angry"></button>
{% endif %}
</h4>
</form>
{% endif %}
<!-js-->
<script>
const likeForms = document.querySelectorAll('.like-forms')
const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value
likeForms.forEach((form) => {
form.addEventListener('submit', function (event) {
event.preventDefault()
const reviewId = event.target.dataset.reviewId
const bookId = event.target.dataset.bookId
axios({
method: 'post',
url: `/detail/${bookId}/like/${reviewId}/`,
headers: {'X-CSRFToken': csrfToken},
})
.then(response => {
const isLiked = response.data.isLiked
const likeBtn = document.querySelector(`#btn-like-${reviewId}`)
console.log(isLiked)
if (isLiked === true) {
likeBtn.classList.add('bi-emoji-heart-eyes')
likeBtn.classList.remove('bi-emoji-angry')
} else {
likeBtn.classList.add('bi-emoji-angry')
likeBtn.classList.remove('bi-emoji-heart-eyes')
}
})
.catch(error => {
console.log(error)
})
})
})
</script>
urls.py
path("detail/<int:book_pk>", views.detail, name="detail"),
path("detail/<int:book_pk>/like/<int:review_pk>", views.like, name="like"),
.....
views.py
def detail(request, book_pk):
reviews = Review.objects.order_by("-pk")
book = Book.objects.get(pk=book_pk)
context = {
"reviews": reviews,
"book": book,
}
return render(request, "review/detail.html", context)
def like(request, book_pk, review_pk):
review = Review.objects.get(pk=review_pk)
book = Book.objects.get(pk=book_pk)
if review.like_users.filter(pk=request.user.pk).exists():
review.like_users.remove(request.user)
is_liked = False
else:
review.like_users.add(request.user)
is_liked = True
data = {
"isLiked": is_liked,
}
return JsonResponse(data)
I got a 404 not found error while writing code for a "like" async function.
data-book-id="{{ book.pk }}" data-review-id="{{ review.pk }} in the form
I seem to get pk values ​​for books and book reviews, but I don't know what causes the 404 error.
Console error message : POST http://localhost:8000/detail/1/like/2/ 404 (Not Found)
I am running this on localhost (http://localhost:8000/)
Thanks for reading..!

Symfony 3/4 : delete a table row from a database through AJAX

I am a little bit stuck on my Symfony code.
Let me explain,
I have a todo-list table in my database containing :
An ID called : id
A name field called : todo
And 3 others fields that don't matter : "completed", "created_at", "updated_at".
Before going further : here is my codes,
The concerned Controller :
/**
* #Route("/todos/delete/{id}", name="todo.delete", methods={"POST"})
* #param Todo $todo
* #param ObjectManager $manager
* #param Request $request
* #return \Symfony\Component\HttpFoundation\RedirectResponse
*/
public function delete(Todo $todo, ObjectManager $manager, Request $request)
{
$manager->remove($todo);
$manager->flush();
if ( $request->isXmlHttpRequest()) {
return $this->redirectToRoute('todo.home', [
'id' => $todo->getId()
]);
}
throw $this->createNotFoundException('The todo couldn\'t be deleted');
}
The view :
{% extends 'base.html.twig' %}
{% block title %}Todos{% endblock %}
{% block content %}
<br>
<form action="{{ path('todo.create') }}" method="post">
<input type="hidden" name="token" value="{{ csrf_token('todo-create') }}"/>
<label for="todo">Todo</label>
<input type="text" id="todo" name="todo" class="form-control input-group-lg" placeholder="Create a new todo">
</form><br>
{% for todo in todos %}
{{ todo.todo }}
Update
x
{% if todo.completed %}
Completed !
{% else %}
Mark as completed
{% endif %}
<hr>
{% endfor %}
{% endblock %}
We focus on :
x
The JavaScript :
$(document).ready(function () {
$('.js-delete-todo').on('click', function (e) {
e.preventDefault();
var url = $(this).attr('href');
delTodo(url);
function delTodo(url) {
$.ajax({
type: "POST",
url: url
}).done(function (data) {
$('#id').remove();
}).fail(function () {
alert('Could not be deleted');
});
}
});
});
Actually,
Everything seems to work : it does a POST ajax request, and delete the row in my table in my database.
The only issue is that I have to hit F5 to see it.
How can I make it work without reloading the page nor hitting the F5 hotkey?
In your symfony code you should return JSON format like here.
Wrap your todo in container like this
{% for todo in todos %}
<div id="todo-{{todo.id}}">
// your todo staff here
</div>
{% endfor %}
Then change your javascript to
function delTodo(url) {
$.ajax({
type: "POST",
url: url
}).done(function (data) {
var id = JSON.parse(data).id;
$('#todo-' + id).remove();
}).fail(function ()
alert('Could not be deleted');
});
}

Using ajax to submit multiples form(s) in Symfony 3?

I'm trying to create a dynamic 2-step form using Jquery where in "step 1", I want to submit the form data without refreshing my page so that I can hide my html division containing my form and show the other representing my step 2 using Jquery.
The problem is that I'm using a collection of forms in my controller action like this:
public function indexAction(Request $request)
{
$user = $this->getUser();
$em = $this->getDoctrine()->getManager();
$repository = $em->getRepository('ATPlatformBundle:NoteDeFrais');
$form = $this->get('form.factory')->createBuilder(FormType::class)
->add('ndf', CollectionType::class,array(
'entry_type' => NoteDeFraisType::class,
'label' => false,
'allow_add' => true,
'allow_delete' => true,
))
->getForm();
And I'm getting the forms data submitted from like this:
if ($request->isMethod('POST') && $form->handleRequest($request)->isValid()
&& isset($_POST['next_button'])) {
$notesDeFrais = $form['ndf']->getData();
foreach ($notesDeFrais as $ndf) {
$ndf->setUser($user);
$em->persist($ndf);
}
$em->flush();
}
elseif (isset($_POST['validate_button'])) {
foreach ($listNdf as $ndf) {
$ndf->setSubmitted(true);
}
$em->flush();
}
So what I wanted to know is how to send my data via an ajax request and how to get them from my action. So far I tried to proceed like this but it (logically) doesn't work.
$("div#bloc_validation").css("display", "none");
$("#next_button").click(function(){
$(".form_ndf").each(function(){
$.post("{{ path('platform_homepage') }}",
{ndf: $(this).serialize()}, //My issue is here
function(){
alert('SUCCESS!');
}
);
});
$("div#form_bloc ").css("display", "none");
$("div#bloc_validation").css("display", "block");
});
Do you have any ideas ? Thanks in advance
The most basic approach is this:
add a javascripts block in your twig file with the content as below.
Change appbundle_blog in the first line inside the .ready() function in the name of your form. (Inspect your html to find it).
{% extends 'base.html.twig' %}
{% block body %}
{{ form_start(edit_form) }}
{{ form_widget(edit_form) }}
<input type="submit" value="Save Changes" />
{{ form_end(edit_form) }}
{% endblock %}
{% block javascripts %}
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous">
</script>
<script>
$(document).ready( function() {
var form = $('form[name=appbundle_blog]');
form.submit( function(e) {
e.preventDefault();
$.ajax( {
type: "POST",
url: form.attr( 'action' ),
data: form.serialize(),
success: function( response ) {
console.log( response );
}
});
});
});
</script>
{% endblock %}
If the form has been submitted you have to answer to an AJAX request. Therefore you could render another template..
/**
* Displays a form to edit an existing blog entity.
*
* #Route("/{id}/edit", name="blog_edit")
* #Method({"GET", "POST"})
*/
public function editAction(Request $request, Blog $blog)
{
$editForm = $this->createForm('AppBundle\Form\BlogType', $blog);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$this->getDoctrine()->getManager()->flush();
/* render some new content */
return $this->render('blog/ajax.html.twig', array(
'blog' => $blog,
));
}
return $this->render('blog/edit.html.twig', array(
'blog' => $blog,
'edit_form' => $editForm->createView(),
));
Or answer in JSON:
use Symfony\Component\HttpFoundation\JsonResponse;
/**
* Displays a form to edit an existing blog entity.
*
* #Route("/{id}/edit", name="blog_edit")
* #Method({"GET", "POST"})
*/
public function editAction(Request $request, Blog $blog)
{
$editForm = $this->createForm('AppBundle\Form\BlogType', $blog);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$this->getDoctrine()->getManager()->flush();
return new JsonResponse(array(
'status' => 'success',
// ...
));
}
return $this->render('blog/edit.html.twig', array(
'blog' => $blog,
'edit_form' => $editForm->createView(),
));
}
If you want you can even test if the request is an AJAX request or not:
if($request->isXmlHttpRequest()) {
// yes it is AJAX
}

Django is_valid() returning false

I'm trying to validate a simple form with Django and it seems that it always returns false. I'm sending the value of the form via AJAX to the views.py and also printing the value in the Javascript and the view.py just to be sure it passed correctly.
The views file:
def change_alphabet(request):
cipher = CaesarCipher()
x = cipher.getListLetter()
y = cipher.getListLetter()
if request.is_ajax() and request.method == "GET":
print("Inside CHANGE")
formKey = caesarKey(request.GET or None)
print("Valid or not: %r " % formKey.is_valid())
integerKey = int(request.GET.get('the_key'))
print(integerKey)
if formKey.is_valid():
print(request.GET.get('the_key'))
integerKey = int(request.GET.get('the_key'))
y = cipher.setCipherLetters(integerKey)
context = { 'x': x,
'y': y,
'formKey': formKey,
}
return render(request, "content/alteredAlphabet.html", context)
else:
print(formKey.errors)
context = { 'x': x,
'y': y,
'formKey': formKey,
}
return render(request, "content/alteredAlphabet.html", context)
The form:
class caesarKey(forms.Form):
key = forms.DecimalField(max_value = 26, min_value = 1, initial = 1, required = True, error_messages={'required' : 'Please input a valid key number!'}, widget=forms.NumberInput(attrs={'class' : 'form-control', 'placeholder' : 'Key'}))
The Javascript:
$("#keyButtonId").on({
click: function() {
var variable = document.getElementById('id_key');
console.log(variable.value)
$.ajax({
url: "/alteredAlphabet",
type: "GET",
data: {
CSRF: 'csrf_token',
the_key: $('#id_key').val()
},
success: function(json) {
// $('#id_key').val('0');
// console.log(json);
$('#letterSection').fadeOut('slow', function() {
$('#letterSection').html(json);
$('#letterSection').fadeIn(3000);
});
//document.getElementById('letterSection').value = json;
console.log("FUNCTION CALLED!");
}
});
}
});
The error that is printed is:
<ul class="errorlist"><li>key<ul class="errorlist"><li>Please input a valid key number!</li></ul></li></ul>
UPDATE:
Template code for rendering the form:
<label for="id_key">
Key:
</label>
<form onsubmit="return false;" method="GET" id="key-form">
{% csrf_token %}
<div class="col-sm-2 col-xs-5">
{{ formKey.key }}
</div>
<button name="action" id="keyButtonId" class="btn btn-primary" value="key">Key</button>
</form>
{% if formKey.errors %}
<div class="alert alert-danger" role="alert">
<strong>{{ formKey.key.errors }}</strong>
</div>
{% endif %}
Why is it always returning false? Am I missing an additional phase of bounding the data?
You're passing your key data as the_key in the Ajax, but the form is expecting just key.

Symfony2 and jquery checkbox

I want to use checkbox with symfony2. I want to update a field value in a table (0/1) dynamically using the checkbox value.
Here is my wrong code :
index.html.twig :
<div class="slider demo" id="slider-1">
{% if plate.share == true %}
<input type="checkbox" value="1" checked>
{% else %}
<input type="checkbox" value="1">
{% endif %}
</div>
<script type="text/javascript">
$("input[type='checkbox']").on('click', function(){
var checked = $(this).attr('checked');
if (checked) {
var value = $(this).val();
$.post("{{ path('plate_share', { 'id': plate.id }) }}", { value:value }, function(data){
if (data == 1) {
alert('the sharing state was changed!');
};
});
};
});
</script>
routing.yml
plate_share:
pattern: /{id}/share
defaults: { _controller: "WTLPlateBundle:Plate:share" }
PlateController.php:
public function shareAction($id)
{
if($_POST && isset($_POST['value'])) {
$link = mysql_connect('127.0.0.1', 'admin', 'wtlunchdbpass');
if (!$link) {
print(0);
}
mysql_select_db('wtlunch');
$value = mysql_real_escape_string($POST['value']);
$sql = "INSERT INTO table (value) VALUES ('$value')";
if (mysql_query($sql, $link)) {
print(1);
}
else {
print(0);
}
}
}
But this solution is wrong and not working.
Is it possible to create a form and submit it with only a checkbox?
Is there an idea? Thanks.
This for example the edit form action in the controller :
public function editAction($id)
{
$user = $this->container->get('security.context')->getToken()->getUser();
if (!is_object($user) || !$user instanceof UserInterface) {
throw new AccessDeniedException('This user does not have access to this section.');
}
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('WTLPlateBundle:Plate')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Plate entity.');
}
$editForm = $this->createEditForm($entity);
$deleteForm = $this->createDeleteForm($id);
return $this->render('WTLPlateBundle:Plate:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}

Categories

Resources