I have a page that contains CGridView in my app. Users can search data by filling the form and clicking submit button. The search function works, and CGridView successfully updated. The problem is it can't be done through ajax, Yii keep doing it through parameters in URL.
I want to update CGridView through ajax so the URL still nice to look. Here's my code.
View File
<?php
Yii::app()->clientScript->registerScript('search', "
$('.btn-link').click(function(){
$('.section').toggle();
return false;
});
$('.section form').submit(function(){
$('#customer2-grid').yiiGridView('update', {
data: $(this).serialize()
});
return false;
});
");
?>
<?php echo CHtml::link('Advanced Search','#',array('class'=>'btn-link')); ?>
<div class="section" style="display:none">
<?php $this->renderPartial('_search',array(
'model'=>$model,
)); ?>
</div><!-- search-form -->
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'customer2-grid',
'dataProvider'=>$model->search(),
'htmlOptions'=>array('style'=>'font-weight:bold'),
'filter'=>$model,
'columns'=>array(
'NAME',
'BIRTHDATE',
'ADDRESS',
'EMAIL',
array(
'header'=>'Action',
'class'=>'CButtonColumn',
'template' => '{add} {updates}',
'buttons' => array(
'add' => array(
'label' => '',
//'imageUrl' => Yii::app()->request->baseUrl.'/images/icon/add.png',
'url' => 'Yii::app()->createUrl("/goods/create/",array("id"=>$data->ID))',
'options'=>array('class'=>'btn btn-info', 'style'=> 'margin-bottom:2px '),
),
'updates' => array(
'label' => 'Update Profil',
// 'imageUrl' => Yii::app()->request->baseUrl.'/images/icon/update.png',
'url' => 'Yii::app()->createUrl("/customer/update/",array("id"=>$data->ID))',
'options'=>array('class'=>'btn btn-info'),
),
),
),
),
));
?>
Here's my _search.php code
<div class="form-horizontal">
<?php $form=$this->beginWidget('CActiveForm', array(
'action'=>Yii::app()->createUrl($this->route),
'method'=>'get',
)); ?>
<div class="form-group">
<?php echo $form->labelEx($model,'NAME',array('class'=>'col-sm-2 control-label')); ?>
<div class="col-sm-6">
<?php echo $form->textField($model,'NAME',array('size'=>60,'maxlength'=>128,'class'=>'form-control')); ?>
</div>
</div>
<div class="form-group">
<?php echo $form->labelEx($model,'BIRTHDATE',array('class'=>'col-sm-2 control-label')); ?>
<div class="col-sm-6">
<?php echo $form->textField($model,'BIRTHDATE',array('class'=>'form-control')); ?>
</div>
</div>
<div class="form-group">
<?php echo $form->labelEx($model,'ADDRESS',array('class'=>'col-sm-2 control-label')); ?>
<div class="col-sm-6">
<?php echo $form->textField($model,'ADDRESS',array('size'=>60,'maxlength'=>512,'class'=>'form-control')); ?>
</div>
</div>
<div class="form-group">
<?php echo $form->labelEx($model,'EMAIL',array('class'=>'col-sm-2 control-label')); ?>
<div class="col-sm-6">
<?php echo $form->textField($model,'EMAIL',array('size'=>60,'maxlength'=>64,'class'=>'form-control')); ?>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<?php echo CHtml::submitButton('Search', array('class'=>'btn btn-primary')); ?>
</div>
</div>
<?php $this->endWidget(); ?>
</div><!-- search-form -->
Here's my controller code
public function actionAdmin()
{
$this->layout = '//layouts/column1';
$model=new Customer('search');
$model->unsetAttributes(); // clear any default values
if(isset($_GET['Customer']))
$model->attributes=$_GET['Customer'];
$this->render('admin',array(
'model'=>$model,
));
}
The toggle function in the jQuery works just fine but the update function doesn't work. The sorting function in CGridView works as well. What do I miss here?
Is there any restriction in CSS for jQuery/CGridView? I presume there's something wrong with the CSS Selector
EDIT :
I've found the problem which unexpectedly lies in layout/main.php
I've included three javascript files and one of them causing the error.
<!-- JAVASCRIPTS -->
<!-- Placed at the end of the document so the pages load faster -->
<!-- JQUERY -->
<script src="<?php echo Yii::app()->request->baseUrl; ?>/css/default/js/jquery/jquery-2.0.3.min.js"></script>
<!-- JQUERY UI-->
<script src="<?php echo Yii::app()->request->baseUrl; ?>/css/default/js/jquery-ui-1.10.3.custom/js/jquery-ui-1.10.3.custom.min.js"></script>
<!-- BOOTSTRAP -->
<script src="<?php echo Yii::app()->request->baseUrl; ?>/css/default/bootstrap-dist/js/bootstrap.min.js"></script>
After I discarded the first script, everything's fine. However, I don't have idea why. Maybe somebody can explain why. Any explanation will be appreciated. Sorry if this question going out of topic
ok I try to describe common solution
this code exampling with default gii crud generator
let you have model Customer.php generetad with standard gii module
class Customer extends CActiveRecord
{
// ...
public function search() {
return new CActiveDataProvider(
// provider properties
'criteria' => new CDbCriteria(), // searches and filters
'sort' => new CSort(), // ordering
'pagination' => new CPagination(), // pagging
);
}
// also there are exists rules for search scneario
public function rules() {
return array(
// ... some other rules
// rule for scenario search
array('NAME, BIRTHDATE,ADDRESS, EMAIL', 'safe', 'on'=>'search'),
);
}
// ...
}
next we should describe primitive controller
class CustomerController extends CController
{
public function actionIndex()
{
// create model with scenario search
$model = new Customer('search');
// check for incoming filter requests and apply filter
if(isset($_GET['Customer']) {
$model->attributes = $_GET['Customer'];
}
$this->render('index', array('model'=>$model);
}
}
now we have to create simplest view with basic CGridView settings
<?php $this->widget('zii.widgets.grid.CGridView', array(
'provider' => $model->search(),
// this property automatically add search field above each columns
'filter' => $model,
));
try this code. and you no need to invent already existing solution by specifying custom search form, of course if you want to have extended search tools, you have to some hard codding
Related
I am creating a questionnaire and I am trying to record the answers obtained, I am showing the questions in a listview which are obtained from one table (question) and I want to record them in another table (answer) using active record. I have tried to add the active form inside the itemView class but the send button appears duplicated every time I have more than 1 question, then I try to add it outside the itemView and if the submit button appears only once but I can't get it the data listed in itemView because I don't know how to send the fields of the active form to get the data from the itamView, I tried to send them by the render of the itemView but it throws me the Undefined variable error.
View
<?php $form = ActiveForm::begin([
'enableClientValidation' => false,
'enableAjaxValidation' => true,]) ?>
<?= ListView::widget([
'layout' => '<div class="pull-left">{items}</div>',
'dataProvider' => $dataProvider,
'itemView' => function ($model, $key, $index, $widget) {
return $this->render('_answers',[
'model' => $model,
'index' => $index
]);
},
]); ?><div class="form-group">
<?php echo Html::submitButton('<span class="fa fa-plus"></span>'.' '.Yii::t('backend', 'Send') , ['class' => 'btn btn-primary']) ?>
View _answers
<td width="5%" class="vcenter" rowspan="3">
<span class="panel-title-address"><label class="control-label">Nr: <?php echo ($index+1); ?></label></span>
</td>
<td width="95%" class="vcenter">
<div class="form-group field-qquestion-0-title required">
<label class="control-label" for="qquestion-type_id"><?= Yii::t('backend', 'Question'.' : ')?></label>
</div>
<div class="form-group field-qquestion-0-title required">
<label class="control-label" for="qquestion-type_id"><?= $model->question ?></label>
</div>
<div class="col-md-4">
<?php echo $form->field($answer, 'answer')->textInput(['maxlength' => true]) ?>
</div>
</td>
what I want to obtain is the id and answer of each question to be able to register them in the answer table.
You are getting the undefined variable error because you are not passing the $form variable from your main view to _answers.php. You can pass it like this:
<?php $form = ActiveForm::begin([
'enableClientValidation' => false,
'enableAjaxValidation' => true,]) ?>
<?= ListView::widget([
'layout' => '<div class="pull-left">{items}</div>',
'dataProvider' => $dataProvider,
'itemView' => function ($model, $key, $index, $widget) use ($form) {
return $this->render('_answers',[
'form' => $form,
'model' => $model,
'index' => $index,
]);
},
]); ?><div class="form-group">
<?php echo Html::submitButton('<span class="fa fa-plus"></span>'.' '.Yii::t('backend', 'Send') , ['class' => 'btn btn-primary']) ?>
As for how to send multiple answers with the question ids you can either use the way mentioned in vvpanchev's answer or add a hidden field with question id. The _answers.php view with hidden field:
<td width="5%" class="vcenter" rowspan="3">
<span class="panel-title-address"><label class="control-label">Nr: <?php echo ($index+1); ?></label></span>
</td>
<td width="95%" class="vcenter">
<div class="form-group field-qquestion-0-title required">
<label class="control-label" for="qquestion-type_id"><?= Yii::t('backend', 'Question'.' : ')?></label>
</div>
<div class="form-group field-qquestion-0-title required">
<label class="control-label" for="qquestion-type_id"><?= $model->question ?></label>
</div>
<div class="col-md-4">
<?php
//set the question's id to answer model if you haven't done that already
$answer->question_id = $model->id;
//output the hidden input with question id
echo \yii\helpers\Html::activeHiddenInput($answer, "[$index]question_id");
?>
<?php echo $form->field($answer, "[$index]answer")->textInput(['maxlength' => true]) ?>
</div>
</td>
If you use the hidden field approach then in your controller you can use \yii\base\Model::loadMultiple() method to load the data into answer models. You can also use \yii\base\Model::validateMultiple() for validation. I'm assuming the name for answer model class is Answer.
$count = count(\Yii::$app->request->post('Answer', []));
$answers = [];
for ($i = 0; $i < $count; $i++) {
$answers[] = new Answer();
}
if (
\yii\base\Model::loadMultiple($answers, \Yii::$app->request->post())
&& \yii\base\Model::validateMultiple($answers)
) {
// ... save your answers and/or do other things needed
}
Change your answer input like this and you'll have answer input for every question:
<?php echo $form->field($answer, '['.$model->id.']answer')->textInput(['maxlength' => true]) ?>
When you submit teh form, it will be submitted with all answer questions. So you can check and save the $_POST like this:
if(isset($_POST['Answer']) and !empty($_POST['Answer'])){
foreach($_POST['Answer'] as $question_id => $answer){
//save your answer to your question
}
}
You will have to change you ajaxvalidation too like this foreach
I have this page containing recent posts at the bottom. I have set it to randomly show me three posts from the same category as the current post. Heres the loop:
<!-- Related Posts =========================================== -->
<div class="relared-posts-heading">
<h2>SIMILAR INSIGHTS</h2>
</div>
<div class="container blog-card-container">
<div class="card-columns">
<?php
// the query
$the_query = new WP_Query( array(
'orderby' => 'rand',
'cat' => '-14',
'posts_per_page' => 3,
));
?>
<?php if ( $the_query->have_posts() ) : ?>
<?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
<!-- Conditional a Link =========================================== -->
<?php
if(get_field('quote') == ''){
$yourTag = "<a href='".get_the_permalink()."'>" ;
} else {
$yourTag = "";
}
?>
<div> <?php echo $yourTag; ?> </div>
<div class="card">
<a href="<?php the_permalink(); ?>">
<div class="blog-thumb-container-2">
<?php if ( has_post_thumbnail() ) { the_post_thumbnail(); } ?>
</div>
</a>
<div class="blog-meta-container-2">
<p class="blog-cat-label"><?php the_category(', '); ?></p>
<h2 class="blog-card-title"><?php the_title(); ?></h2>
<p class="card-text"><?php the_excerpt(__('(moreā¦)')); ?></p>
<p><strong><?php the_author(); ?></strong> | <?php echo get_the_date(); ?> </p>
</div>
</div>
</a>
<?php endwhile; ?>
<?php wp_reset_postdata(); ?>
<?php else : ?>
<p><?php __('No News'); ?></p>
<?php endif; ?>
</div>
</div>
This works fine currently.
The trouble is, when finished, the site will be behind a clients custom cache and he tells me that PHP randomisers wont work as it will just show the cached version. He suggested I do any randomising using Javascript!
So firstly - is this possible? Secondly, How would I go about targeting this is javascript!? Thanks for looking!!
Unfortunately you won't be able to randomize a post in this way for the caching reason.
What you can do instead is use an Ajax call to dynamically fetch and insert a random post...
$.get('/wp-content/themes/SomeTheme/random.php?v=' + Math.floor(Date.now() / 1000))
.done(function(resp) {
$('.random-post').html(resp);
})
.fail(function(xhr) {
// handle error (xhr object contains the response)
});
And then create a separate random.php file in your theme and put the code to randomly return a single post in there. Note, that you don't need to put the whole layout around the post (don't include header.php etc). That's because this exact HTML fragment will be sent to the frontend and inserted dynamically.
The ?v= parameter is required for cache busting so that it fetches a new post each time.
Try wrapping the entire funtionality as a shortcode.
I have following code in my view:
<?= $form->labelEx($model, 'p_2_1', array('class' => 'col-xs-12 col-sm-2 control-label')) ?>
<div class="col-xs-12 col-sm-3">
<?= $form->dropDownList($model, 'p_2_1',array_combine($model->getData('money'),$model->getData('money')), array('class' => 'form-control')) ?>
<?= $form->error($model, 'p_2_1') ?>
</div>
<?= $form->labelEx($model, 'p_3_1', array('class' => 'col-xs-12 col-sm-2 control-label')) ?>
<div class="col-xs-12 col-sm-3">
<?= $form->dropDownList($model, 'p_3_1',array_combine($model->getData('money'),$model->getData('money')), array('class' => 'form-control')) ?>
<?= $form->error($model, 'p_3_1') ?>
</div>
And in my model, I have following code:
public function getData($property) {
$data = array(
'money' => array(
Yii::t('plaintinfo', 'RUB'),
Yii::t('plaintinfo', 'USD'),
Yii::t('plaintinfo', 'EURO'),
),
);
return $data[$property];
}
I need to develop JavaScript code when user p_2_1 value changes, p_3_1 value also changes and becomes the same as p_2_1 value. (for example, if user chooses USD from the drop down list p_2_1, the value of p_3_1 will be USD automatically (the same as p_2_1(USD) ). How can I do it?
You can solve it with following Javascript code. You could also change your ids to more understandable.
<script>
$("#p_2_1").change(function(){
var selected = $("#p_2_1 option:selected").val();
var elementToChange = document.getElementById('p_2_1');
elementToChange.value = selected;
});
</script>
I have traveled many articles Stack OverFlow but none have solved my problem. I just want to use Ajax with Cake php to refresh a DIV containing the results of my pagination.
Note:
I included the jQuery library.
I called the RequestHandler component:
public $components = array('RequestHandler');
public function beforeFilter() {
if($this->RequestHandler->isAjax()){
$this->layout=null;
Configure::write('debug', 0);
}
}
I checked the presence of a "ajax.ctp" in the layout folder
Here is my search function:
public function searchIndex(){
//debug($this->request->data); die;
$search = $this->request->data['Concessionnaire']['search'];
$this->Paginator->settings = array(
'conditions' => array('Concessionnaire.ville LIKE' => '%'.$search.'%'),
'limit' => 5
);
$data = $this->Paginator->paginate('Concessionnaire');
$this->set('concessionnaires', $data);
$this->render('index');
}
Views :
<div class="row">
<div class="large-12 columns">
<div class="panel">
<h4>Recherchez une ville :</h4>
<?php echo $this->Form->create('Concessionnaire',array('id' => 'textBox', 'type' => 'post','url' => array('controller' => 'concessionnaires', 'action' => 'searchIndex'))); ?>
<?php echo $this->Form->input('search', array('label'=>"",'placeholder'=>'Tapez le nom d\'une ville, puis la touche Entree de votre clavier' ,'id'=>'search')); ?>
<?php echo $this->Form->end(); ?>
</div>
</div>
</div>
<div class="row">
<div class="large-12 columns">
<div class="panel" id="conssR">
<!-- generation vignettes -->
<?php foreach ($concessionnaires as $concessionnaire): ?>
<div class="panel conssPanel radius">
<h4><b><?php echo h($concessionnaire['Concessionnaire']['nom']); ?></b></h4>
<div class="row">
<div class="large-6 columns" style="padding-left: 70px; font-size: 20px;">
<?php echo h($concessionnaire['Concessionnaire']['adresse']); ?><br>
<?php echo h($concessionnaire['Concessionnaire']['cp']); ?>
<?php echo h($concessionnaire['Concessionnaire']['ville']); ?>
<!-- <p>It's a little ostentatious, but useful for important content.</p> -->
</div>
<div class="large-6 columns" style="font-size: 20px; text-align: center;">
Tel: <?php echo h($concessionnaire['Concessionnaire']['tel']); ?><br>
Site: <?php echo h($concessionnaire['Concessionnaire']['website']); ?>
</div>
</div>
<?php
// $map_id = "map_canvas";
// $marker_id = 1;
// $position = "rue du depot, 62000 ARRAS";
// echo $this->GoogleMap->addMarker($map_id, $marker_id, $position);
?>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
I want to reload the DIV "#conssR" with the string results entered in the form "Concessionnaires". For now , when i write something and valid, the controller show me the result by refreshing the page but I just want to recharge the DIV.
Thank you in advance for your help
$this->Paginator->options(array(
'update' => '#conssR',
'evalScripts' => true
));
The code above is not part of function it is part of view files which are in View folder and it creates the proper JavaScript to update the div.
Check : http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html
It is a helper and helper code goes in your view
if($this->request->is('ajax'))
{
$this->render('/Elements/ajax');
}
The above code is used to render ajax.ctp in View/Elements folder which you are not doing at the moment.
I want to add some JavaScript validation to my form of password creation.
I have the following as javascript
function Validation(){
var password = document.getElementById('password').value;
var error = document.getElementById('error');
if((/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]+$/).test(password) == false){
error.html('error');
}
}
I have the following code in my _form.php for the user creation
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'users-form',
'htmlOptions'=>array('onsubmit'=>'return Validation()'),
// Please note: When you enable ajax validation, make sure the corresponding
// controller action is handling ajax validation correctly.
// There is a call to performAjaxValidation() commented in generated controller code.
// See class documentation of CActiveForm for details on this.
'enableAjaxValidation'=>false,
)); ?>
<p class="note">Fields with <span class="required">*</span> are required.</p>
<?php echo $form->errorSummary($model); ?>
<div class="row">
<?php echo $form->labelEx($model,'username'); ?>
<?php echo $form->textField($model,'username',array('size'=>20,'maxlength'=>20)); ?>
<?php echo $form->error($model,'username'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,'password'); ?>
<?php echo $form->passwordField($model,'password',array('size'=>60,'maxlength'=>255)); ?>
<?php echo $form->error($model,'password'); ?>
</div>
<div class="row buttons">
<?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>
</div>
<div id="error">
</div>
<?php $this->endWidget(); ?>
Now i do have my script imported and even when i put a simple alert('hello') it doesnt work when i press create.
Also i know the validation wont work properly since i am hashing the password. How i can validate it before it becomes hash.
You can do it two way
1) With form htmlOptions
<?php Yii::app()->clientScript->registerScript('someScript', "
validate = function(){
alert("Your Validation Function");
return false;
}
");
?>
<?php $form=$this->beginWidget('CActiveForm', array(
'id' => 'user-form',
'enableAjaxValidation' => false,
'htmlOptions' => array(
'onsubmit'=>"return validate();",
),
)); ?>
2) With Jquery submit method
<?php Yii::app()->clientScript->registerScript('someScript', "
$('#user-form').submit(function() {
alert("Your validation");
});
");
?>
<?php $form=$this->beginWidget('CActiveForm', array(
'id' => 'user-form',
'enableAjaxValidation' => false,
)); ?>