How to use Ajax in Symfony? - php

I have a page with a list of items and some controls that are used for searching/sorting these items. I want these controls to work dynamically, using Ajax, but I can't find a way to use it in Symfony.
In plain PHP, I had the JS file that collected the data, then sent it to a PHP file, which triggered specified method from a class. How can I do something like that in Symfony3? Only tutorial I found was for Symfony 1.x.

If you are in a form, you can do something like :
$(document).submit(function () {
var url = $('form').attr('action');
var data = $('form').serialize();
$.post(url, data, function (data) {
window.location.href = data.redirect;
})
.fail(function () {
$('form').replaceWith(data.form);
});
});
You just need to send the correct url :
$(document).on('click', 'a', function () {
var url = window.location.href;
$.get(url, function (data) {
$('.container').replaceWith(data);
});
});
It is also possible to use a routing generator, simply add: "friendsofsymfony/jsrouting-bundle": "dev-master" to your composer.json.
AppKernel.php :
new FOS\JsRoutingBundle\FOSJsRoutingBundle()
Then config it in your routing.yml :
fos_js_routing:
resource: "#FOSJsRoutingBundle/Resources/config/routing/routing.xml"
And finally use "expose" arg in your routing :
#Route("/{table}/index", name="beta.index", options={"expose"=true})
I use annotation routing
In your JS :
var url = Routing.generate('beta.index', { 'table': 'foo' });
Hope it'll help you :)

Related

JQUERY ajax to update field in laravel doesn't work

I am trying to update a field in laravel and it doesn't do anything, I tryed to trace the error checking if the fields are correct and the routes but I don't really know.
//js file
$(document).on('blur','#dato-anyadir',function(){
var atributo=$(this).parent().attr('name');
var id=$(this).parent().parent().attr('id');
var valor= $(this).val();
if($(this).val() == ''){
$(this).parent().html($(this).attr('placeholder'));
}else{
if(!comprobacionModificacion(atributo,valor)){
alert("hola");
alert(id);
alert("atributo " + atributo);
alert("valor " + valor);
$.ajax({
//This is the url
url: "/listar/modificar/"+id+"/"+atributo+"/"+valor,
method: "GET",
});
}
$(this).parent().html(valor);
}
});
//web routes
Route::get('/listar/modificar/{id}/{atributo}/{valor}', 'AnimalController#modificarAnimal');
//Controller php
public static function modificarAnimal($id,$atributo,$valor){
$animal = Animal::find($id);
$animal->$atributo = $valor;
$animal->save();
}
Any idea? It doesn't do anything when it reaches the controller
Firstly if you dont put this route in except list in VerifyCsrfToken middleware, you must to use:
$.ajaxSetup ({
headers: {
'X-CSRF-TOKEN': $ ('meta[name="csrf-token"]').attr ('content')
}
});
and ensure you have meta tag csrf-token on header
Then your ajax code not doing anything after get, valor not changed. so please lookup jquery ajax done method
I finally know what's happening, it was my fault ofcourse.
I didn't had the migrations so laravel tried to update the 'animals.updated_at' . A field that is created when you do the migrations.
My fault.
Thanks for the help!

How to make ajax call in yii2?

In yii version 1.14 we used
CHtml::ajaxlink
for ajax call what about in yii2?
You can make an ajax link like
Html::a('Your Link name','controller/action', [
'title' => Yii::t('yii', 'Close'),
'onclick'=>"$('#close').dialog('open');//for jui dialog in my page
$.ajax({
type :'POST',
cache : false,
url : 'controller/action',
success : function(response) {
$('#close').html(response);
}
});return false;",
]);
From: http://www.yiiframework.com/wiki/665/overcoming-removal-of-client-helpers-e-g-ajaxlink-and-clientscript-in-yii-2-0/
You can easily create and combine all such client helpers for your
need into separate JS files. Use the new AssetBundle and AssetManager
functionality with the View object in Yii2, to manage these assets and
how they are loaded.
Alternatively, inline assets (JS/CSS) can be registered at runtime
from within the View. For example you can clearly simulate the
ajaxLink feature using a inline javascript. Its however recommended if
you can merge where possible, client code (JS/CSS) into separate
JS/CSS files and loaded through the AssetBundle. Note there is no more
need of a CClientScript anymore:
$script = <<< JS
$('#el').on('click', function(e) {
$.ajax({
url: '/path/to/action',
data: {id: '<id>', 'other': '<other>'},
success: function(data) {
// process data
}
});
});
JS;
$this->registerJs($script, $position);
// where $position can be View::POS_READY (the default),
// or View::POS_HEAD, View::POS_BEGIN, View::POS_END
$.get( "' . Url::toRoute('controller/action') . '", { item: $("#idoffield").val()} ) /* to send the parameter to controller*/
.done(function( data )
{
$( "#lists" ).html( data );
})
and give lists id for div
<div id="lists"></div>
for more visit https://youtu.be/it5oNLDNU44
<?=yii\helpers\Url::toRoute("site/signup")?>

Contao 2.11 call to module via ajax

I have question about call to my module action via ajax.
I'd like call to class in my module via ajax. But best solution for me is call to clean class. Not extends Module.
I don't know hot can I make url without add article to database and add module to him.
I use JQuery instead mooTools but js framework is not important. Most important is call to php class by ajax.
I have ajax module. But if I call to ajax.php required is module id from tl_module table. I don't want use this table. (Ajax will be very often calling, I prefer to don't load all contao mechanism. It should be very fast).
Thanks in advance for answers.
I found the answer for Contao >3.x in a GitHub issuse(german)
At first do in your Front-end Template:
<script type="text/javascript">
var data = {};
data["REQUEST_TOKEN"] = "<?php echo REQUEST_TOKEN ?>";
$(document).ready(function(){
$("#trigger").click(function(event){
$.post(
'<?php echo \Contao\Environment::get('requestUri')?>',
data,
function(responseText) {
alert(responseText);
}
).fail(function( jqXhr, textStatus, errorThrown ){ console.log( errorThrown )});
event.preventDefault();
});
});</script>
Important is the
- data["REQUEST_TOKEN"] -> if you do not add it, the POST-request will not reach your module:
public function generate()
{
if ($_SERVER['REQUEST_METHOD']=="POST" && \Environment::get('isAjaxRequest')) {
$this->myGenerateAjax();
exit;
}
return parent::generate();
}
//do in frontend
protected function compile()
{
...
}
public function myGenerateAjax()
{
// Ajax Requests verarbeiten
if(\Environment::get('isAjaxRequest')) {
header('Content-Type: application/json; charset=UTF-8');
echo json_encode(array(1, 2, 3));
exit;
}
}
If you want to do the ajax via GET you do not need the reqest token but the jquery funktion $get();
I would suggest you to use Simple_Ajax extension.
In this case you dont need to use Database and you can do pretty much anything you can do normally with Jquery ajax calls.
It works with Contao 2.11 and you can call your php class with it.
I find it much easier to use than ajax.php .
You can get it from : https://contao.org/de/extension-list/view/simple_ajax.de.html
Copy SimpleAjax.php to Contao's root folder.
Go to [CONTAO ROOT FOLDER]/system/modules and create a php file like following :
class AjaxRequestClass extends System
{
public function AjaxRequestMethod()
{
if ($this->Input->post('type') == 'ajaxsimple' )
{
// DO YOUR STUFF HERE
exit; // YOU SHOULD exit; OTHERWISE YOU GET ERRORS
}
}
}
Create a folder called config with a php file like following ( You can hook you class to TL_HOOKS with class name - class method, simple_ajax will execute you method whenever a ajax call is made ):
$GLOBALS['TL_HOOKS']['simpleAjax'][] = array('AjaxRequestClass','AjaxRequestMethod'); // Klassenname - Methodenname
Now you can easily make ajax calls with simply posting data to SimpleAjax.php:
$.ajax({
type: "POST",
url: "SimpleAjax.php",
data: { type: "ajaxsimple" },
success: function(result)
{
//DO YOUR STUFF HERE
}

why .load is not refreshing php file on IE? [duplicate]

I have the following code making a GET request on a URL:
$('#searchButton').click(function() {
$('#inquiry').load('/portal/?f=searchBilling&pid=' + $('#query').val());
});
But the returned result is not always reflected. For example, I made a change in the response that spit out a stack trace but the stack trace did not appear when I clicked on the search button. I looked at the underlying PHP code that controls the ajax response and it had the correct code and visiting the page directly showed the correct result but the output returned by .load was old.
If I close the browser and reopen it it works once and then starts to return the stale information. Can I control this by jQuery or do I need to have my PHP script output headers to control caching?
You have to use a more complex function like $.ajax() if you want to control caching on a per-request basis. Or, if you just want to turn it off for everything, put this at the top of your script:
$.ajaxSetup ({
// Disable caching of AJAX responses
cache: false
});
Here is an example of how to control caching on a per-request basis
$.ajax({
url: "/YourController",
cache: false,
dataType: "html",
success: function(data) {
$("#content").html(data);
}
});
One way is to add a unique number to the end of the url:
$('#inquiry').load('/portal/?f=searchBilling&pid=' + $('#query').val()+'&uid='+uniqueId());
Where you write uniqueId() to return something different each time it's called.
Another approach to put the below line only when require to get data from server,Append the below line along with your ajax url.
'?_='+Math.round(Math.random()*10000)
/**
* Use this function as jQuery "load" to disable request caching in IE
* Example: $('selector').loadWithoutCache('url', function(){ //success function callback... });
**/
$.fn.loadWithoutCache = function (){
var elem = $(this);
var func = arguments[1];
$.ajax({
url: arguments[0],
cache: false,
dataType: "html",
success: function(data, textStatus, XMLHttpRequest) {
elem.html(data);
if(func != undefined){
func(data, textStatus, XMLHttpRequest);
}
}
});
return elem;
}
Sasha is good idea, i use a mix.
I create a function
LoadWithoutCache: function (url, source) {
$.ajax({
url: url,
cache: false,
dataType: "html",
success: function (data) {
$("#" + source).html(data);
return false;
}
});
}
And invoke for diferents parts of my page for example on init:
Init: function (actionUrl1, actionUrl2, actionUrl3) {
var ExampleJS= {
Init: function (actionUrl1, actionUrl2, actionUrl3) ExampleJS.LoadWithoutCache(actionUrl1, "div1");
ExampleJS.LoadWithoutCache(actionUrl2, "div2");
ExampleJS.LoadWithoutCache(actionUrl3, "div3");
}
},
This is of particular annoyance in IE. Basically you have to send 'no-cache' HTTP headers back with your response from the server.
For PHP, add this line to your script which serves the information you want:
header("cache-control: no-cache");
or, add a unique variable to the query string:
"/portal/?f=searchBilling&x=" + (new Date()).getTime()
If you want to stick with Jquery's .load() method, add something unique to the URL like a JavaScript timestamp. "+new Date().getTime()". Notice I had to add an "&time=" so it does not alter your pid variable.
$('#searchButton').click(function() {
$('#inquiry').load('/portal/?f=searchBilling&pid=' + $('#query').val()+'&time='+new Date().getTime());
});
Do NOT use timestamp to make an unique URL as for every page you visit is cached in DOM by jquery mobile and you soon run into trouble of running out of memory on mobiles.
$jqm(document).bind('pagebeforeload', function(event, data) {
var url = data.url;
var savePageInDOM = true;
if (url.toLowerCase().indexOf("vacancies") >= 0) {
savePageInDOM = false;
}
$jqm.mobile.cache = savePageInDOM;
})
This code activates before page is loaded, you can use url.indexOf() to determine if the URL is the one you want to cache or not and set the cache parameter accordingly.
Do not use window.location = ""; to change URL otherwise you will navigate to the address and pagebeforeload will not fire. In order to get around this problem simply use window.location.hash = "";
You can replace the jquery load function with a version that has cache set to false.
(function($) {
var _load = jQuery.fn.load;
$.fn.load = function(url, params, callback) {
if ( typeof url !== "string" && _load ) {
return _load.apply( this, arguments );
}
var selector, type, response,
self = this,
off = url.indexOf(" ");
if (off > -1) {
selector = stripAndCollapse(url.slice(off));
url = url.slice(0, off);
}
// If it's a function
if (jQuery.isFunction(params)) {
// We assume that it's the callback
callback = params;
params = undefined;
// Otherwise, build a param string
} else if (params && typeof params === "object") {
type = "POST";
}
// If we have elements to modify, make the request
if (self.length > 0) {
jQuery.ajax({
url: url,
// If "type" variable is undefined, then "GET" method will be used.
// Make value of this field explicit since
// user can override it through ajaxSetup method
type: type || "GET",
dataType: "html",
cache: false,
data: params
}).done(function(responseText) {
// Save response for use in complete callback
response = arguments;
self.html(selector ?
// If a selector was specified, locate the right elements in a dummy div
// Exclude scripts to avoid IE 'Permission Denied' errors
jQuery("<div>").append(jQuery.parseHTML(responseText)).find(selector) :
// Otherwise use the full result
responseText);
// If the request succeeds, this function gets "data", "status", "jqXHR"
// but they are ignored because response was set above.
// If it fails, this function gets "jqXHR", "status", "error"
}).always(callback && function(jqXHR, status) {
self.each(function() {
callback.apply(this, response || [jqXHR.responseText, status, jqXHR]);
});
});
}
return this;
}
})(jQuery);
Place this somewhere global where it will run after jquery loads and you should be all set. Your existing load code will no longer be cached.
Try this:
$("#Search_Result").load("AJAX-Search.aspx?q=" + $("#q").val() + "&rnd=" + String((new Date()).getTime()).replace(/\D/gi, ''));
It works fine when i used it.
I noticed that if some servers (like Apache2) are not configured to specifically allow or deny any "caching", then the server may by default send a "cached" response, even if you set the HTTP headers to "no-cache". So make sure that your server is not "caching" anything before it sents a response:
In the case of Apache2 you have to
1) edit the "disk_cache.conf" file - to disable cache add "CacheDisable /local_files" directive
2) load mod_cache modules (On Ubuntu "sudo a2enmod cache" and "sudo a2enmod disk_cache")
3) restart the Apache2 (Ubuntu "sudo service apache2 restart");
This should do the trick disabling cache on the servers side.
Cheers! :)
This code may help you
var sr = $("#Search Result");
sr.load("AJAX-Search.aspx?q=" + $("#q")
.val() + "&rnd=" + String((new Date).getTime())
.replace(/\D/gi, ""));

ajaxFileUpload on xhr.setRequestHeader is not a function

In my footer.php I have this code which i needed for my api references
<script type="text/javascript">
/** Override ajaxSend so we can add the api key for every call **/
$(document).ajaxSend(function(e, xhr, options)
{
xhr.setRequestHeader("<?php echo $this->config->item('rest_key_name');?>", "<?php echo $this->session->userdata('api_key')?>");
});
</script>
It works fine in my project without any error but when I started working on file upload and I'm using ajaxfileupload to upload file, I got this error whenever i upload the file.
TypeError: xhr.setRequestHeader is not a function
xhr.setRequestHeader("KEY", "123456POIUMSSD");
Here is my ajaxfileuplod program code:
<script type="text/javascript">
$(document).ready(function() {
var DocsMasterView = Backbone.View.extend({
el: $("#documents-info"),
initialize: function () {
},
events: {
'submit' : 'test'
},
test: function (e) {
e.preventDefault();
var request = $.ajaxFileUpload({
url :'./crew-upload-file',
secureuri :false,
fileElementId :'userfile',
dataType : 'json',
data : {
'title' : $('#title').val()
},
success : function (data, status)
{
if(data.status != 'error')
{
$('#files').html('<p>Reloading files...</p>');
refresh_files();
$('#title').val('');
}
alert(data.msg);
}
});
request.abort();
return false;
}
});
var x = new DocsMasterView();
});
</script>
Can anyone here fix my problem. Any suggestion/advice in order to solve my problem.
As I understand from your comments, setRequestHeaders works fine with regular ajax calls. At the same time it is not available when ajaxFileUpload is used. Most likely that is because transport method does not allow to set headers (for instance, in case when iframe is used to emulate upload of files in ajax style) . So, possible solution is to place a key into your form data:
$(document).ajaxSend(function(e, xhr, options)
{
if(xhr.setRequestHeader) {
xhr.setRequestHeader("<?php echo $this->config->item('rest_key_name');?>", "<?php echo $this->session->userdata('api_key')?>");
else
options.data["<?php echo $this->config->item('rest_key_name');?>"] = "<?php echo $this->session->userdata('api_key')?>";
});
Note: I'm not sure if options.data is a correct statement, just do not remember structure of options object. If proposed code does not work - try to do console.log(options) and how
to get an object with data that should be posted (it might be something like options.formData, I just do not remember exactly)
And on server side you will just need to check for key in headers or form data.

Categories