I've been struggling for a few days with this issue and I really hope you can help me out.
I've created a plugin, which is located in:
'/wp-content/plugins/my-cool-plugin'.
My plugin allows users to post a custom post type via a form on a public page, basically anyone should be able to post something.
Using jQuery, I listen to when my frontend form is submitted and using Ajax I pass the data from the form to a php file to process it into a post.
This file is located at:
'/wp-content/plugins/my-cool-plugin/inc/processor.php'.
Below is the content of my processor file:
$var1= $_POST['some'];
$var2= $_POST['data'];
$new_post = array(
'post_type' => 'my_custom_post',
'post_status' => 'publish',
'mcp_1' => $var1,
'mcp_2' => $var2
);
$post_id = wp_insert_post( $new_post, $wp_error );
if ($wp_error == 'false'){
$post_url = get_permalink( $post_id );
echo $post_url;
}else {
// some sort of error
}
When I test my form, it results in the following error:
Call to undefined function wp_insert_post() on line ... which is the following line:
$post_id = wp_insert_post( $new_post, $wp_error );
Do I need to include something since I'm not in the WordPress 'scope' anymore?
Or is there another (much better) way for inserting custom posts from a front end form?
Why are you running the file out of wordpress scope? That is not the best practive. Instead you could run it in wordpress scope and user wordpress native ajax.
add_action('wp_ajax_yourplugin_create_post', 'yourplugin_create_post');
add_action('wp_ajax_nopriv_yourplugin_create_post', 'yourplugin_create_post');
function yourplugin_create_post() {
// your code here
}
Then you would need your ajax url to be passed from php to js:
function your_plugin_ajaxurl() {
?>
<script type="text/javascript">
var yourPluginAjaxUrl = "<?php echo admin_url('admin-ajax.php'); ?>";
</script>
<?php
}
add_action('wp_head','your_plugin_ajaxurl');
Then you can use your ajax request but you would need to indicate action:yourplugin_create_post and url = yourPluginAjaxUrl
Try adding
require(dirname(__FILE__) . '/wp-load.php');
It took me some time to process Nick's answer, but I finally got it to work! Like Nick said, I dropped using the process file because is was out of the scope of WordPress. I moved my post creation from my proces file to a new function in the plugin init file (my-cool-plugin.php), as Nick suggested. This resulted in the following new function:
add_action('wp_ajax_coolplugin_create_post', 'coolplugin_create_post');
add_action('wp_ajax_nopriv_coolplugin_create_post', 'coolplugin_create_post');
function coolplugin_create_post() {
$var1 = $_POST['some'];
$var2 = $_POST['data'];
$new_post = array(
'post_type' => 'my_custom_post',
'post_status' => 'publish'
'post_title' => 'Some title'
);
$post_id = wp_insert_post( $new_post, $wp_error );
// check if there is a post id and use it to add custom meta
if ($post_id) {
update_post_meta($post_id, 'mcp_1', $var1);
update_post_meta($post_id, 'mcp_2', $var2);
}
if ($wp_error == false){
$post_url = get_permalink( $post_id );
echo $post_url;
}else {
// some sort of error
}
}
I also had to change the way I inserted my custom values into the newly created post, because the wp_insert_post() function only accepts default post parameters (see the wp_insert_post documentation for these parameters).
Next to my insert/create post function I also had to make some adjustments to my javascript file, which retrieves the filled in data from my form. Therefore (as Nick suggested) I needed to pass my Ajax URL from PHP to JS by adding the following function to my-cool-plugin.php like this:
function your_plugin_ajaxurl() { ?>
<script type="text/javascript">
var coolPluginAjaxUrl = "<?php echo admin_url('admin-ajax.php'); ?>";
</script>
<?php }
add_action('wp_head','your_plugin_ajaxurl');
By adding the coolPluginAjaxUrl variable to the head I'm able to use the URL in my javascript to post the data to when my form is submitted, like this:
$( '#form' ).on( 'submit', function(e) {
var request;
e.preventDefault();
var val_one = $( '#val-one' ).val();
var val_two = $( '#val-two' ).val();
var formData = {
action: 'coolplugin_create_post',
some: val_one,
data: val_two,
};
request = $.ajax({
type: 'POST',
url: coolPluginAjaxUrl,
data: formData,
});
});
The formData holds the coolplugin_create_post action defined in PHP and the request is posted to the coolPluginAjaxUrl URL, defined in the head.
Thanks Nick for pointing me into the right direction and I hope that my solution will also help others. Please note that I've stripped my code of several security measures for others to easily understand how the code works.
Related
I am writing a plugin and the widget contains drop-down lists and needs to retrieve values for each successive drop-down list from the database using AJAX based on the previous drop-down list's selected value.
I am going off a slightly modified version of the code from the WordPress codex found here:http://codex.wordpress.org/AJAX_in_Plugins
For some reason the action function either isn't being called or the there is some error in my code:
// add action hooks
add_action('wp_footer', 'er_qm_ajax_handler' );
add_action('wp_ajax_repopulate_widget_club_type', 'repopulate_widget_club_type');
add_action('wp_ajax_nopriv_repopulate_widget_club_type', 'repopulate_widget_club_type');
// action for the wp_footer hook to insert the javascript
function er_qm_ajax_handler(){
?>
<script type="text/javascript" >
jQuery(document).ready(function($) {
jQuery('#widget_manufacturer').val('3').change(function(){
var manufacturer = $("#widget_manufacturer").val();
var data = {
action: 'repopulate_widget_club_type',
selected_manufacturer: manufacturer
};
// since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
jQuery.post(ajaxurl, data, function(response) {
alert('Got this from the server: ' + response);
});
});
});
</script>
<?php
}
// The action function
function repopulate_widget_club_type(){
die("Got to the action");
}
Not exactly sure what I am doing wrong as I am getting no response from the AJAX post, I know that the jQuery .change() is working as I set up some alert()'s to test it out once I altered the dropdown lists values.
Any thoughts and help will be greatly appreciated, thanks!
You need to define the value of ajaxurl like this:
var ajaxurl = '<?php echo admin_url( 'admin-ajax.php' ); ?>'
It's prefferable to define it in javascript's global scope so before this line:
jQuery(document).ready(function($) {
I have a sample code:
in default.php:
<?php
JHTML::_('behavior.mootools'); /* to load mootools */
$ajax = "
/* <![CDATA[ */
window.addEvent('domready', function() {
$('start_ajax').addEvent('click', function(e) {
e.stop();
var url = 'index.php?option=com_xxx&controller=xxx&task=updateAjax&format=raw';
var x = new Request({
url: url,
method: 'post',
onSuccess: function(responseText){
document.getElementById('ajax_container').innerHTML = responseText;
}
}).send();
});
})
/* ]]> */
" ;
$doc = &JFactory::getDocument();
$doc->addScriptDeclaration($ajax);
?>
And controller of default.php i using code:
function updateAjax() {
echo date('Y-m-d D H:i:s');
}
When i run code is error undefined method JDocumentRaw::addCustomTag(), how to fix it ?
I think you wrong in call jquery using for ajax:
$document =& JFactory::getDocument();
$document->addCustomTag("call jquery library or script other");
And you try:
if($document->getType() != 'raw'){
$document->addCustomTag("call jquery library or script other");
}
This is because you are setting the "format" parameter to "raw", usually by adding &format=raw to the end of the URL you are using to access your component. This triggers Joomla to use the JDocumentRaw renderer instead of the standard JDocument renderer. You can resolve this by choosing one of the following (whichever is more appropriate):
Remove the "format=raw" from the URL of the linked page and use an alternate method to get your page to display as expected, such as adding tmpl=component or template=system to the URL
Add a check for if "format" is set to raw, in which case do not add the scripts at all
Extend the JDocumentRaw class with your own which implements your own methods for adding scripts and use format=yourRendererName instead of format=raw
Hi guys Im trying to make a drop-down list of countries and when the user select a country that redirect to a specific page created dynamically actually i manage to make the redirection work using javascript, but i need to take more parameters to the method inside the controler like the county "id" with out exposing it on the uri, so is that possible using $_post also i should not use button submit.
this is my code
view page
<?php echo form_open('site/country');
$options = array();
$js = 'id="country" onChange="window.location.href= this.form.CTRY.options[this.form.CTRY.selectedIndex].value"';
$options['#'] = "(please select a country)" ;
foreach ($list as $row):
$value= site_url()."/site/country/".url_title($row->name);
$options[$value] = $row->name ;
endforeach;
echo form_dropdown('CTRY', $options,'',$js);
//$test =array ('number' => 10)
//echo form_hidden($test);
echo form_close();?>
this is my method in controller
function country($data)
{
echo 'this is taking you to county= '.$data;
}
Why don't you do something like #Joseph Silber described.
Use jQuery to perform an ajax request when the drop-down list is changed, also managing the redirect?
Something like;
$('#my-drop-down').change(function() {
$.ajax({
url: '/site/country',
type: 'post',
data: $("#my-form").serialize(),
success: function( response.redirect ) {
window.location.href = response.redirect;
},
error: function( response ) {
alert('Oops');
}
});
});
By using serilaize(), you can post all data from the form, or just add the parameters you want to pass.
E.g data: 'id='+$('#id').val()+'&country='+$('#country').val()
I have an admin page for a WordPress plugin that, thanks to the stackoverflow community, I've learned how to add ajax calls to all of the functions that add/delete/update questions and answers for the plugin to access.
To help visualize it:
The next step is to refresh the content after a successful ajax call. Of course I don't want to just re-load the page and I assume refreshing the entire page might cause the answer divs to collapse, which would be undesirable. So refreshing only the related content is best.
The list of questions is generated with the following call to the database:
<?php
$qresult = $wpdb->get_results("SELECT * FROM " . $wpdb->prefix . "ccd_ex_questions ORDER BY sort ASC");
$qcount = $wpdb->num_rows;
foreach( $qresult as $key => $qrow ) {
?>
<div id="question<?php echo $qrow->id; ?>" class="display-questions">
<form id="update-question-<?php echo $qrow->id; ?>" action="" method="post">
//question form and content
</form> {snip...}
and the answers are done similar and within the loop generating the list of questions:
<?php
$aresult = $wpdb->get_results("SELECT * FROM " . $wpdb->prefix . "ccd_ex_answers WHERE question_id = " . $qrow->id . " ORDER BY sort ASC");
foreach( $aresult as $key => $arow ) {
?>
<form id="update-answer-<?php echo $arow->question_id."-".$arow->id; ?>" action="" method="post">
//answer form and content
</form> {snip...}
The following is one of the jQuery functions using an ajax call to update content:
//Add New Answer
jQuery(document).ready(function($) {
$('.asubmitbutton').live("click", function(){
var thisasubmit = $(this).data('asubmit');
$(thisasubmit).submit(function(){
// Get the proper instance of the form fields for the variables
var answer = $(this).find('.answer').val();
var sort = $(this).find('.sort').val();
var correct = $(this).find('.correct').val();
var question_id = $(this).find('.question_id').val();
$.ajax({
type: 'POST',
url: ajaxurl,
data: {
action: 'ccd_ex_insert_answer',
answer: answer,
sort: sort,
correct: correct,
question_id: question_id
},
success: function(data, textStatus, XMLHttpRequest){
console.log(data);
console.log(answer);
console.log(sort);
console.log(correct);
},
error: function(MLHttpRequest, textStatus, errorThrown){
alert(errorThrown);
}
});
return false;
});
});
});
And while we're at it, here's the php function handling this ajax call:
//Add an answer
function ccd_ex_insert_answer() {
global $wpdb;
$wpdb->insert( $wpdb->prefix . 'ccd_ex_answers', array(
'answer' => $_POST['answer'],
'sort' => (int)$_POST['sort'],
'correct' => (bool)$_POST['correct'],
'question_id' => (int)$_POST['question_id']
)
);
}
add_action( 'wp_ajax_ccd_ex_insert_answer', 'ccd_ex_insert_answer' );
As is, everything works except that changes don't show until the next page re-load.
I presume that I need to add the functions to refresh the data into the success: handler, but I couldn't find an example that spoke to updating the content that is pulled from the database.
So my question is: How to refresh only the updated content after ajax call and, if possible, maintain the visibility of expanded divs?
Any help would be greatly appreciated! Note: I am barely an intermediate jQuery user and this is my first ajax attempt, so it's better to assume I know nothing if it prevents something important from shooting over my head. ;)
UPDATE: I think I am making progress, but still missing something. Problem with the proposed solution is that .html(data) was returning '0'. By removing the line: url: ajaxurl, from the ajax call, what is returned now is the entire page content. What I really need to be returned is just the updated content.
First, you want to do a POST to a page/url that will return only the updated content for a certain element (say, with id="id"). For example, you do a call
$.ajax({url:"http://example.com/newcontent.php", ...});
and the PHP page simply returns
<?php echo "thisisnewcontent"; ?>
You can then update the html of any DOM element with
$("css_selector").html(newContent); // newContent will contain "thisisnewcontent"
You should do this update in the ajax success function, where 'data' represents the data that you received from the server.
$.ajax({ ..., success: function(data, textStatus, XMLHttpRequest) {
$("#id").html(data);
});
You can read more about ajax() and html() here http://api.jquery.com/jQuery.ajax and here
http://api.jquery.com/html/
Good luck!
I have a form that is added through the nodeapi displayed only on view mode. Users can select an item from a select menu and their choice will automatically get saved to the database with a hook_menu callback on change. If the user has javascript disabled, it'll submit normally with the form api. This is all working fine, but now for security reasons I want to submit the ajax version via the form api too. My form_name_submit is simple like:
function mymodule_test_form_submit($form, &$form_state) {
global $user;
db_query("INSERT INTO {mymodule} (nid, uid, status, created) VALUES (%d, %d, %d, " . time() . ")", $form['#parameters'][2], $user->uid, $form_state['values']['mymodule_status']);
}
My ajax:
$('.mysubmit').css('display', 'none');
$('.myclass').change(function() {
$.ajax({
type: 'POST',
url: Drupal.settings.basePath + 'mymodule/set/' + $nid + '/' + $('.myclass').val(),
dataType: 'json',
data: { 'ajax' : true, 'form_build_id' : $('#mymodule-form input[name=form_build_id]').val() }
});
});
And my callback function:
function mymodule_set($nid, $status) {
$form_build_id = $_POST['form_build_id'];
$form_state = array('storage' => NULL, 'submitted' => FALSE);
$form = form_get_cache($form_build_id, $form_state);
$args = $form['#parameters'];
$form_id = array_shift($args);
$form['#post'] = $_POST;
$form['#redirect'] = FALSE;
$form['#programmed'] = FALSE;
$form_state['post'] = $_POST;
drupal_process_form($form_id, $form, $form_state);
}
Originally my callback function was about the same as my submit function, but now I'm trying to use the submit function with ajax as well. Is this the right way to use drupal_process_form? The form is grabbed from the cache, it get's validated and submitted if no errors? I'm using some code from this tutorial to apply to my situation: http://drupal.org/node/331941 There doesn't seem to be any examples of what I'm trying to do. I also have $form['#cache'] = TRUE; in my form function.
How does drupal_process_form compare the submitted values with the original form to check for integrity? Am I supposed to add my values to the form_state since the form state will be empty with ajax. Been stuck on this for a few days, hopefully someone has experience with this.
Thanks.
I had to do somenthing similar to you in the past and read the same tutorial you posted, unfortunately there isn't much information avalaible about this and it was headache for me to make it work. I don't remember well the details but I was taking a look to the code I wrote and here are a couple of suggestions that may work for you:
Do not submit the form using your own jQuery code, instead use the new "#ahah" property of form elements that can be used for calling your callback in the onchange of the select http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html/6#ahah
IF you are doing this in a node form, adding the #ahah property in a form alter may not work, I remember having seen an issue about this that wasn't solved at that moment. if this is the case, use this code for attaching the ahah binding, you'll not need "efect", "method" or "progress" since you just want to submit the form, not to change anything about it:
function YOURMODULE_form_alter(&$form, $form_state, $form_id) {
if ('YOURCONTENTTYPE_node_form' == $form_id) {
//the only way I could make it work for exisiting fields is adding the binding "manually"
$ahah_binding = array(
'url' => url('YOURCALLBACKPATH'),
'event' => 'change',
'wrapper' => 'FIELD-wrapper',
'selector' => '#FIELD',
'effect' => 'fade',
'method' => 'replace',
'progress' => array('type' => 'throbber'),
);
drupal_add_js('misc/jquery.form.js');
drupal_add_js('misc/ahah.js');
drupal_add_js(array('ahah' => array('FIELDd' => $ahah_binding)), 'setting');
//force the form to be cached
$form['#cache'] = TRUE;
}
}
Here is my callback function, note that it has some modifications from the tutorial you posted:
function YOURMODULE_js() {
// The form is generated in an include file which we need to include manually.
include_once 'modules/node/node.pages.inc';
// We're starting in step #3, preparing for #4.
//I have to add the 'rebuild' element, if not an empty node was created
$form_state = array('storage' => NULL, 'submitted' => FALSE, 'rebuild' => TRUE);
$form_build_id = $_POST['form_build_id'];
// Step #4.
$form = form_get_cache($form_build_id, $form_state);
// Preparing for #5.
$args = $form['#parameters'];
$form_id = array_shift($args);
$form_state['post'] = $form['#post'] = $_POST;
$form['#programmed'] = $form['#redirect'] = FALSE;
// if you want to do any modification to the form values, this is the place
// Step #5.
drupal_process_form($form_id, $form, $form_state);
// Step #6 and #7 and #8.
$form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
// Final rendering callback.
drupal_json(array('status' => TRUE, 'data' => $output));
}
As I said before there are details that I have forgot but maybe this will help you.
Good Luck.