Ajax pagination and remembering last page - ajax

I have ajax pagination:
class AjaxPager extends CLinkPager {
protected function createPageButton($label,$page,$class,$hidden,$selected)
{
if($hidden || $selected)
$class.=' '.($hidden ? $this->hiddenPageCssClass : $this->selectedPageCssClass);
return '<li class="'.$class.'">'.CHtml::ajaxLink($label,$this->createPageUrl($page), array(
'update'=>'#auctionList',
'data' => array('price_from'=>$_GET['price_from'],'price_to'=>$_GET['price_to'])
), array('id'=>'link-'.uniqid())).'</li>';
}
}
When i am on second page, click to view item details and go back, then i am on first page. I know i must use history.pushState but I don't know how use it in AjaxPager. Can you help me?
Edit:
I add 'complete' => 'function(){ window.history.pushState({}, "", this.url); }', but when I use back button it loads only ajax content from cache, instead of layout with it. How to prevent this?

Related

Call view in Laravel Controller with anchor tag

I need to call a view in a Laravel Controller, with parameters and with Anchor Tag.
I have this code in my controller:
return view('plans/editPlanView',
['plan' => $plan,
'patient' => $patient,
'aliments'=>$aliments, 'menu'=>$menu, 'tabName'=>$tabName]);
But i need to add an Anchor tag to land in a specific section of the page.
I can't use
return Redirect::to(URL::previous() . "#whatever");
proposed in other posts because i need to pass some parameters.
I think there are some base problem, trying with console this:
$('html, body').animate({
scrollTop: $('#whatever').offset().top
}, 1000);
scrolling to the desired section does not work.
it seems the page makes a small snap but always returns to the top.
Update
I have found the cause of the problem. At the bottom of the blade page I have the following code, without it the anchor tag works fine. Adding it the page makes a small scroll to return to the head. I need to use the datepicker, how can I fix the problem and get the anchor tag to work?
#push('scripts')
<script type="text/javascript">
$(document).ready(function () {
$('.date').datepicker({
firstDayOfWeek: 1,
weekDayFormat: 'narrow',
inputFormat: 'd/M/y',
outputFormat: 'd/M/y',
markup: 'bootstrap4',
theme: 'bootstrap',
modal: false
});
});
</script>
#endpush
You can create the method showPage() in your contoller for example TestController
public function showPage(Request $request)
{
$plan = $request->plan;
...
return view('plans/editPlanView', [
'plan' => $plan,
'patient' => $patient,
'aliments'=>$aliments, 'menu'=>$menu, 'tabName'=>$tabName
]);
}
Then create a route for rendering that view
Route::get('/someurl', 'TestController#showPage')->name('show-page');
And then in your methods you can use something like that:
$url = URL::route('show-page', ['#whatever']);
return Redirect::to($url)
I found a workaround, I added the disable attribute to the date input, in doing so, when the datepicker is initialized, the page does not scroll up. Then, as a last javascript statement I re-enabled the fields:
$('.date').prop("disabled", false);

Update area outside of CGridView via Ajax

I'm working with CGridview and updating the grid after an Ajax call. However before I get into the grid I have a a small title and a count $model->itemCount identifying how many records there are. How would I additionally try to update this piece of information along with the grid. Would it be a separate JS call?
Appreciate any help
This is my current code for the grid
'click'=>"function(){
$.fn.yiiGridView.update('item-grid', {
type:'POST',
url:$(this).attr('href'),
success:function(message) {
$('#Ajax-Flash').html(message).fadeIn().animate({opacity: 1.0}, 3000).fadeOut('slow');
$.fn.yiiGridView.update('item-grid');
}
})
return false;
}",
Not sure is this what yoy want but you can use beforeAjaxUpdate() in CgridView as shown below
<?php
$this->widget('zii.widgets.grid.CGridView', array('id'=>'insurance_grid',
'beforeAjaxUpdate'=>"function(id, data){
//Your code to update the title and count
}",
'dataProvider'=>$model->search(),
//'filter'=>$model,
'summaryText' => '', // 1st way
'template' => '{items}{pager}', // 2nd way
'selectableRows' => 2,
'selectionChanged' => "
function(id){
}",
'columns'=>array(array('id'=>'selectedCompanies',
'class'=>'CCheckBoxColumn',
array('name'=>'Agency Name',
'type'=>'raw',
'value'=>'$data->agencyname',
),
),
));
?>

Yii ClientSide Validation on Render Partial not Working

I have a Yii form which calls a render partial from another model (team has_many team_members). I want to call via ajax a partial view to add members in team/_form. All works (call, show, save) except for ajax validations (server and client side). If i submit form, member's model isn't validating, even in client side, it's not validating the required fields.
Any clue?
//_form
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'team-form',
'enableAjaxValidation'=>true,
'enableClientValidation'=>true,
'clientOptions'=>array(
'validateOnSubmit'=>true,
'validateOnChange'=>true
),
'htmlOptions' => array('enctype' => 'multipart/form-data'),
)); ?>
//Controller
public function actionMember($index)
{
$model = new TeamMember();
$this->renderPartial('_member',array(
'model'=> $model, 'index'=> $index
)
,false,true
);
}
public function actionCreate()
{
$model=new Team;
$members = array();
if(isset($_POST['Team']))
{
$model->attributes=$_POST['Team'];
if(!empty($_POST['TeamMember'])){
foreach($_POST['TeamMember'] as $team_member)
{
$mem = new TeamMember();
$mem->setAttribute($team_member);
if($mem->validate(array('name'))) $members[]=$mem;
}
}
$this->redirect(array('team/create','id'=>$model->id,'#'=>'submit-message'));
}
$members[]=new TeamMember;
$this->performAjaxMemberValidation($members);
$this->render('create',array(
'model'=>$model,'members'=>$members
));
}
//_member
<div class="row-member<?php echo $index; ?>">
<h3>Member <?php echo $index+1; ?></h3>
<div class="row">
<?php echo CHtml::activeLabel($model, "[$index]name",array('class'=>'member')); ?>
<?php echo CHtml::activeTextField($model, "[$index]name",array('class'=>'member')); ?>
<?php echo CHtml::error($model, "[$index]name");?>
</div>
</div>
ProcessOutput was set to true. No dice.
Switch renderPartial() to render(). No dice.
If you will look at the CActiveForm::run:
$cs->registerCoreScript('yiiactiveform');
//...
$cs->registerScript(__CLASS__.'#'.$id,"jQuery('#$id').yiiactiveform($options);");
Then you will understand that you validation will not work, because you render partial and not the whole page. And these scripts show up at the bottom of the page. So you should solve this by execute these scripts.
After you partial is rendered, try to get activeform script which should be stored at the scipts array:
$this->renderPartial('_member',array('model'=> $model, 'index'=> $index));
$script = Yii::app()->clientScript->scripts[CClientScript::POS_READY]['CActiveForm#team-form'];
after, send it with rendered html to page:
echo "<script type='text/javascript'>$script</script>"
Also remember before you will append recieved html on the page you should include jquery.yiiactiveform.js, if you not already did it(by render another form, or registerCoreScript('yiiactiveform')), on the page from calling ajax request. Otherwise javascript error will raised.
Hope this will help.
Edit:
Sorry I'm not understood that you are render part of form and not the whole. But you validation will not work exactly with the same issue. Because jQuery('#$id').yiiactiveform($options); script was not created for the field.
The actual problem is that the ActiveForm saves its attributes to be validated in the "settings" data attribute. I see you are already using indexes so what you need to add the new elements to this settings object in order for the validation to work. After the ajax response this is what must be done:
//Get the settings object from the form
var settings = $("#form").data('settings');
//Get all the newly inserted elements via jquery
$("[name^='YourModel']", data).each(function(k, v) {
//base attribute skeleton
var base = {
model : 'YourModel',
enableAjaxValidation : true,
errorCssClass : 'error',
status : 1,
hideErrorMessage : false,
};
var newRow = $.extend({
id : $(v).attr('id'),
inputID : $(v).attr('id'),
errorID : $(v).attr('id') + '_em_',
name : $(v).attr('name'),
}, base);
//push it to the settings.attribute object
settings.attributes.push(newRow);
});
//update the form
$("#form").data('settings', settings);
```
This way the ActiveForm will be aware of the new fields and will validate them.
Well, setting processOutput to true in renderPartial (in order to make client validation works on newly added fields) will not help in this case since it will only work for CActiveForm form and you don't have any form in your _member view (only input fields).
A simple way to deal with this kind of problem could be to use only ajax validation, and use CActiveForm::validateTabular() in your controller to validate your team members.

$ajax->submit Does Not Go To Controller

I am using cakephp and pippoacl plugin and I simply cannot add a new role. What I modify in the plugin is to make the submit using ajax, something like this in my view (add.ctp):
<?php echo $ajax->submit(
'submit',
array(
'url' => array('controller' => 'roles', 'action' => 'add'),
'before' => 'beforeSubmitAdd();',
'complete' => 'completeSubmitAdd(request);'
)
);
?>
When the add.ctp gets loaded for the first time, I can print_r something from the controller. But the ajax submit above only executes the javascript on 'before' and 'complete'. I check on the firebug, the response is blank.
On my controller:
function add() {
print_r("start");
if (!empty($this->data)) {
print_r("add new role");
// save new role
}
}
I use ajax submit for user and I don't have any problem adding new user. Is there any idea where I should check? I have been comparing the user and role code for a week and I have asked a friend to look at my code, too, but we still cannot find what causes this.
Thanks in advance! :D
I am not so familiar with the Ajax helper, but I haven't using it from so long that I can't remember what is it doing :).
Back to the problem.
Did you check if the requested URL in the Ajax address is correct? This should work straightforward, but it's possible that the url to be invalid.
Are you using Security component (even just adding it on the var $components variable)?. This could lead to blank screen especially if you modifying the fields in the form somehow. Try to remove it and see if it's working without.
Finally I would say how I would do it with jQuery.
Following code should do the job:
$(document).ready(function(){
$('form').live('submit', function(){ //handles also dynamically loaded forms
var form = $(this).addClass('loading'); //indicate somehow that the form has been submitted
$('#content').load($(this).attr('action'), $(this).serialize(), function(){
form.removeClass('loading');
});
})
});
This will handle all submits in the forms of the system, but you can modify of course.

Help with ajax callback and drupal_process_form

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.

Resources