I'm having an issue with submitting a TbActiveForm and the renderPartial wiping my page out and displaying only the partial view. I want to reload only the widget after my action triggers and finishes. I'm also using a modal to display and make changes.
view:
$form = $this->beginWidget(
'booster.widgets.TbActiveForm',
array(
'id' => 'horizontalForm',
'type' => 'horizontal',
'action' => Yii::app()->createUrl('orderControl/order/returns.save'),
)
);
echo $form->hiddenField(
$editReturnFormModel,
'orderId',
array(
'value' => $editReturnFormModel->orderId
)
);
$this->widget(
'bootstrap.widgets.TbButton',
array('buttonType' => 'submit', 'type' => 'primary', 'label' => 'Save')
);
$this->endWidget();
Action:
$this->controller->renderPartial('ScModules.orderControl.widgets.ReturnsWidget.views._returnItems', array('returnsDataProvider'=>$returnsDataProvider, 'editReturnFormModel'=>$editReturnFormModel));
One other point is that the Yii::app()->createUrl('orderControl/order/returns.save') is change the page url all together. On this page page I'm directed to, the view is created fine. I need the widget to rebuild/refresh on the current page and not send me somewhere else. Any ideas on solution would be appreciated.
Here's what I would do:
Wrap your form widget inside a div or whatever block tag you like.<div id="myFormWrapper"> (your widget goes here) </div>
Add a custom ID in your form (id="formId") and submit button (id="submitButtonId")
Add some jQuery in order to submit your form and replace the old widget with the new
$(document).on('click', '#submitButtonId' , function() {
$.ajax({
type: 'POST',
url: $('#formId').attr('action'),
data : $('#formId').serialize(),
beforeSend : function(){
//do anything you want before sending the form
},
success : function(data){
//We'll replace the old form with the new form widget
$('#myFormWrapper').html(data);
},
error : function(data){
console.log('ops');
},
});
return false;
});
Do whatever you want to do in your Controller action and use renderPartial.
//The action below should be the same that you used in the action attribute of the form
public function actionProcessForm(){
$model = new MyFormModelName();
if(isset($_POST['MyFormModelName'])){
$model->attributes = $_POST['MyFormModelName'];
if($model->save()){
//Do whatever you want here
$returnsDataProvider = new CActiveDataProvider('YourModel');
$this->renderPartial('//folder/to/your/view', array('returnsDataProvider'=> $returnsDataProvider, 'editReturnFormModel'=>$editReturnFormModel));
}else{
//You might want to render something else here
$this->renderPartial('errorViewPage');
}
}
}
Related
I have build a search/result page with FacetWP and ACF.
On the result page I add the possibility to edit one specific repeater fields for each result listed.
To do that I include in the FacetWP loop this code:
<?php
$options = array(
'id' => 'acf-form_'.$post->ID,
'post_id' => $post->ID,
'post_title' => false,
'post_content' => false,
'field_groups' => array('group_6166044822675'),
'fields' => array('field_6166066864387'),
);
acf_form($options);
?>
On the main page the button “add row” work well.
When with a Facet I refine the result to show only the post from October 2021 or any other specification, FacetWP import the new search result via ajax.
But this time if I click on a “add row” button, nothing happen.
The javascript and the new HTML code imported via ajax by FacetWP are not binded.
There are many answers about binding problem but I can't find how to solve it because the ACF function has no name.
! function() {
var t = {
...
945: function() {
! function(t) {
var e = acf.Field.extend({
type: "repeater",
wait: "",
events: {
'click a[data-event="add-row"]': "onClickAdd",
'click a[data-event="duplicate-row"]': "onClickDuplicate",
'click a[data-event="remove-row"]': "onClickRemove",
'click a[data-event="collapse-row"]': "onClickCollapse",
showField: "onShow",
unloadField: "onUnload",
mouseover: "onHover",
unloadField: "onUnload"
}, ...
Is there a way to target this function ?
p.s. had placed this simply to share the solution.
I'd like to save a post in front end if we click a button using ajax in js:
var title = $("#portfolioTitle").val();
var customFieldValues = $("#customfieldValue").val();
$("#btnClick").on("click", function() {
$.ajax({
url : ajax_url,
type: 'post',
dataType: 'json',
data: {
action: 'data_Publish', portfolioTitle: title, fieldValues: customFieldValues
},
success: function(data) {
if(data == "exists") {
console.log("Add a different title");
} else {
console.log("post added");
console.log(data["link"]);
console.log(data["title"]);
}
}
});
});
Placing my own answer but wondering if there is there any speed or security improvements?
For example we could add a caching system, or define our own ajax (Maybe a help could be answering: How to implement the code in the link using the case scenario we have on this question?) in order not to have wordpress loading all the files but here we are doing a http request, anyway, if any of you would want to give their 2 cents to make it faster, It'd be great.
Let's say we want to add posts via ajax in frontEnd in wordpress and we want to check if the title is unique in the database otherwise tell the user to add a different title:
We have a button to click:
<button type="button" id="btnClick">Load</button>
We have an input for the title and a custom field:
<input type="text" id="portfolioTitle" name="portfolioTitle" value="" placeholder="Your title...">
<input type="text" id="customfieldValue" name="customfieldValue" value="" placeholder="Your customFieldvalue...">
The JS. Firstly you need to load wordpress ajax (This is the bit that could be improved if anyone fances to):
var ajax_url = '<?php echo admin_url( 'admin-ajax.php' ); ?>';
Then your javaScript:
var title = $("#portfolioTitle").val();
var customFieldValues = $("#customfieldValue").val();
$("#btnClick").on("click", function() {
$.ajax({
url : ajax_url,
type: 'post',
dataType: 'json',
data: {
action: 'data_Publish', portfolioTitle: title, fieldValues: customFieldValues
},
success: function(data) {
if(data == "exists") {
console.log("Add a different title");
} else {
console.log("post added");
console.log(data["link"]);
console.log(data["title"]);
}
}
});
});
Then in function.php:
function data_Publish() {
$post_title = $_POST['portfolioTitle'];
$post_custom_field = $_POST['fieldValues'];
$post = array(
'post_title' => $post_title,
'post_status' => 'publish',
'post_type' => 'page',
'page_template' => 'portoflio.php'
);
if ( get_page_by_title( $post_title ) === null ) {
// the title is unique, we can add the new page
$post_id = wp_insert_post( $post );
add_post_meta($post_id, 'customField', $post_custom_field], true);
$link = get_permalink( get_page_by_title( $post_title ) );
$title = get_the_title($post_id);
$newPostAttributes[] = array("link"=>$link, "title"=>$title);
echo json_encode($newPostAttributes);
} else {
// that title already exists, tell the user to change it
echo json_encode("exists");
}
wp_die();
}
add_action('wp_ajax_data_Publish', 'data_Publish');
Basically that function is a normal wordpress query. Therefore you could use the same logic to retrieve post values if You'd want to, for example you won't be using $post_id = wp_insert_post( $post ); but maybe to get the tittle back to the user you'd use $postTile = get_the_title();.
Let's break it down:
In ajax we use action: 'data_Publish', portfolioTitle: title where data_Publish is our php function, and portfolioTitle: title is what we are sending.
In function we can see: $post_title = $_POST['portfolioTitle']; that's our title that we have sent via ajax. With 'page_template' => 'portoflio.php' we can add our own template to that page.
Then we need to use if ( get_page_by_title( $_POST['portfolioTitle'] ) === null ) { to check if that title exists or not, if it doesn't exist, we add the posts to the database with $post_id = wp_insert_post( $post );
Once we added it we use the following to add any other values to our custom field in the newly created postadd_post_meta($post_id, 'customField', $_POST['customfieldValue'], where customField is the name of the custom field we want to create in the new post we just added.
So if the posts doesn't exist, we save it and we can send back to ajax its title and its link so that we could shows it to the user as a response if We'd ever want to.
So we define title and link like this and we create a multidimentional array to send the data back to the front end:
$link = get_permalink( get_page_by_title( $post_title ) );
$title = get_the_title($post_id);
$newPostAttributes[] = array("link"=>$link, "title"=>$title);
If the title exists we send back a response echo json_encode("exists");
We need to die the query for safeness wp_die();
If We'd ever want to make ajax available to no logged user, remember wordpress ajax is only available to admin, so we need to add:
add_action('wp_ajax_data_Publish', 'data_Publish');
add_action( 'wp_ajax_nopriv_data_Publish', 'data_Publish' );
Basically in function.php wordpress uses wp_ajax_ +"name of our function" and wordpress has wp_ajax_nopriv_ to make ajax available if not logged.
I hope It helps anyone and if any of You could improve it, It'll be better for all.
I'm using Codeigniter 2.2. I'm trying to build a table using HTML table class library. It also contain a edit button .here is my view file :
foreach($invoices as $row) {
$data = array(
'name' => 'btn btn-default btn-sm dropdown-toggle',
'type' => 'button',
'content' => '',
'class' => 'btn btn-default btn-sm dropdown-toggle',
'class' => 'entypo-trash',
);
$edit_url = base_url().
'index.php?modal/popup/modal_edit_invoice/'.$row['invoice_id'];
$onclick_edit = array('onclick' => "showAjaxModal('{$url}')");
$links = form_button($data, $js);
$links. = anchor('#', 'edit', $onclick_edit); //here is the issue, on click popup try load , but in a next second page redirect to the index page
$this->table->add_row(
$this->crud_model->get_type_name_by_id('student', $row['student_id']), $row['title'], $row['description'], $row['amount'], $row['amount_paid'], $row['due'], $row['status'], $links
);
}
echo $this->table->generate();
Everything is working fine. But when I try to click edit button my model window is popup but in a next second page redirect to the index page.
Here is JavaScript file :
function showAjaxModal(url) {
// SHOWING AJAX PRELOADER IMAGE
jQuery('#modal_ajax .modal-body').html('<div style="text-align:center;margin-top:200px;"><img src="assets/images/preloader.gif" /></div>');
// LOADING THE AJAX MODAL
jQuery('#modal_ajax').modal('show', {
backdrop: 'true'
});
// SHOW AJAX RESPONSE ON REQUEST SUCCESS
$.ajax({
url: url,
success: function(response) {
jQuery('#modal_ajax .modal-body').html(response);
}
});
}
It's working fine with anchor tag but I can't use that one in HTML table class.
Please help me out.. thanks in advance
Just change this line
$onclick_edit = array('onclick' => "showAjaxModal('{$url}')");
to this
$onclick_edit = array('onclick' => "return showAjaxModal('{$url}')");
And change your js function like this
function showAjaxModal(url) {
// SHOWING AJAX PRELOADER IMAGE
jQuery('#modal_ajax .modal-body').html('<div style="text-align:center;margin-top:200px;"><img src="assets/images/preloader.gif" /></div>');
// LOADING THE AJAX MODAL
jQuery('#modal_ajax').modal('show', {
backdrop: 'true'
});
// SHOW AJAX RESPONSE ON REQUEST SUCCESS
$.ajax({
url: url,
success: function(response) {
jQuery('#modal_ajax .modal-body').html(response);
}
});
return false; //this will stop <a> tag behavior
}
Overview of my situation -
I have a database with 2 tables in it. The first table is called 'primary_content_areas', the second table is called 'secondary_content_areas'. The only important thing to note is that each one contains an ID and the 'secondary_content_areas' table has a field called primary_content_area_id. The primary_content_areas Model has a hasMany relationship with secondary_content_areas.
Using the Cakephp framework, i have an element view, called Primary, which contains a div. Inside the div there's a foreach loop that loops through the data passed in from the controller and creates divs according to how many secondary_content_areas have a primary_content_area_id that is equal to the current primary_content_area id. The database basically creates a tree structure that is then recursively looped through and draws divs inside divs. Currently it is only 2 layered. An 'add' button is also inside the 'Primary' element view. When this add button is clicked, using jquery it creates a new object in the secondary_content_areas table and assigns the field 'primary_content_areas_id' to the ID of the div that the add button belongs too. Then in the same jquery process, if it succeeds, it loads a function in the controller that re-renders the 'Primary' element view. Because of how it is set up, this actually re-renders every div from the from the 'Primary' divs too all secondary divs connected.
My Problem -
I have this working. My problem is that after i click the button once, it adds a 'secondary' object to the database, and renders a new div, but after that the button doesn't work. After some research, i believe it's to do with the fact that re-rendering a view and more specifically the 'add' button using jquery basically unbinds all events from the DOM.
So my question is how do i re-bind my jquery events using cakephp.
Here is the code.
Controller ----
...
public function add_secondary () {
$this->layout = 'ajax';
// check user is logged in
if($this->Session->read('Auth.User'))
{
$this->Secondary->create();
$content_area_id = $this->request->data['primary_content_area_id'];
$this->Secondary->set('primary_content_area_id', $content_area_id);
$this->Secondary->set('position', '1');
if ($this->Column->save($this->request->data))
{
$result = array('result' => 'success', 'text' => 'Column Added');
}
}
echo json_encode($result);
die();
}
public function ajax_render () {
$this->Primary->recursive = 5;
$page_data = $this->Primary->find('first',array('conditions' => array('Primary.name' => 'index' ))); //temporary
$this->set('page_data', $page_data);
$this->render('/elements/primary');
}
...
My best guess was i felt like i needed a line after ' $this->render('/elements/primary'); ' That calls my ' bindEvents(); ' function in my Js. I haven't been able to find a way to call a js function from my controller though using cakephp.
Primary element view ---
<?php foreach($page_data['ContentArea'] as $contentArea){ ?>
<div class="content_area <?php echo $contentArea['tags'] ?>" >
<?php echo $this->element('secondary', array( "contentArea" => $contentArea));?>
<div class="button_container">
<div class="add_button content_area_add_button">
<input class="add_content_area" id="add_content_area" type="submit" value="add" data-content-area-id="<?php echo $contentArea['id']?>" />
</div>
</div>
</div>
JS ----
function bindEvents() {
$("#add_content_area").click(function() {
//alert($(this).data("content-area-id"));
var request = $.ajax({
type: "POST",
url: "/pages/add_secondary/",
dataType: "json",
data: { content_area_id: $(this).data("content-area-id") }
});
request.done(function(result) {
if(result.result == "success")
{
alert( "success" );
$('#content').load('/pages/ajax_render/', function() {
alert( "Load was performed." );
});
}
else
{
alert("Comment " + result.result + ": " + result.text);
}
});
request.fail(function(jqXHR, textStatus) {
alert("Request failed: " + textStatus);
});
});
}
$(document).ready(function() {
bindEvents();
});
PS. The 'alert( "Load was performed." )' doesn't happen. I believe i have the syntax is right where it is meant to alert that message when it has completed the load. It does not.
Rather than rebinding your events, consider using event delegation from a parent element (that doesn't change), then you won't need to rebind anything:
$("body").on('click', '#add_content_area', function(){
.. do stuff
});
try to put the JS code in a file, and call it in afterRender() function
function afterRender()
{
echo $this->Html->script('UR JS', array('inline'=>false));
}
Ok so I'm not sure how relevant this will be to others but thought I'd post how i fixed this. Turns out i just forgot the line $this->layout = 'ajax'; in public function ajax_render(); . Once i added that in, the alert( "Load was performed." ); happened. instead i replaced that alert with bindEvents(); so after the load was completed for my ajax_render function it called bindEvents() again.
code in my view is bellow:
<?php echo $form->create( "ChatForm", array("id" => "chat_form", "type" => "post",'class'=>'form_chat',"url" => array( "controller" => "qasamples", "action" => "quick_request" ) ) );
echo $form->hidden( 'ChatForm.pid', array('class'=>'chat_input_hidden') );
echo $form->hidden( 'ChatForm.uid', array('class'=>'chat_input_hidden') );
echo $form->textarea('ChatForm.text',array('id'=>'text_input','rows'=>'14','cols'=>'400','style'=>'resize:none;width:907px;border:0px;','onkeyup'=>"onTextChange()")); ?>
<p style="text-align:center;margin-top:20px;"><button type=submit id="chat_send">Send</button></p>
<?php $form->end(); ?>
here is the controller code:
public function quick_request(){
if(!empty($this->data))
{
$fields=array('QasampleAnswer.uid','QasampleAnswer.pid','QasampleAnswer.text');
$data=array(
'uid'=>$this->data['ChatForm']['uid'],
'pid'=>$this->data['ChatForm']['pid'],
'text'=>$this->data['ChatForm']['text']);
if($this->QasampleAnswer->save($data))
{
$data_update=array(
'id'=>$this->data['ChatForm']['pid'],
'status'=>'0');
if($this->Qasample->save($data_update))
$this->render('text2');
}
}
}
Can I just send the message and without fresh my page?
I heard that CakePHP and AJAX can make it work, but I'm a new learner of CakePHP and Javascript also. I hope you guys can help me with it. Thank you very much. The page text2 is to turn the page back to where I was,but it not working well.So I hope I could send my message and just stay this page without refreshing.
Post your data with Ajax, jquery gives you a lot of options to do that... you can also implement a JavaScript and make it call when the for. is submitted (this can be achieved when you add in the array at $form->create array('onsubmit'=>'return yourFunction()') then you have to red your form data in this function, post it via ajax and very important return false in this function (it will prevent the form submitting) you can also make a button instead of the submit button that calls this function but then you have to implement in the text-field that when the user presses enter it should send the data... it is more comfortable with the onsubmit thing.
If you need an example I can also provide a practical code for this...
I will use a cake-less example of the JavaScript
<?php echo $form->create( "ChatForm", array("id" => "chat_form", "type" => "post",'class'=>'form_chat',"url" => array( "controller" => "qasamples", "action" => "quick_request", "onsubmit"=>"return performPostRequest(this)") ) );
this is the part you use to create the form
<script type="text/javascript">
function performPostRequest(form) {
parameters="";
for(var i=0;i<form.elements.length;i++) {
if(parameters!="")
parameters+="&";
if(form.elements[i].checked==true || !(form.elements[i].type=="radio" || form.elements[i].type=="checkbox"))
parameters+=form.elements[i].name+"="+encodeURIComponent(form.elements[i].value);
}
$.ajax({
url: form.action,
data: parameters,
type : 'POST',
});
return false;
};
</script>
and this is the JavaScript function, I use it myself so it should work without a Problem :) It simulates your post request, but uses Ajax and therefore your page will not reload...
You need a simple Ajax Call like the following and modify the form create so that it does not post automatically.
$ajax->form(array('type' => 'post',
'options' => array(
'model'=>ChatForm,
//'update'=>'UserInfoDiv',
'url' => array(
'controller' => 'chatforms',
'action' => 'quick_request'
)
)
));