Testing an AJAX call in phpunit / symfony, using client or crawler - ajax

I want to test a conroller which generates a page with a field that changes dynamically with ajax.
Here is the code of ajax:
<script>
var $groupeCompetence = $('#requete_prestataire_groupeCompetence');
// When sport gets selected ...
$groupeCompetence.change(function() {
// ... retrieve the corresponding form.
var $form = $(this).closest('form');
// Simulate form data, but only include the selected sport value.
var data = {};
data[$groupeCompetence.attr('name')] = $groupeCompetence.val();
// Submit data via AJAX to the form's action path.
$.ajax({
url : $form.attr('action'),
type: $form.attr('method'),
data : data,
success: function(html) {
// Replace current position field ...
$('#requete_prestataire_competence').replaceWith(
// ... with the returned one from the AJAX response.
$(html).find('#requete_prestataire_competence')
);
// Position field now displays the appropriate positions.
}
});
});
</script>
How can I call this code from phpunit using client or crawler?
I tried :
$this->client->request(
'POST',
'/',
array('requete_prestataire[groupeCompetence]' =>2),
array(),
array(),
array('HTTP_X-Requested-With' => 'XMLHttpRequest',
));
But it doesn't work.
Thanks a lot !

I found the solution :
you have to disable validation, and send the form as it was generated :
$crawler = $this->client->request('GET', '/');
$form = $crawler->selectButton('requete_prestataire_Rechercher')->form();
$form['requete_prestataire[groupeCompetence]'] = 2;
$form['requete_prestataire[competence]']->disableValidation()->select(50);
$crawler = $this->client->submit($form);
here is the explanation in doc :
doc symfony dom crawler component

Related

Detect forward or backward on popstate

I'm using ajax to load new post pages into the content section of my site and using pushstate to edit the url each time. I'm looking for a way to move when the forward and back buttons are clicked on the browser.
My thinking was to create an array of post id's adding one to the list every time I move forward
$(document).on("click", ".title[data-ajax='post']", function() {
$post_id = $(this).data("id");
$post_type = $(this).data("type");
$post_url = $(this).data("url");
var historyData = $(".wrapper").attr("data-history");
if (!historyData){
historyData = [];
}
else{
historyData = JSON.parse(historyData);
}
historyData.push({
id: $post_id,
type: $post_type,
url: $post_url
});
var data = {
action : 'new_ajax_'+ $post_type +'_template',
post_id : $post_id
};
$("#main").empty().hide();
$.ajax({
url : ajax_object.ajax_url,
type : 'post',
data : data,
success: function(html) {
$("#main").append(html);
history.pushState('data', '', $post_url);
$(".wrapper").attr("data-id", $post_id);
$(".wrapper").attr("data-history", JSON.stringify(historyData));
$("#main").fadeIn("fast");
}
});
});
But instead of this I want to create two seperate arrays for forward and back id's so when back is triggered, I can snag the last post id in the "back" array to get the content I need.
My question is how to detect forward or backward on popstate to achieve this or a better way in general to implement this.
$(window).on('popstate', function(event) {
<---detect direction---->
});

how to fill field values using ajax in yii2?

I am using ajax in yii2.
How to fill fields without submit form. Without submitting the validation is working, but how to add field value.
In below code $this->name is my field name.
if($this->statusOk){
$this->name = "gana";
}else{
return $this->addError('branch_code', ' code can’t be found');
}
you can set your value in save function(in model) or before saving your model(in controller) ,and use custom validation just for validation.
Try this,custom ajax
$(document).ready(function () {
$("body").on("blur", "#id", function () {
var data = $("#nameField").val();
$.ajax({
url : "validURL",
type : "post",
data : {"sortcode":data},
success: function (response)
{
var json_obj = $.parseJSON(response);
if(json_obj.errorMessage) {
// do something
}else {
// do something
}

$_FILES not working with ajax submit in woocommerce checkout

I am try to upload file on woocommerce checkout page but I am not able to upload file. I have also try to get value using print_r($_FILES) in create_order function in class-wc-checkout.php file but it will return blank array
When I have remove class checkout from checkout form then it will working fine (without ajax submit)
I want to submit form without ajax but I need ajax remain on checkout page because I have add some extra price using ajax (update price without refresh)
My ajax call to add extra fee.
jQuery('#PageCount').change(function () {
var state = jQuery('#PageCount').val();
var current_price = jQuery('#carttot').val();
var data = {
action: 'woocommerce_apply_state',
security: wc_checkout_params.apply_state_nonce,
state: state,
current_price: current_price
};
jQuery.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: data,
success: function (code) {
console.log(code);
if (code === '0') {
jQuery('body').trigger('update_checkout');
}
},
dataType: 'html'
});
return false;
});
and php code or woocommerce hooks to add extra fee
add_action('wp_ajax_woocommerce_apply_state', 'calculate_per_page', 10);
add_action('wp_ajax_nopriv_woocommerce_apply_state', 'calculate_per_page', 10);
function calculate_per_page() {
if (isset($_POST['state'])) {
global $woocommerce;
$weight = WC()->cart->cart_contents_weight;
$state = $_POST['state'];
$current_price = $_POST['current_price'];
$val = $current_price * $state -$current_price;
session_start();
$_SESSION['val'] = $val;
}
}
add_action('woocommerce_cart_calculate_fees', 'woo_add_cart_fee');
function woo_add_cart_fee() {
session_start();
$extracost = $_SESSION['val'];
WC()->cart->add_fee('Per page charges:', $extracost);
}
And my function to upload file..
add_action('woocommerce_checkout_update_order_meta', 'custom_checkout_field_update_order_meta');
function custom_checkout_field_update_order_meta( $order_id ) {
if ($_FILES['avatar']['name']) {
if ( ! function_exists( 'wp_handle_upload' ) ) {
require_once( ABSPATH . 'wp-admin/includes/file.php' );
}
$upload_dir = wp_upload_dir();
$path = $upload_dir['path'];
$fileName = $_FILES["avatar"]["name"];
$fileTmpLoc = $_FILES["avatar"]["tmp_name"];
$pathAndName = $path."/".$fileName;
$moveResult = move_uploaded_file($fileTmpLoc, $pathAndName);
update_post_meta( $order_id, 'uploaded_file_to_translate', $_FILES['avatar']['name']);
if ($_POST['billing_output_to_send'])
update_post_meta( $order_id, 'How do you want your translation sent to you?', esc_attr(htmlspecialchars($_POST['billing_output_to_send'])));
if ($_POST['PageCount'])
update_post_meta( $order_id, 'How many pages are in your documents?', esc_attr(htmlspecialchars($_POST['PageCount'])));
}
}
How it will possible?
$_FILES you can not get it at woocommerce_checkout_update_order_meta hook because of woocommerce serialize the form and submit form throw ajax,
as we know that form serialize can not submit files requests. but I have two solutions for doing this may be it work for you.
You can use a plugin woocommerce upload file in the checkout. you can easily find it on google
But if you want to upload custom files then you can use this
when onchange file fire an ajax and push file array in session when user checkout, get the files from the session and upload to the directory, and then destroy your session.
$('.fileupload').change(function(e){
var action = 'update_session_files';
e.preventDefault();
var fd = new FormData();
fd.append('action', action);
var files = $('input[name="file"]')[0].files[0];
fd.append('billing_artist_headshot', files);
$.ajax({
url: my_ajax_object.ajax_url,
type: 'post',
data: fd,
contentType: false,
processData: false,
success: function(response){
},
});
});
and ajax action
add_action( 'wp_ajax_nopriv_update_session_files', 'update_session_function' );
add_action( 'wp_ajax_update_session_files', 'update_session_function' );
function update_session_function(){
session_start();
$_FILES['billing_artist_headshot'];
// upload your file here with Wordpress and get the id.
}

How do I perform a jQuery ajax request in CakePHP?

I'm trying to use Ajax in CakePHP, and not really getting anywhere!
I have a page with a series of buttons - clicking one of these should show specific content on the current page. It's important that the page doesn't reload, because it'll be displaying a movie, and I don't want the movie to reset.
There are a few different buttons with different content for each; this content is potentially quite large, so I don't want to have to load it in until it's needed.
Normally I would do this via jQuery, but I can't get it to work in CakePHP.
So far I have:
In the view, the button control is like this:
$this->Html->link($this->Html->image('FilmViewer/notes_link.png', array('alt' => __('LinkNotes', true), 'onclick' => 'showNotebook("filmNotebook");')), array(), array('escape' => false));
Below this there is a div called "filmNotebook" which is where I'd like the new content to show.
In my functions.js file (in webroot/scripts) I have this function:
function showNotebook(divId) {
// Find div to load content to
var bookDiv = document.getElementById(divId);
if(!bookDiv) return false;
$.ajax({
url: "ajax/getgrammar",
type: "POST",
success: function(data) {
bookDiv.innerHTML = data;
}
});
return true;
}
In order to generate plain content which would get shown in the div, I set the following in routes.php:
Router::connect('/ajax/getgrammar', array('controller' => 'films', 'action' => 'getgrammar'));
In films_controller.php, the function getgrammar is:
function getgrammar() {
$this->layout = 'ajax';
$this->render('ajax');
}
The layout file just has:
and currently the view ajax.ctp is just:
<div id="grammarBook">
Here's the result
</div>
The problem is that when I click the button, I get the default layout (so it's like a page appears within my page), with the films index page in it. It's as if it's not finding the correct action in films_controller.php
I've done everything suggested in the CakePHP manual (http://book.cakephp.org/view/1594/Using-a-specific-Javascript-engine).
What am I doing wrong? I'm open to suggestions of better ways to do this, but I'd also like to know how the Ajax should work, for future reference.
everything you show seems fine. Double check that the ajax layout is there, because if it's not there, the default layout will be used. Use firebug and log function in cake to check if things go as you plan.
A few more suggestions: why do you need to POST to 'ajax/getgrammar' then redirect it to 'films/getgrammar'? And then render ajax.ctp view? It seems redundant to me. You can make the ajax call to 'films/getgrammar', and you don't need the Router rule. You can change ajax.ctp to getgrammar.ctp, and you won't need $this->render('ajax');
this is ajax call
$(function() {
$( "#element", this ).keyup(function( event ) {
if( $(this).val().length >= 4 ) {
$.ajax({
url: '/clients/index/' + escape( $(this).val() ),
cache: false,
type: 'GET',
dataType: 'HTML',
success: function (clients) {
$('#clients').html(clients);
}
});
}
});
});
This the action called by ajax
public function index($searchterm=NULL) {
if ( $this->RequestHandler->isAjax() ) {
$clients=$this->Client->find('list', array(
'conditions'=>array('LOWER(Client.lname) LIKE \''.$searchterm.'%\''),
'limit'=>500
));
$this->set('clients', $clients);
}
}
This is a function I use to submit forms in cakephp 3.x it uses sweet alerts but that can be changed to a normal alert. It's very variable simply put an action in your controller to catch the form submission. Also the location reload will reload the data to give the user immediate feedback. That can be taken out.
$('#myForm').submit(function(e) {
// Catch form submit
e.preventDefault();
$form = $(this);
// console.log($form);
// Get form data
$form_data = $form.serialize();
$form_action = $form.attr('action') + '.json';
// Do ajax post to cake add function instead
$.ajax({
type : "PUT",
url : $form_action,
data : $form_data,
success: function(data) {
swal({
title: "Updated!",
text: "Your entity was updated successfully",
type: "success"
},
function(){
location.reload(true);
});
}
});
});

dojo pass URL parameter into AJAX

I want to take URL parameter and pass to ajax function,
var queryParams = dojo.queryToObject(window.location.search.slice(1));
var data = dojo.toJson(queryParams, true);
console.log(data);
getCategory( data );
...
function getCategory(input){
dojo.xhrGet( {
// The following URL must match that used to test the server.
url: "http://js.localhost/dojo-release-1.5.0-src/json3.php",
handleAs: "json",
content: input,
on my URL parametetr, I pass in
?return_type=category&category_desc=Business2
when I view on firebug, the ajax request become ....
t?0=%7B&1=%0A&2=%09&3......
but data debug is correct, any idea what's wrong?
{ "return_type": "category",
"category_desc": "Business2" }
just found out that it doesn't need dojo.toJson
var queryParams = dojo.queryToObject(window.location.search.slice(1));
getCategory( queryParams );

Resources