I am rendering an ActiveForm dynamically via ajax, however because the form isn't there on page load, the necessary JS files yiiActiveForm.js, yii.validation.js) and the associated validation triggers aren't there when the form is echoed out.
Here is some sample code:
JS:
$('.btn-edit').on('click', function() {
var id = $(this).attr('data-id');
var url = base_url + '/account/editreview/' + id;
$.ajax({
type: 'post',
url: url,
dataType: 'json',
success: function(result) {
$('.popup').html(result.html);
}
});
});
Controller:
public function actionEditReview($id)
{
$return_array = [
'html' => null,
];
$review = $this->findReview($id);
$return_array['html'] = $this->renderPartial('review-popup', [
'review' => $review,
]);
echo json_encode($return_array);
}
View (review-popup.php):
<?php
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin([
'id' => 'review-form',
'enableAjaxValidation' => false,
'enableClientValidation' => true,
]); ?>
<?php echo $form->field($review, 'title')->textInput(); ?>
<button type="submit" class="btn-edit" data-id="<?php echo $review->id; ?>">Submit</button>
<?php ActiveForm::end(); ?>
I have read the notes on this page https://yii2-cookbook.readthedocs.io/forms-activeform-js/ but this talks about adding validation to single attributes, and not to an entire form.
Does anyone know how to do this?
I found the solution: use renderAjax() instead of renderPartial() when echoing out the view.
http://www.yiiframework.com/doc-2.0/yii-web-view.html#renderAjax()-detail
Related
Definition :
I want to send text data from the template (ctp file) to the controller but it is not working.
What I DO Until now :
I have this controller courses and it has function called search as following :
/src/Controller/CoursesController :
public function search()
{
$search = $this->request->getData('keyword');
debug($search);die;
...
The /src/Template/search:
<?= $this->Form->create(null, ['url' => ['controller'=>'courses','action' => 'search']]) ?>
<?= $this->Form->control('keyword', ['label' => false, 'type'=>'text','class'=>'form-control', 'placeholder' => __('Search for...')]); ?>
<?= $this->Form->button(__('Go'), ['class' => 'btn btn-default', 'type' => 'submit']) ?>
<?= $this->Form->end() ?>
Despite my attempts to get the text data from the form and print it using debug but unfortunately I've got empty array
try this:
public function search()
{
$data = $this->request->data;
if($this->request->is(['patch', 'post', 'put', 'get']))
{
$search = $this->request->data('keyword');
debug($search);
}
}
index.php
<?php
Yii::app()->clientScript->registerScript('items_update',
"$('#dropit').change(function(){
$.ajax({
url: '".Yii::app()->createUrl('survey/questions')."',
data:
{
_designation : test,
},
type: 'POST',
success:function()
{
console.log('success');
},
error:function()
{
console.log('failure');
}
});
return false;
});
");
?>
<div id="surveyupdate">
<?php
echo CHtml::dropDownList('dropit', '',
array(
'Reception'=>'Service Reception',
'SA'=>'ServiceAdvisor','Billing'=>'Billing Staff',
'Parts'=>'Parts Counter','Cashier'=>'Cashier','Cwd'=>'Customer Welfare Desk'),
array('prompt'=>'- select -'));
?>
</div>
<?php
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_view',
'id'=>'ajaxListView',
));
?>
controller 'survey.php'
public function actionQuestions()
{
//debugging purposes
echo "<pre>";
print_r($_POST);
exit;
}
To Do's
What I'm trying to do is to update the CListView by getting the selected data from dropdownlist via POST that to be evaluated by the controller, get the data from database and update the CListview.
Please help me. I'm just newly learning Yii. Thanks!
You need to add Id for dropdownList, like below
echo CHtml::dropDownList('dropit', '',
array(
'Reception'=>'Service Reception',
'SA'=>'ServiceAdvisor','Billing'=>'Billing Staff',
'Parts'=>'Parts
Counter','Cashier'=>'Cashier','Cwd'=>'Customer Welfare
Desk'),
array('prompt'=>'- select -', 'id'=>'dropit')); // added I'd here
In yii2 project I have my own file structure setup. Anything uploaded will get saved as a file type. I can get the file dimensions using the file uploaded in the temp folder by yii2. Using those dimensions I set my own width and height and compare them. If the height and width is more than what I have declared It has display an error message in the form. Which I am unable to do it.
My Active Form
<div class="company-form">
<?php
$form = ActiveForm::begin([
'action'=>['company/logo', 'id'=>$model->company_id],
'validateOnSubmit' => true,
'options' =>
['enctype' => 'multipart/form-data','class' => 'disable-submit-buttons','id'=> 'companyLogoForm'],
'fieldConfig' => [
'template' => "<div class=\"row\">
<div class=\"col-xs-6 margin-top-8\">{label}</div>\n<div class=\"col-xs-6 text-right\">{hint}</div>
\n<div class=\"col-xs-12 \">{input}</div>
</div>",
],
]); ?>
<?= $form->errorSummary($model, $options = ['header'=>'','class'=>'pull-left']); ?>
<?= $form->field($model, 'company_name')->hiddenInput(['maxlength' => true])->label(false) ?>
<?= $form->field($file, 'file')->fileInput([])->label(Yii::t('app', 'Attach Logo'),['class'=> 'margin-top-8']) ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? Yii::t('app', 'Save') : Yii::t('app', 'Save'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary','data' => ['disabled-text' => 'Please Wait']]) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
My Controller Action
public function actionLogo($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
$file = new File;
$file->load(Yii::$app->request->post());
$a = UploadedFile::getInstance($file,'file');
$size = getimagesize($a->tempName);
$maxWidth = 500;
$maxHeight = 500;
if ($size[0] > $maxWidth || $size[1] > $maxHeight)
{
$model->addError('file', $error = 'Error Message');
if($model->hasErrors()){
return ActiveForm::validate($model);
}
}
$file->file = UploadedFile::getInstance($file,'file');
$file->file_name = $file->file->name;
$file->file_user = Yii::$app->user->id;
$file->file_type = 1;
if($file->save()){
$file->file_path = Files::getFilePath($file->file_id);
$validDir = $file->file->createFileDir($file->file_path, $file->file_id);
if($validDir){
$file->file->saveAs($file->file_path, false);
if($file->save()){
$model->company_file = $file->file_id;
$model->save();
return $this->redirect(['index']);
}
}
}
}
}
How do I add error message in the controller and pass that to display on my form on the modal box.
Note: my form is displayed on the modal box.
Thank you!!
You should handle the file processing in your model - or even better, create a specific UploadForm model for this purpose.
In that case you can use File Validation or a custom validator to set errors during model validation.
The built-in yii\validators\FileValidator gives you plenty pf validation rules out of the box.
This is actually pretty well explained in the documentation: Uploading Files
See also the documentation for FileValidator
Example for validating an uploaded image file:
namespace app\models;
use yii\base\Model;
use yii\web\UploadedFile;
class UploadForm extends Model
{
/**
* #var UploadedFile
*/
public $imageFile;
public function rules()
{
return [
[['imageFile'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],
];
}
public function upload()
{
if ($this->validate()) {
$this->imageFile->saveAs('uploads/' . $this->imageFile->baseName . '.' . $this->imageFile->extension);
return true;
} else {
return false;
}
}
}
Try this validation rule
['imageFile', 'image', 'minWidth' => 250, 'maxWidth' => 250,'minHeight' => 250, 'maxHeight' => 250, 'extensions' => 'jpg, gif, png', 'maxSize' => 1024 * 1024 * 2],
It appears that the links aren't in correct order and I can't figure out why. I have it in other grids, they seem to be fine.
This is what the link shows:
index.php?ajax=gridID&id=180&r=controller/action
when it's suppose to show:
index.php?r=controller/action&id=180
this is my value in gridview:
'value'=>function($data,$row){
if (intval($data->sid) ==$someID){
if($data->accept == "ACCEPTED")
return CHtml::Link("[X]", array("controller/action","id"=>$data->id),
array('confirm' => 'Are you sure?',
'class'=>'stat')
);
}
where grid is suppose to refresh on confirm:
<?php
Yii::app()->clientScript->registerScript('stat', "
$('#gridId a.stat').live('click', function() {
$.fn.yiiGridView.update('gridId', {
type: 'POST',
url: $(this).attr('href'),
success: function() {
$.fn.yiiGridView.update('gridId');
}
});
return false;
});"
);
?>
if you need generate url on "path" format (controller/action/id/180) and without script name you can set urlFormat property in UrlManager to "path" and set showScriptName property to false. Look this and this
in aplication config file:
'urlManager' => array(
'urlFormat' => 'path',
'showScriptName' => false,
)
I use CGridView to render a result (invoice rows) from a db query. This is done inside a <div> on html page that is later converted to a PDF using wkhtmltopdf and printed. The problem is that today I have no support for page break so if number of invoice rows are greater than 10 the remaining rows are not visible. I can't let the div flow since I have an invoice footer with an absolute position that can't move.
Is there a way to force a page break and continue rendering rows on a separate page?
Below is part of the CGridView code used.
<...plenty of html---->
<div class="invoiceRow">
<?php
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider' => $dpRows,
'cssFile' => Yii::app()->request->baseUrl . '/css/invoice.css',
'summaryText' => '',
'enablePagination' => false,
'columns' => array(
'number',
'name',
'description',
'amount',
array (
'name'=>'value',
'header' => 'netprice',
'value' => 'number_format($data->value,2,","," ")'
),
));
?>
</div>
<---more html ----->
If wkhtml is able to parse css (it seems so) you could try:
<div style="page-break-after:always">
//X invoices here
</div>
if(!empty($model))
{
if($model->content_type==1)
{
$sentences = explode ('<div style="page-break-after: always;"><span style="display:none"> </span></div>',$model->content);
?>
<div id="datashow">
<?php
echo $sentences[0];
?>
</div>
<?php
$dummy=array();
$kcnt=preg_match_all('/page-break-after: always/', $model->content,$dummy);
// echo $model->content;
}
<script>
$("#pagebreakdiv").find(":button").click(function () {
var datashow=$('#datashow');
var a=this.value;
var bid='<?php echo $bid; ?>';
var id='<?php echo $id; ?>';
var pdata = {};
pdata["bitt"] = a;
pdata["bid"] = bid;
pdata["id"] = id;
$.ajax(
{
url : "<?php echo Yii::app()->request->baseUrl; ?>/UserSimple/Contentpagebreak",
type: "POST",
data : pdata,
success:function(data, textStatus, jqXHR)
{
datashow.html(data);
},
error: function(jqXHR, textStatus, errorThrown)
{
}
});
});
</script>