I'm not sure if this is a new bug or what's going on, but I'm having trouble getting the Yii2 validator to recognize a file is there after it's been uploaded. The client side validation works fine.
Rules for the model:
return [
[['store_id', 'name', 'csv'], 'required'],
[['store_id', 'created_at', 'updated_at'], 'integer'],
[['name'], 'string', 'max' => 255],
[['csv'], 'file', 'skipOnEmpty' => false, 'maxSize'=>1024 * 1024 * 2],
];
Controller Action:
public function actionUploadFromCsv()
{
$store = Yii::$app->user->identity->store;
$store_csv = new StoreCsv;
$store_csv->store_id = $store->id;
$store_csv->name = $store_csv->getDefaultName();
if (Yii::$app->request->isPost) {
$store_csv->csv = UploadedFile::getInstance($store_csv, 'csv');
if ($store_csv->upload()) {
return $this->redirect(['view-csv', 'id'=>$store_csv->id]);
}
return json_encode($store_csv->getErrors());
}
return $this->render('csv_upload', [
'store'=>$store,
'csv'=>$store_csv
]);
}
Model Upload() Function:
public function upload()
{
if ($this->validate()) {
$file_name = uniqid(rand(), false) . '.' . $this->csv->extension;
$this->csv->saveAs(Yii::getAlias('#backend') . '/web/store/' . $this->store_id . '/csv/' . $file_name);
$this->csv = $file_name;
return $this->save();
}
return false;
}
Form Markup:
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
<?= $form->field($csv, 'csv')->fileInput() ?>
<div class="form-group">
<?= Html::submitButton('Submit', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
Currently when I perform the upload I get this error after validation fails:
{"csv":["Please upload a file."]}
If I change 'skipOnEmpty' to true, however, it works fine. It saves the model and moves and renames the temporary file. I would like to get validation working though, so I can restrict to certain extensions. What's the deal? I've spent hours trouble shooting this.
I figured out what my problem here is. After saving the file I try to rename it, however, the way I do it here takes away the association of this attribute as a file.
Wrong:
$this->csv = $file_name;
Right:
$this->csv->name = $file_name;
In addition, I originally asked this question because I was having trouble getting the validator to work, restricting extensions. It would not recognize "xls" or "csv" after the client side validation when I did $model->validate(). I just found that this is a known issue due to the MIME TYPE validator:
https://github.com/yiisoft/yii2/issues/6148
The solution to the extension issue is to set checkExtensionByMimeType to false:
[['csv'], 'file', 'skipOnEmpty' => false, 'extensions'=>['xls', 'csv'], 'checkExtensionByMimeType'=>false, 'maxSize'=>1024 * 1024 * 2],
What is your FORM markup? View the page source within the browser. Files are ignored unless the form markup has has multipart/form-data.
<form action="upload.php" method="post" enctype="multipart/form-data">
Related
I have a create action of controller where I passed $ingredients array into the view
public function actionCreate()
{
return $this->render('create',
['model' => $model, 'ingredients' => Ingredient::find()->all()]
);
}
In create.php I can acess $ingredients variable.
But if I try to access $ingredients in the _form.php
<?= $form->field($model, 'ingredient_id')->checkbox(
ArrayHelper::map($ingredients, 'id', 'name')
) ?>
I get error
Undefined variable: ingredients
This can be done by two ways
//first render the view file like this
$params = [];
$params['eqpType'] = $eqpType;
$params['discountModel'] = $discountModel;
$params['tabActive'] = $tabActive;
$params['discountLabel'] = $discountLabel;
echo $this->render('_form', $params);
//or you can include the code file directly ..in this case do not need to pass all perameters
<?php include_once "_form.php";?>
Your are passing the variables to the create view, and your widget is in another view called _form. Go to the create view and make sure that all variables are passed to the _form view.
in create.php
<?php echo $this->render('_form', [
'model' => $model,
'ingredients' => $ingredients
]) ?>
I am doing a project how to calculate total in yii2. When i'm building the project, i found trouble when i'm input data to be percent format. When I'm save data,in index look 2,300%, even though it is 23%. What can i do?
In my view, format like this'format'=>['percent',],
enter image description here
this is my code
<?php
use yii\helpers\Html;
use kartik\grid\GridView;
/* #var $this yii\web\View */
/* #var $searchModel backend\models\LaporanSearch */
/* #var $dataProvider yii\data\ActiveDataProvider */
$this->title = 'Laporans';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="laporan-index">
<h1><?= Html::encode($this->title) ?></h1>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<p>
<?= Html::a('Create Laporan', ['create'], ['class' => 'btn btn-success']) ?>
</p>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'showPageSummary'=>true,
'columns' => [
['class' => 'kartik\grid\SerialColumn'],
// 'id',
// 'inv_no',
// 'inv_date',
//'rate',
[
'attribute'=>'kode_customer',
// 'width'=>'150px',
//'hAlign'=>'right',
// 'format'=>['decimal', 0],
],
// 'kode_item',
// 'qty',
// 'price',
// 'ed',
['attribute'=>'total_price',
'pageSummary'=>true
],
// 'dsc',
['attribute'=>'total_dsc',
'pageSummary'=>true
], // 'trans',
['attribute'=>'total_trans',
'pageSummary'=>true
],
['attribute'=>'total_margin_rp',
'pageSummary'=>true
],
['attribute'=>'total_margin_persen',
'pageSummary'=>true,
// 'groupSeparator' => '.',
'format'=>['percent',],
], // 'kode_area',
['class' => 'kartik\grid\ActionColumn'],
],
]); ?>
</div>
The problem you have is probably due to the fact that you have stored the actual percentage value in the database. So for example your 23% is actually the number 23 in your database table.
If you look at the documentation for the percent formatter in Yii2 here (http://www.yiiframework.com/doc-2.0/yii-i18n-formatter.html#asPercent()-detail) you will see that it says:
The value to be formatted. It must be a factor e.g. 0.75 will result
in 75%.
So for your data to show up correctly you either have to provide the data as a factor, use a different formatter or write your own formatting function.
I have created a method in my model that successfully displays the correct data when I pr($variable) to the screen. However without the print I am receiving the 'Notice (8): Undefined variable' message.
The model in question 'industry' has many 'news and events'.
What I'm trying to do in the view for a specific industry is display news that is of two different conditions. One type of news is news.type = highlight(displaying just one highlight story), and the second is a list of active stories.
This is the method in my model.
// industry highlight news
public function getHighlightNews() {
$newsHeadline = $this->News->find('first', array(
'conditions' => array('News.type' => 'highlight','News.active' => 'yes'),
'limit' => 1,
'recursive' => 0,
'fields' => array(
'News.slug',
'News.title',
'News.date',
'News.imgPathThumb',
'News.alt_tag',
'News.id',
'News.caption',
'News.body'
),
));
return $newsHeadline;
}
public function getNewsList() {
$newslist = $this->News->find('all', array(
'conditions' => array('News.active = "Yes"','News.industry_id = 1'),
'limit' => 4,
'recursive' => 0,
'fields' => array(
'News.slug',
'News.title',
'News.date',
'News.industry_id',
'News.imgPathThumb',
'News.alt_tag',
'News.id',
'News.caption',
'News.body'
),
));
return $newslist;
}
And this is what is in my industry controller. I've created similar model methods for the news list and event lists.
public function view($id = null) {
$this->layout='default';
$this->Industry->id = $id;
if (!$this->Industry->exists()) {
throw new NotFoundException(__('Invalid industry'));
}
$eventlist = $this->Industry->getEventsList($id);
$newslist = $this->Industry->getNewsList($id);
$highlights = $this->Industry->getHighlightNews($id);
//pr($newslist); die;
$this->set('eventlist', $eventlist, 'newslist', $newslist, 'highlights', $highlights);
}
And this is my view:
<div class="first articles">
<?php foreach ($highlights as $highlight): ?>
<h1><?php echo $highlight['Industry']['title']; ?></h1>
<p><?php echo $highlight['Industry']['body']; ?>
<?php endforeach; ?>
</p>
</div><!-- /articles -->
the message I get in the view is:
Notice (8): Undefined variable: highlights [APP\View\Industries\view.ctp, line 12]
Warning (2): Invalid argument supplied for foreach() [APP\View\Industries\view.ctp, line 12]
I suspect it's something small I'm overlooking.
Thanks, Paul
Setting variables doesn't work like that. You need to change this:
$this->set('eventlist', $eventlist, 'newslist', $newslist, 'highlights', $highlights);
To this:
$this->set('eventlist', $eventlist);
$this->set('newslist', $newslist);
$this->set('highlights', $highlights);
Or this:
$this->set(compact('eventlist','newslist','highlights'));
in ZF1 form and form elements had a setDescription method that was outputted as <p>description here</p> in view ....
ZF2 seems that doesn't have this method
so my question is how can i add description to form elements ?
this is my view :
<div>
<?
$form = $this->form;
$form->prepare();
echo $this->form()->openTag($form);
foreach ($form->getElements() as $el) {
?>
<div class="form_element">
<?=$this->formRow($el);?>
</div>
<?
}
echo $this->partial('system/form/buttons_form_part.phtml', array('form' => $form));
echo $this->form()->closeTag();
?>
</div>
Using ZF 2.1.5, one solution might be setOptions().
In the form definiton:
$file = new Element\File('file');
$file->setLabel('Photo (.jpg, .gif, .png)');
$file->setOptions(array('description' => 'test description'));
…
When rendering the form element:
$element = $form->get(…);
var_dump($element->getOptions());
Will give you access to:
array(1) { ["description"]=> string(16) "test description" }
If you mean a label for an Element you can use the setLabel method when you create the form (in Controller).
$name = new Element('name');
$name->setLabel('Your name');
Or if you use an array to create your form elements use this:
array(
'spec' => array(
'name' => 'name',
'options' => array(
'label' => 'Your name',
),
'attributes' => array(
'type' => 'text'
),
)
),
Here is a link:
enter link description here
I wish to generate the following markup:
<label>some label here <span>(optional)</span></label>
Is there a way to do this, by using Yii labelEx or just label?
Thanks
If the attribute is required
You can set the CHtml static properties like this
CHtml::$beforeRequiredLabel = '';
CHtml::$afterRequiredLabel = '<span>(optional)</span>';
Yii will generate a tag
<label>CHtml::$beforeRequiredLabel.$label.CHtml::$afterRequiredLabel</label>
but the static properties will effect all labels generated by $form->labelEx() (#see CHtml::activeLabelEx())
if you don't need, you must set the static properties to default
If the attribute is not required
you can set the htmlOptions
$form->labelEx($model, $attribute, array('label' => 'your label'))
It's simple, make use of the Decorator pattern:
<?php
// components/CustomCHtml.php
class CustomCHtml extends CHtml
{
public static function activeLabelEx($model,$attribute,$htmlOptions=array())
{
if (isset($htmlOptions['optional']) && $htmlOptions['optional']) {
if (isset($htmlOptions['label']) && $htmlOptions['label']) {
$htmlOptions['label'] .= $htmlOptions['optional'];
} else {
$htmlOptions['label'] = $htmlOptions['optional'];
}
}
return parent::activeLabelEx($model,$attribute,$htmlOptions);
}
}
use case:
<?php echo CustomCHtml::activeLabelEx($model, 'field', array('optional'=>' <span>(optional)</span>')); ?>
Here is a little hack to make it possible.
<?php
$username = $form->field($model, 'username')
->input('text', ['class' => 'form-control input-lg'])
->label(true, 'username', ['class' => 'fa fa-user signin-form-icon']);
$username->parts['{label}'] = '<span class="fa fa-user signin-form-icon">dwe</span>';
echo $username;
?>
You could use CHtml::$afterRequiredLabel and/or CHtml::$beforeRequiredLabel
$initValue = CHtml::$afterRequiredLabel;
CHtml::$afterRequiredLabel = $initValue.'<span>(optional)</span>';
echo $form->labelEx($model, $fname, array('class' => ''));
echo $form->textField($model, $fname, array('class' => ''));
CHtml::$afterRequiredLabel = $initValue;
This way the label will be applied only on the specified form field. You actually set the initial value of CHtml::$afterRequiredLabel and/or CHtml::$beforeRequiredLabel on a temp variable, you overwrite the value that you need, and then reset it to original value.