Ajax on JQuery drag event - php

I'm creating a nested list with data from database. On this list, I'm using the JQuery UI Drag effect. What I need to do is when the drag is over, it will update the database.
The list coints Professor's name and his ID, it has as sub-list with his classes, like:
John teaches Math & physics, Dwayne teaches English.
John
*Physics
*Math
Dwayne
*English
Let's say I want to give Math class to Dwayne. So I'll drag Math from John and drop it on Dwayne sub-list. It's working fine.
What I can't do is to make the update on database, because John no longer teaches Math instead John is going to teach it. So I need to make an update there or a delete+insert.
Obs: I'm using laravel
Here is my Code:
#extends('app')
#section('assets')
<script type="text/javascript" src="{{ URL::to('/js/jquery.mjs.nestedSortable.js') }}"></script>
#stop
#section('content')
<ol>
#foreach($professores as $prof)
<li data-id=" {{ $prof->id }}">
{{ $prof->nome }}
<ol class="list-disc">
#foreach($prof->disc as $disc)
<li data-id="{{ $disc->id }}">{{ $disc->nome }}</li>
#endforeach
</ol>
</li>
#endforeach
</ol>
<script type="text/javascript">
$(function(){
var old_teacher;
$('.list-disc').sortable({
connectWith: '.list-disc',
start: function (event, ui){
old_teacher = ui.item.parent().parent().attr('data-id');
},
stop: function (event, ui){
$.ajax({
type: "POST",
url: '{{ URL::to("/professor") }}',
data: {disc: ui.item.attr('data-id'), professor: ui.item.parent().parent().attr('data-id'), old: old_teacher},
success: function(data){
console.log(data);
}
});
}
});
})
</script>
#stop
With this currently code, When I drop the item I get:
Internal Server Error (500)
UPDATE
Route File:
Route::post('professor', [
'uses' => 'ProfessorController#postProfessorList'
]);
Controller File:
public function postProfessorList()
{
Professor::submit(Input::post('disciplina'), input::post('professor'), input::post('old'));
}
Log file: Update
local.ERROR: exception 'Symfony\Component\Debug\Exception\FatalErrorException' with message 'Call to undefined method Illuminate\Http\Request::post()' in F:\PathToProject\vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php:210

Internal Server Error (500) means that something is wrong with your server-side (laravel) code.
Can you provide us with the code which is used in POST: /professor ?
EDIT
You might want to check your logs in app/storage or storage/ (depending on the laravel version). They should give you a better description of the error that occurs.
Also, you should replace Input::post('...') with Input::get('...') laravel takes care of $_GET and $_POST variables automatically.
EDIT 2
The error you get is due to Laravels CSRF protection.
You will need to set the csrf token in your ajax request like that:
data: {disc: ....., _token: '{{csrf_token()}}' }

Related

How to Pass an array from Laravel Blade to a Vue Component in Laravel 6/Vue 2.6.*

I am passing an object from my controller to my blade.php.file. From there I use object notation to get the variables from my object which leaves me with an array. I then am trying to pass that array of data from my blade.php file to my vue component. I want to pass the entire array not just one index of it. As of right now when I try to pass the array I get the error htmlspecialchars() expects parameter 1 to be string, array given which makes sense because I am passing an array (which is what I want). How do I successfully pass an array of data from laravel blade to VUE?
blade.php file
<div id="app">
<draggable
draggable-table="{{ $table->vars }}">
</draggable>
</div>
VUE component
<template>
</template>
<script>
export default {
props: ['draggableTable'],
};
</script>
EDIT:
As suggested to me I added a : and json_encode in my blade fole table like so:
:draggable-table="{{json_encode($table->vars)}}">
But when I check my VUE console my component no longer shows and only root is shown with none of the array data passed in. (See photo)
2ND EDIT:
I am trying to do this via axios now. I added this to my component within the <script> tags
data(){
return{
table: this.draggableTable
}
},
methods: {
getData(){
axios.get(this.endpoint, {
table: this.table,
}).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
});
}
},
computed: {
endpoint(){
return window.location.protocol + "//" + window.location.host + '/users';
}
}
app.js
const app = new Vue({
el: '#app'
});
So now how to I pass the data from blade to VUE?
Thank you.
you have to add : in prop, live below code.
<div id="app">
<draggable
:draggable-table="{{ json_encode($table->vars) }}">
</draggable>
</div>
You can just send it as a JSON object and then parse it either in Vue or when accepting it as a prop.
<div id="app">
<draggable
:draggable-table=JSON.parse({{ json_encode($table) }})>
</draggable>
</div>
Why would you need to pass data from Blade to Vue if you are using an API call in Vue? Data is already available to you.

How can I extend template with custom javascript for modal window in the Sonata Admin (Symfony 3.3, PHP 7)?

I have an entity structure:
Deal --> DealCondition <-- Product
id id id
dealConditons product name
I have the admin sections:
DealAdmin:
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->add('dealConditions',
'sonata_type_collection',
[
'by_reference' => false,
'required' => false,
],
[
'edit' => 'inline',
'inline' => 'table',
'sortable' => 'position',
]);
...}
ProductConditionAdmin:
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->add('product','sonata_type_model');
}
ProductAdmin:
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->add('name', null);
}
On ProductAdmin page I need some javascript to my purposes, so I did this:
application.admin.product:
class: ...\ProductAdmin
tags:
- { name: sonata.admin, manager_type: orm, label_translator_strategy: "sonata.admin.label.strategy.underscore"}
arguments:
- ~
- ...\Product
- ~
calls:
- [setTemplates, [{
edit: ApplicationDealBundle:ProductAdmin:edit.html.twig}]]
And in edit.html.twig:
{% block javascripts %}
{{ parent() }}<script type="text/javascript">MyScript();</script>
{% endblock %}
Everything works when I open ProductAdmin as main page, but when I click "Add new product" button next to Product field on nested form DealConditions, the script doesn't exist.
How it looks
How can I add the script?
Thanks.
You may have resolved this issue by now, but I had the same problematic yesterday so I'll put how I've done if others come here.
There may be better / more elegant solutions but this works just fine for now. What I've done is to override the base edit_many_script.html.twig which manages the many-to-[one|many] association field popup
Copy paste the file from vendor and put it in your app/Resources/SonataAdminBundle/views/CRUD/Association directory (or create it).
You'll find inside the file this ajax call to retrieve the admin form for your entity :
// retrieve the form element from the related admin generator
jQuery.ajax({
url: a.attr('href'),
dataType: 'html',
success: function(html) {
Admin.log('[{{ id }}|field_dialog_form_edit] ajax success', field_dialog_{{ id }});
// populate the popup container
field_dialog_content_{{ id }}.html(html);
field_dialog_title_{{ id }}.html("{{ associationadmin.label|trans({}, associationadmin.translationdomain) }}");
Admin.shared_setup(field_dialog_{{ id }});
// capture the submit event to make an ajax call, ie : POST data to the
// related create admin
jQuery(document).on('click','#field_dialog_{{ id }} a', field_dialog_form_action_{{ id }});
jQuery('form', field_dialog_{{ id }}).on('submit', field_dialog_form_action_{{ id }});
// open the dialog in modal mode
field_dialog_{{ id }}.modal();
Admin.setup_list_modal(field_dialog_{{ id }});
}
});
You can add your script there. Note that it will be used by default for every many to X relations, so if you want your script to be loaded only in specific situations, you can test {{ associationadmin.label|trans({}, associationadmin.translationdomain) }} like the following:
// retrieve the form element from the related admin generator
jQuery.ajax({
url: a.attr('href'),
dataType: 'html',
success: function(html) {
Admin.log('[{{ id }}|field_dialog_form_edit] ajax success', field_dialog_{{ id }});
// populate the popup container
field_dialog_content_{{ id }}.html(html);
field_dialog_title_{{ id }}.html("{{ associationadmin.label|trans({}, associationadmin.translationdomain) }}");
Admin.shared_setup(field_dialog_{{ id }});
// capture the submit event to make an ajax call, ie : POST data to the
// related create admin
jQuery(document).on('click','#field_dialog_{{ id }} a', field_dialog_form_action_{{ id }});
jQuery('form', field_dialog_{{ id }}).on('submit', field_dialog_form_action_{{ id }});
// Custom JS for PopUpWidget Entity
if("{{ associationadmin.label|trans({}, associationadmin.translationdomain) }}" === "PopUpWidget"){
//your script
}
// open the dialog in modal mode
field_dialog_{{ id }}.modal();
Admin.setup_list_modal(field_dialog_{{ id }});
}
});

Ajax get request laravel 5.4 resource controller

I've been searching for similar question in a while but I couldn't find what would actually help my issue.
Using Laravel 5.4.
So I have a resource controller and its index method that returns a view with some data attached to it.
Then I want to make an ajax request from the view returned which is a search request.
e.preventDefault();
let q = $('#inputserver').val();
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
url: "/servers",
type: 'GET',
data: {'data': q},
success: function(response){
console.log('Successo');
}
})
That, for how a resource controller's methods are structured should invoke the index method, in which I want to identify if I have an Ajax request incoming.
If I do, I'll search with a query in an Eloquent Model for the data retrieved by the search form and of course I want to show only the matching results.
This is my controller code:
if(!$request->ajax()){
$colonna = 'id';
$servers = Server::orderBy($colonna, 'desc')->paginate(10);
return view('servers.index', array('servers' => $servers));
}
else{
$servers= Server::where('name', '=', $request->data)->paginate(10);
return view('servers.index', array('servers' => $servers));
}
The issue is that nothing is happening, so the ajax request isn't even considered, can someone help me with this? I'm almost sure the issue is some obvious things I forgot or didn't consider.
Thank you in advance, I'll edit if you would need some more info about it.
EDIT:
This is the route I have Route::resource('servers', 'ServerController');
EDIT2:
I'm sorry ids are in Italian, but I of course select them correctly when using jQuery.
<div class="input-group mb-2 mr-sm-2 mb-sm-0">
<div class="input-group-addon">
<span>
<i class="fa fa-search"></i>
</span>
</div>
{{Form::text('search', null, array('class' => 'form-control', 'id' => 'inputserver' , 'placeholder' => 'Cerca..'))}}
<span class="input-group-btn">
<button class="btn btn-default" type="button" id="cercaserver">Go!</button>
</span>
The blade file is messy.Try to create a form open and form close and make the button submit of type. And try to change your ajax to this:
$(document).ready(function() {
$('#cercaserver').on('submit', function (e) {
e.preventDefault();
var input = $('#inputserver').val();
$.ajax({
type: "GET",
url: './servers',
data: {input: input},
});
});
});
make sure you are loading jquery.
What do you mean by nothing's happening? What was shown in the console when the ajax request was fired?
Also, you're returning a view, you might want to return a json array of your results?
return $servers;
Laravel will automagically convert it into a JSON response
https://laravel.com/docs/5.4/responses#creating-responses
Or if you want to be specific:
return response()->json($servers);
https://laravel.com/docs/5.4/responses#json-responses
Edit:
I think I already know the problem, in your resource controller function index, is there a parameter called $request? It might be non existing and for sure will throw a 500 internal server error because you used it in your condition.

Laravel sessions with sweet alert Session Loops

I'm just confused about my code. But I really thought that my code is correct. I'm trying to use with() method in Laravel 5.1 and then return to a view, then the sweet alert appears if the session that has been set is exists. Please see my code below:
PageController.php
return redirect()->route('list.view')->with('sweetalert', 'List has been created!');
view.blade.php
#extends('layout.master')
#section('container')
#foreach($lists as $list)
<li>{{ $list->name }}</li>
#endforeach
#stop
master.blade.php
<div class="container">
// some markup here...
</div>
#if(Session::has('sweetalert'))
<script>
swal('Success!', '{{ Session::get('sweetalert') }}', 'success');
</script>
#endif
I only want it to appear once, but if I try to click the back button, the message appears again. I have also tried the ff. code but nothings change:
#if(Session::has('sweet'))
<script>
swal('Success!', '{{ Session::get('sweetalert') }}', 'success');
</script>
<?php Session::forget('sweetalert'); ?>
#endif
Little help here?
a flash message has to be trigerred otherwise it will not make sense as you will set it everytime for the view
however you can use this code wherever the trigger is
Please Note :- I am just trigerring it everytime
Route::get('/', function () {
session()->flash('testing', 'I see this'); // Please have this line inside the trigger so the session does not get created everytime the view is called
return view('welcome');
});
Hope this helps

Laravel delete link for items within a foreach loop

I am attempting to delete an item within a foreach loop. In this loop, there are several images within $property. For each image ($propimg), I want to delete each image using it's id. However the link doesn't work. How do I get it to delete the individual image?
#foreach($property->images as $propimg)
<li>{{ $propimg->id }}<br/>{{ $propimg->image_url }}</li>
Delete
#endforeach
You need to perform an Ajax request, please try this:
$("[data-method='delete']").click(function(event) {
event.preventDefault();
$.ajax({
type: "DELETE",
url: $(this).prop("href")
}).always(function () {
location.reload();
});
});
If you get 500 HTTP error, due to CSRF token mismatch, please add this:
$.ajaxSetup({
headers: {
"X-XSRF-TOKEN": document.cookie.match('(^|; )XSRF-TOKEN=([^;]*)')[2]
}
});

Categories