Symfony2 - Issue getting correct id to show/{id} - php

I have a view page which is passed all my active alerts. On each displayed row, I have a show button so you can see the individual alert
{% for alert in alerts %}
<tr>
<td>{{ alert[0].id }}</td>
<td>{{ alert[0].alertStatus }}</td>
<td>
<input type="button" value="Show" data-url="{{ path('NickAlertBundle_show', {id: alert[0].id}) }}" onclick="show_alert( {{ alert[0].id }} )" id="show"/>
</td>
</tr>
{% endfor %}
So when the button is clicked, the javascript function show_alert is called.
function show_alert(id){
alert(id);
$.ajax({
type: "POST",
url: $("#show").attr('data-url'),
data: {id: id},
success: function(data) {
if(data){
}else{
alert("Unknown Error!");
}
},
error:function(){
alert(id);
}
});
}
Now I do an alert at the top of that function, and that alert always displays the correct id. I think the problem is with the url part of the ajax call. It calls the data-url which should be correct. This is what it should be calling
NickAlertBundle_show:
pattern: /show-alert/{id}
defaults: { _controller: NickAlertBundle:Alert:show }
requirements:
_method: GET|POST
id: \d+
So this should then call the controller action
public function showAction(Request $request, $id)
{
var_dump($id);
if($request->isXmlHttpRequest())
{
$id = (int)$request->request->get('id');
}
return new JsonResponse('test');
}
At this point though, the var_dump in this action always outputs the id of the last added alert, and not the selected alert. And when I display the alert, it always displays the latest added alert.
So what is causing it to get the latest alert id instead of the selected id? As I say, it initially gets the correct id, but at some point this changes.
Thanks

You shouldn't declare duplicated ids, like id="show" in your template, better use class or declare your ids like id="show_1 ... n"

Related

Returning value from ajax in vuejs

Im trying to pass an integer (id) to a function which calls an api. The api then checks if the id passed matches any data in the database and returns the name associated with the id. I'm using vue.js for this along side laravel. Below is my code.
<tr v-for="store in storeList" :key="store.id">
<td>{{ getNodeName(store.store_name) }}</td>
</tr>
getNodeName(nodeId)
{
axios.get('api/store/getNodeName/'+nodeId).then(function (response){
return response.data[0].name;
});
}
Now the question is how do I get the result to print inside the td tag. apparently return from ajax doesnt work and I tried pushing it all to an array and printing it again but it didnt work either.
thanks
Assuming your API works, the first thing you are doing wrong is that you are returning from the callback when the Promise is resolved and not from the getNodeName method.
One simple way to achieve what you want, is to loop through your storeList (assuming it's a prop) inside the mounted lifecycle hook (using arrow functions here)
...
<tr v-for="node in nodes" :key="node.id">
<td>{{ node.name }}</td>
</tr>
...
data() {
return {
nodes: []
};
},
mounted() {
this.storeList.forEach(store => this.getNodeName(store.store_name));
},
methods: {
getNodeName(nodeId) {
axios.get('api/store/getNodeName/' + nodeId)
.then(response => this.nodes.push({ id: nodeId, name: response.data[0].name }))
}
}
...
You probably also want to turn this into one API call if possible, since you are making storeList.length calls.
You can make a loop of storelist and get nodeId from there and then do the API calls.
<tr v-for="store in storeData" :key="store.id">
<td>{{store.name}} </td>
</tr>
data(){
return{
storeData : []
};
},
created(){
for(var i=0; i<this.storeList.length; i++){
axios.get('api/store/getNodeName/' + this.storeList[i].store_name)
.then(response => this.storeData.push({ id: this.storeList[i].store_name,
name: response.data[0].name
}))
}
}

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 }});
}
});

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]
}
});

Ajax on JQuery drag event

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()}}' }

Update a section of page from button click in table with laravel

I'm trying to figure out how to have a table where each row has data including a unique ID and an edit button. When the edit button is clicked I would like for another section of the page to show a form to edit the data on that line. So far I have something like:
//linePage.blade.php
<table>
#foreach($lineList as $line)
<tr>
<td>{{ $line->Name }}</td>
<td>Edit</td>
</tr>
#endforeach
</table>
#if (!empty($lineSelected))
{{-- show form --}}
#endif
//routes.php
Route::get('/LinePage/{lineSelected?}', 'Forms#linePage');
Route::post('/LinePage/{lineSelected?}', 'Forms#updateLinePage');
//Forms.php
public function linePage($lineSelected = NULL){
$data = array('lineSelected=>$lineSelected);
return View::make('Forms\linePage',$data);
}
public function updateLinePage($lineSelected = NULL){
$data = array('lineSelected=>$lineSelected);
return View::make('Forms\linePage',$data);
}
This is working for me but I feel like I'm making it more complicated than it needs to be. Am I going about this correctly? Also, I don't like how the address bar shows localhost/LinePage/LineName once the line is selected. Is it possible to somehow hide the data being passed within the page?
Thanks
a simpler method for this is to use Javascript (and/or) jQuery .
The basic idea is, when you click a button in the table, you will make an ajax request. In that ajax request, you have only the form for that particular lineName . In this way, the page will not be reloaded, and you won't get to change the URL, and it's more fast .
If you choose to do this with jQuery. You will have something like :
//linePage.blade.php
<table>
#foreach($lineList as $line)
<tr>
<td>{{ $line->Name }}</td>
<td>Edit</td>
</tr>
#endforeach
</table>
//in the footer somewhere, after you load query
<script>
$(function()
{
$('a.btn-line').click(function(event){
var id = event.target.id;
fieldName = id.split('-');
lineName = fieldName[1];
$.get(
"{{action('Forms#lineForm'}}?lineName="+lineName,
function(data){
$('div#line-form').html(data);
}
);
});
</script>
in your routes :
Route::get('/linePage/form/', 'Forms#lineFormPage');
and in your controller, you will return the view with only the form
Maybe this is not the easiest way to do, but you won't need to refresh every time you need to reload the form, + it keeps things more separated

Categories