I have a main php file and a javascript file. I want to update each field in my form by using jQuery/AJAX. I have all the right database update sql, etc. It's my jQuery that is wrong. I have a table tahts called profiles. Here are the column names:
As of now, when I click the update button, it redirects me to a blank page, with the updated information displayed in the page url. When I check my database, nothing has been saved.
This is a wordpress plugin
Here is my code
jQuery update
jQuery(document).ready(function ($) {
eventHandlers = function () {
$('#cm-list').delegate('.update', 'click', function (event) {
event.preventDefault();
var row = $(this).parent()[0],
htmid = row.id,
id = htmid.replace('no_', ''),
fname = $('.fname', row).val(),
lname = $('.lname', row).val(),
sex = $('.sex', row).val(),
nationality = $('.nation', row).val(),
position = $('.position', row).val(),
json = { 'id': id, 'fname': fname, 'lname': lname, 'sex': sex, 'nationality': nation, 'position': position };
if (fname.length > 1) {
$.post(ajaxurl, { action: 'updateprofile', 'pro_data': json }, function (data) {
if (data) {
$.jGrowl(custom.profile_name + fname + lname + custom.edited, { header: custom.yes });
}
});
}
else {
$.jGrowl(custom.err, { header: custom.no });
}
});
},
cm_init = function () {
eventHandlers();
};
cm_init();
});
Php code just to show you my sql
My function updateprofile() is inside __construct()
add_action(wp_ajax...... ajax hooks
function update() {
if (!isset($_POST['pro_data'])) {
return;
}
$this->db_update($_POST['pro_data']);
}
function db_update($input) {
global $wpdb;
$result = $wpdb->update($wpdb->prefix . CM_PROTBL,
array('fname' => $input->fname,
'lname' => $input->lname,
'sex' => $input->sex,
'nationality' => $input->nationality,
'position' => $input->position
),
array('id' => $input->id),
array('%s',
'%s',
'%s',
'%s',
'$s'
),
array('%d')
);
if ($this->return_result($result)) {
$this->renderprofile($input);
}
}
function renderprofile($input) {
$output = array(
'fname' => $input->fname,
'lname' => $input->lname,
'sex' => $input->sex,
'nationality' => $input->nationality,
'position' => $input->position
);
$this->renjson($output);
}
Unable to find answers for this so any help is appreciated!
Edit: At the moment, no errors with the jQuery. When I click the update button. It brings me to a blank page, with the url containing the information I submitted, which is useless to me. I want it to update instantly and alert the user, etc.
Edit: Getting uncaught syntaxerror: unexpected token if now, If I take out the semi-colon. If I leave it in after the json variable, it gives me unexpected token error, how to solve this?
Edit: I have now fixed this error, it was my mistake, I had an extra bracket. It's not going to a white blank page now. The text is coming up, e.g. Profile John has been modified. But still nothing has changed in the database.
Related
How do you target the sub-fields inside a repeater field, so the JS applies to the sub-field when appending new groups???
Been looking, but I got really lost as to where even to start. And the JavaScript API is falling a little short on explaining how to work with repeaters.
I'm working on a form to add orders for a bakery. The form has a repeater which holds the options for each different bread order. In here the select field for TYPE OF DOUGH does much of the pre-selection for the other fields (size, shape, extras).
I've managed to target the select field of TYPE OF DOUGH to send and modify data through AJAX, but when adding another repeater row the code doesn't work.
Here's my code for php and js.
JS
jQuery(document).ready(function ($) {
// field key for TYPE OF DOUGH select field inside repeater field
var field = acf.getField("field_609b103fcd576");
field.on("change", function (e) {
var value = field.val();
console.log(value);
var data = {
"action": "get_size_options",
"type_of_dough": value,
};
$.ajax({
url: ajax_object.ajax_url,
type: "post",
data: data,
dataType: "json",
success: function (data) {
console.log(data);
},
});
});
});
PHP
// enqueue the scripts
function fw_acf_register_scripts() {
// enqueue js file with ajax functions
wp_enqueue_script(
'acf-ajax-script',
get_template_directory_uri() . '/assets/js/autopopulate.js',
['jquery']
);
wp_localize_script(
'acf-ajax-script',
'ajax_object',
['ajax_url' => admin_url('admin-ajax.php')]
);
}
add_action('acf/input/admin_enqueue_scripts', 'fw_acf_register_scripts');
// ex. function to get options for the other fields
function get_size_options() {
$meta_value = fw_get_term_id($_POST['type_of_dough'], 'dough');
// just a function to get the ID for the taxonomy from the slug,
// so it just returns a number, say 501 which is then used for the term query
$size_options = array();
$terms_args = array(
'taxonomy' => 'size',
'hide_empty' => false,
'meta_key' => 'tax_position',
'orderby' => 'tax_position',
'order' => 'ASC',
);
if ($meta_value_masa) {
$terms_args['meta_query'] = array(
array(
'key' => 'dough',
'value' => $meta_value,
'compare' => 'LIKE',
),
);
}
$terms = get_terms($terms_args);
foreach ($terms as $term) {
$size_options[$term->term_id] = $term->name;
}
wp_send_json($size_options);
die();
}
add_action('wp_ajax_get_size_options', 'get_size_options');
I am having some difficulties with trying to add to cart with custom data from the front end.
My current PHP from the backend is as follows - this is placed in my functions.php for my child-theme (This code is from the following post: Adding a product to cart with custom info and price - considering I am indeed a PHP-noobie):
<?php // This captures additional posted information (all sent in one array)
add_filter('woocommerce_add_cart_item_data','wdm_add_item_data',1,10);
function wdm_add_item_data($cart_item_data, $product_id) {
global $woocommerce;
$new_value = array();
$new_value['_custom_options'] = $_POST['custom_options'];
if(empty($cart_item_data)) {
return $new_value;
} else {
return array_merge($cart_item_data, $new_value);
}
}
// This captures the information from the previous function and attaches it to the item.
add_filter('woocommerce_get_cart_item_from_session', 'wdm_get_cart_items_from_session', 1, 3 );
function wdm_get_cart_items_from_session($item,$values,$key) {
if (array_key_exists( '_custom_options', $values ) ) {
$item['_custom_options'] = $values['_custom_options'];
}
return $item;
}
// This displays extra information on basket & checkout from within the added info that was attached to the item.
add_filter('woocommerce_cart_item_name','add_usr_custom_session',1,3);
function add_usr_custom_session($product_name, $values, $cart_item_key ) {
$return_string = $product_name . "<br />" . $values['_custom_options']['description'];// . "<br />" . print_r($values['_custom_options']);
return $return_string;
}
//This adds the information as meta data so that it can be seen as part of the order (to hide any meta data from the customer just start it with an underscore)
add_action('woocommerce_add_order_item_meta','wdm_add_values_to_order_item_meta',1,2);
function wdm_add_values_to_order_item_meta($item_id, $values) {
global $woocommerce,$wpdb;
wc_add_order_item_meta($item_id,'item_details',$values['_custom_options']['description']);
wc_add_order_item_meta($item_id,'customer_image',$values['_custom_options']['another_example_field']);
wc_add_order_item_meta($item_id,'_hidden_field',$values['_custom_options']['hidden_info']);
}
and then I have a button on the frontend that runs the following script when pressed - this runs on a custom wordpress post where I have scripted have done some scripting in the background that collects information based on the users actions on the post:
function cartData() {
var metaData = {
description: 'My test Description'
another_example_field: 'test'
};
var activeVariationId = 10335;
var data = {
action: 'wdm_add_item_data',
product_id: 10324,
"add-to-cart": 10324,
quantity: 1,
variation_id: activeVariationId,
cart_item_data: metaData
};
$.ajax({
type: 'post',
url: wc_add_to_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'add-to-cart' ),
data: data,
beforeSend: function (response) {
//$thisbutton.removeClass('added').addClass('loading');
},
complete: function (response) {
//$thisbutton.addClass('added').removeClass('loading');
},
success: function (response) {
if (response.error & response.product_url) {
window.location = response.product_url;
return;
} else {
alert('ajax response recieved');
jQuery( document.body ).trigger( 'added_to_cart', [ response.fragments, response.cart_hash ] );
}
},
});
}
Unfortunately this only seems to add my current variation of the product to the to cart without any more custom information. Any help with nesting in this issue would be highly appreciated. If you need any more information and/or code examples I'd be happy to supply it :)
I think that I might have solved it, or at least parts of it with this PHP (this is really just a small modification of this code - adding $cart_item_data https://quadmenu.com/add-to-cart-with-woocommerce-and-ajax-step-by-step/):
add_action('wp_ajax_woocommerce_ajax_add_to_cart', 'woocommerce_ajax_add_to_cart');
add_action('wp_ajax_nopriv_woocommerce_ajax_add_to_cart', 'woocommerce_ajax_add_to_cart');
function woocommerce_ajax_add_to_cart() {
$product_id = apply_filters('woocommerce_add_to_cart_product_id', absint($_POST['product_id']));
$quantity = empty($_POST['quantity']) ? 1 : wc_stock_amount($_POST['quantity']);
$variation_id = absint($_POST['variation_id']);
// This is where you extra meta-data goes in
$cart_item_data = $_POST['meta'];
$passed_validation = apply_filters('woocommerce_add_to_cart_validation', true, $product_id, $quantity);
$product_status = get_post_status($product_id);
// Remember to add $cart_item_data to WC->cart->add_to_cart
if ($passed_validation && WC()->cart->add_to_cart($product_id, $quantity, $variation_id, $cart_item_data) && 'publish' === $product_status) {
do_action('woocommerce_ajax_added_to_cart', $product_id);
if ('yes' === get_option('woocommerce_cart_redirect_after_add')) {
wc_add_to_cart_message(array($product_id => $quantity), true);
}
WC_AJAX :: get_refreshed_fragments();
} else {
$data = array(
'error' => true,
'product_url' => apply_filters('woocommerce_cart_redirect_after_error', get_permalink($product_id), $product_id));
echo wp_send_json($data);
}
wp_die();
}
Where this is part of the JS-function:
var data = {
action: 'woocommerce_ajax_add_to_cart',
product_id: 10324,
quantity: 1,
variation_id: activeVariationId,
meta: metaData
};
$.ajax({
type: 'post',
url: wc_add_to_cart_params.ajax_url,
data: data, ...........
I am going to have to test it some more, as it seems now that all the data-fields also gets posted in the cart, email etc - I probably have to rewrite something so that some parts of it is hidden for the "non-admin", but available for me later on + adding custom product thumbnail on add to cart.
I have two entity dropdowns field in my symfony form. On the front end i change the option list of 2nd drop drown using ajax based on the value of first dropdown selected value. and Upon submitting the form i get the error that,
This value is not valid.
below is the code;
/**
* #ORM\ManyToOne(targetEntity="State")
* #ORM\JoinColumn(name="province_id", referencedColumnName="id")
*/
protected $Province;
/**
* #ORM\ManyToOne(targetEntity="District")
* #ORM\JoinColumn(name="district_id", referencedColumnName="id")
*/
protected $District;
and in the form,
->add('domicileDistrict','entity', [
'label' => ucwords('District'),
'class'=>'GeneralBundle\Entity\District',
'required' => true,
'mapped' => true,
'attr' => ['class' => 'form-control'],
'label_attr' => ['class' => 'control-label'],
])
->add('domicileProvince','entity', [
'label' => ucwords('Province'),
'class'=>'GeneralBundle\Entity\State',
'required' => true,
'attr' => ['class' => 'form-control select2'],
'label_attr' => ['class' => 'control-label'],
])
and on front end,
$("#profile_from_type_domicileProvince").change(function() {
var state = $('option:selected', this).val();
getDistrictByState(state);
});
function getDistrictByState(state){
var dict = {
type: "POST",
url: "{{ url('ajax_district_by_stateId') }}?id=" + state,
success: function(e) {
$("#profile_from_type_domicileDistrict option").remove();
$.each(e, function(e, p) {
$("#profile_from_type_domicileDistrict").append($("<option />", {
value: e,
text: p
}));
});
}
};
$.ajax(dict);
}
UPDATE: Add PRE_SUBMIT Event;
After suggestion form #Alsatian, I update my form and add the event as below, but nothing happens on selecting first dropdown.
$builder->addEventListener(FormEvents::PRE_SUBMIT, [$this, 'preSubmitData']);
public function preSubmitData(FormEvent $event){
$form = $event->getForm();
$data = $event->getData();
if (array_key_exists('Province', $data)) {
$state = $data['Province'];
$event->getForm()
->add('District','entity', [
'label' => ucwords('District'),
'class'=>'GeneralBundle\Entity\District',
'required' => true,
'mapped' => true,
'query_builder' => function(DistrictRepository $repository) use ($state) {
$qb = $repository->createQueryBuilder('d')
->andWhere('d.verified = :verified')
->andWhere('d.active = :active')
->setParameter('verified', true)
->setParameter('active', true);
if ($state instanceof State) {
$qb = $qb->where('d.state = :state')
->setParameter('state', $state);
} elseif (is_numeric($state)) {
$qb = $qb->where('d.state = :state')
->setParameter('state', $state);
} else {
$qb = $qb->where('d.state = 1');
}
return $qb;
},
'attr' => ['class' => 'form-control select2'],
'label_attr' => ['class' => 'control-label'],
]);
}
}
I had the same problem.
I wrote a bundle here to deal with "extensible" choice types (also entity or document) :
https://github.com/Alsatian67/FormBundle/blob/master/Form/Extensions/ExtensibleSubscriber.php
How I do it :
Hooking in the form submission process, we can access to the submitted entity by the PRE_SUBMIT FormEvent.
All submitted entity are loaded and are in $event->getData().
Then we have just to take this submitted choices as new 'choices' option for the field.
Caution :
Doing it so it will only validate that the entity submitted exist !
If only a part of the entities are possible choices you have to add a constraint to validate them.
You can also set the choices in the PRE_SUBMIT event, depending on the value of the first dropdown (instead of using all submitted entities).
I'm currently building a comment system and would like to include the ability to mention users and tag them, subsequently I would like the tag to have a link to their profile (In this example, it's just /profile/{id})
I am currently using Laravel Mentions to generate the auto filled list from my Users Model. I'm doing it like:
function enableMentions(elem, type, column) {
$(elem).atwho({
at: "#",
limit: 5,
displayTpl: '<li><span>${name}</span></li>',
insertTpl: '${name}',
callbacks: {
remoteFilter: function(query, callback) {
if (query.length <= 1) return;
$.getJSON("/api/mentions/" + type, {
q: query,
c: column
}, function(data) {
callback(data);
});
}
}
});
}
// My api/mentions route: Route::get('/api/mentions/{type}', 'ApiController#index');
//My api controller:
public function index($type, Request $request)
{
try {
$resultColumns = [];
$query = $request->get('q');
$column = $request->get('c');
$model = app()->make(config('mentions.' . $type));
$records = $model->where($column, 'LIKE', "%$query%")
->get();
foreach ($records as $record) {
$resultColumns[] = $record->$column;
}
return response()->json($resultColumns);
} catch (\ReflectionException $e) {
return response()->json('Not Found', 404);
}
}
And finally, initializing the at.js
<script type="text/javascript">
$(function(){
enableMentions("#mention-commentContent", "users", "Username");
});
</script>
<div contentEditable="true" id="mention-commentContent" class="user-form" name="commentContent" type="text"></div>
I'm confused on how I can modify the above to return the username and the ID assigned to them, that way I can change the ${name} to ${id} and have it link through to their profile, right?
This package may help Laravel Mentions or this .
The basic idea is getting the usernames from the database via JSON , here is how they are using it in laracasts:
$("textarea#body").atwho({
at: "#", limit: 5, callbacks: {
remoteFilter: function (t, e) {
t.length <= 2 || $.getJSON("/api/users", {q: t}, function (t) {
e(t)
})
}
}
})
I have a EXTjs grid, which displays some fields from my custome tables in database..
Reports.grid.Reports = function(config) {
config = config || {};
Ext.applyIf(config,{
id: 'reports-grid-reports'
,url: Reports.config.connectorUrl
,baseParams: { action: 'mgr/reports/getList' }
,save_action: 'mgr/reports/updateFromGrid'
,fields: ['id','name','filename','remark','year','resourceID','typeID','visible']
and then :
{
header: 'Type ID'
,dataIndex: 'typeID'
,sortable: true
,width: 100
}
My types table has typeid and name.. my grid displays the number, How can I tell it to display the coresponding name for that id in the table instead?
I also got a combobox which I use in update window:
Reports.combo.Types = function(config) {
config = config || {};
Ext.applyIf(config,{
name: 'typeID'
,hiddenName: 'typeID'
,displayField: 'name'
,valueField: 'id'
,fields: ['name','id']
,listWidth: 380
,pageSize: 20
,url: Reports.config.connectorUrl
,baseParams: {
action: 'mgr/reports/gettypelist2', 'combo': true
}
});
Reports.combo.Types.superclass.constructor.call(this,config);
};
Ext.extend(Reports.combo.Types,MODx.combo.ComboBox);
Ext.reg('combo-modx-types',Reports.combo.Types);
Using ,displayField: 'name' makes combo display name instead of the id.. how can I do the same thing in grid?
If I understand the question correctly, I believe you would need to customise the getList processor rather than in the ExtJS directly. Override the afterIteration() function. Something along the lines of:
public function afterIteration(array $list) {
$rows = array();
foreach ($list as $row){
// This calls a custom getName() function that gets the name from the other table
$row['typeID'] = $this->getName($row['id']);
$rows[] = $row;
}
return $rows;
}
and maybe your getName() function could be something like:
private function getName($id) {
$otherTable = $this->modx->getObject('TABLE_ALIAS_HERE', array('internalKey' => $id));
$name = $otherTable->get('name');
return $name;
}