Yii2: Kartik's DetailView and Select2 loading id's not text - json

So I'm loading Kartik's Select2 widget in Kartik's DetailView using multiple input:
[
'attribute' => 'characters',
'format' => 'raw',
'type' => DetailView::INPUT_SELECT2,
'value' => function($form, $widget) {
<my_stuff_in_VIEW_mode>
},
'widgetOptions' => [
'options' => ['multiple' => true, 'placeholder' => Yii::t('app', 'Select...')],
'pluginOptions' => [
'allowClear' => true,
'minimumInputLength' => 3,
'maximumInputLength' => 20,
'language' => Yii::$app->language,
'ajax' => [
'url' => \yii\helpers\Url::to(['myAjaxServer']),
'dataType' => 'json',
'delay' => 250,
'data' => new JsExpression('function(params) { return {q:params.term, p:params.page}; }'),
'cache' => true,
],
'escapeMarkup' => new JsExpression("function (markup) { return markup; }"),
'templateResult' => new JsExpression("function (characters) { return '<b>' + characters.text + '</b>'; }"),
'templateSelection' => new JsExpression("function (characters) { return characters.text; }"),
],
],
],
When it comes to Kartik's DetailView, VIEW mode correctly shows my list of characters given by value, but when entering EDIT mode I got this:
which obviously is not what I expected: I want my characters' names rather than their IDs. However if I select new characters from this very same input dropdown, new tags are added which properly show the new names (thus this issue happens when updating data). After I confirm the new data and then try to update, new characters are shown with their IDs again.
JSON data is as follows:
{"results":[{"id":"8","text":"Character8"},{"id":"5","text":"Character5"}],"pagination":{"more":true}}
Any ideas?
UPDATED WITH SOLUTION BY KARTIK BELOW:
Add initValueText as an array of desired attribute values:
'initValueText' => ArrayHelper::getColumn($model->characters, 'name'),

You need to set Select2::initValueText when using Select2 with ajax to show the displayed name instead of id. For multiple select this needs to be setup as an array.

Related

Listview pagination and GET parameters on the next page

I have this UrlManager rule:
'<pageSlug>-pa<pageId:\d+>' => 'page/page',
Then I have page with url like this domain.com/blog-pa54
In this example I have
pageSlug = blog and pageId = 54
In my view I have ListView with my blog posts.
I set my dataprovider like this:
$dataProvider = new ActiveDataProvider([
'query' => BlogPost::find()
->where([
'active' => 1
]),
'pagination' => [
'defaultPageSize' => 3,
//'params' => [], when I set this, it only shows get param "page"
'pageParam' => 'page',
'route' => $pageURL, // this variable is equal to "blog-pa54"
],
]);
My route is current url slug - blog-pa54
When I go to next page I recieve this url: blog-pa54?pageSlug=blog&pageId=54&page=2
How can I remove $_GET params pageSlug and pageId from url?
I try to set pagination > params = [] and it remove this get param, but when I go to other page it doesn't change items in my ListView
Here is also my ListView and LinkPager
<div class="blog-post-wrapper">
<?= ListView::widget([
'dataProvider' => $blogPostsDataprovider,
'itemOptions' => ['tag' => null],
'options' => [
'tag' => false,
],
'layout' => "{summary}<div class='row'>{items}</div>",
'itemView' => function ($model, $key, $index, $widget) use ($page) {
return $this->render('//blog-post/_blogPostList', [
'page' => $page,
'model' => $model
]);
},
]); ?>
</div>
<?= \yii\widgets\LinkPager::widget([
'pagination' => $blogPostsDataprovider->pagination,
'linkContainerOptions' => [
'class' => 'page-item',
],
'linkOptions' => [
'class' => 'page-link',
],
]); ?>
Okay, I figured it out.
params attribute must not be empty.
You can set it like this:
'params' => [
'page' => isset($_GET['page']) ? $_GET['page'] : 1,
]
Or if you have another get params like get filters:
$getParams = [];
if(isset($_GET)){
foreach($_GET as $getKey => $getValue){
if(in_array($getKey, ['pageSlug', 'pageId'])){ //here I skip my params from UrlManager rule
continue;
}
$getParams[$getKey] = $getValue;
}
}
.....
'params' => $getParams

Show name of saved file in Upload Field using kartik form in Yii2

I have an application built using Yii2 framework, and the app has a form using kartik\form\ActiveForm, this is some line in my _form.php. In that form, user should upload a file, and submit it. After that form successfully saved, the user trying to update the data, but the form didn't show the saved uploaded file. Like this
I need to show the saved file name in that upload field. How do I can do it?
This is my code in _form.php
<?=
$form->field($model, 'buktiNpwp')->widget(FileInput::classname(), [
'options' => [
'multiple' => false,
'accept' => 'img/*', 'doc/*', 'file/*',
'class' => 'optionvalue-img',
'placeholder' => 'maximum size is 2 MB',
],
'pluginOptions' => [
'allowedFileExtensions' => ['jpg', 'gif', 'png', 'jpeg'],
'maxFileSize' => 2048, //membatasi size file upload
'layoutTemplates' => ['footer' => 'Maximum size is 2 MB'],
'browseLabel' => 'Browse (2MB)',
'showPreview' => false,
'showCaption' => true,
'showRemove' => true,
'showUpload' => false,
]
]);
?>
To save images do this in your controller. Hope that will work
$model = new YourModel();
$files = UploadedFile::getInstances($model, 'name');
foreach($files as $file){
$path = 'somepath';
$file->saveAs($path);
}
on update controller you can do
$images_old = \common\models\YourModel::find()->where(['=', 'some_id', $model->id])->all();
if ($images_old) {
foreach ($images_old as $image) {
$baseurl = \Yii::$app->request->BaseUrl;
$image_url = $baseurl . '/uploads/' . $image->thumbnail;
$all_images[] = Html::img("$image_url", ['class' => 'file-preview-image']);
$obj = (object) array('caption' => '', 'url' => $baseurl . '/some-path/delete-image', 'key' => $image->id);
$all_images_preview[] = $obj;
}
}
Now send the $all_images_preview and $all_images to your view file and show it like
$form->field($images, 'name[]')->widget(FileInput::classname(), [
'options' => ['accept' => 'image/*', 'multiple' => true],
'pluginOptions' => [
'previewFileType' => 'image',
'allowedFileExtensions' => ['jpg', 'gif', 'png', 'bmp','jpeg'],
'showUpload' => true,
'initialPreview' => $all_images,
'initialPreviewConfig'=>$all_images_preview,
'overwriteInitial' => false,
'showRemove' => true,
'showPreview' => true,
'uploadUrl' => Url::to(['cases/upload']),
//'onRemove'=>''
],
]);
In your controller class and just actionUpload define upload file directory path, because UploadedFile model save a file in absolute physical path. If you need, can necessary verify post variable use $_FILES. The method saveAs need complete absolute file path and file name. Use slash or backslash according to its SO to best results.

Error InputWidget.php line 75 properties must be specified

I want to make input field with tag using Input Tags Widget. But I got this error :
Either 'name', or 'model' and 'attribute' properties must be
specified.
in /var/www/html/paramoor/vendor/yiisoft/yii2/widgets/InputWidget.php at line 75:
/**
* Initializes the widget.
* If you override this method, make sure you call the parent implementation first.
*/
public function init()
{
if ($this->name === null && !$this->hasModel()) {
throw new InvalidConfigException("Either 'name', or 'model' and 'attribute' properties must be specified.");
}
if (!isset($this->options['id'])) {
$this->options['id'] = $this->hasModel() ? Html::getInputId($this->model, $this->attribute) : $this->getId();
}
parent::init();
}
And here's my View Code :
<?= $form->field($modelDetail, 'product_id')->widget(TagsinputWidget::classname(),
[
'clientOptions' => [
'trimValue' => true,
'allowDuplicates' => false,
'delimiter' => ';',
],
]) ?>
When using widgets for fields/filters/etc., you need to provide one (or two) of those options. You have 2 options:
Give model and attribute:
<?= $form->field($modelDetail, 'product_id')->widget(TagsinputWidget::classname(),
[
'model' => $modelDetail,
'attribute' => 'product_id',
'clientOptions' => [
'trimValue' => true,
'allowDuplicates' => false,
'delimiter' => ';',
],
]) ?>
Give just name (as combined model and attribute name):
<?= $form->field($modelDetail, 'product_id')->widget(TagsinputWidget::classname(),
[
'name' => 'ModelDetail[product_id]',
'clientOptions' => [
'trimValue' => true,
'allowDuplicates' => false,
'delimiter' => ';',
],
]) ?>
I suggest using first option as if model name is changed, you won't need to search where this model name was used as string.

kartik DynaGrid select2 filter not render

my setup column using kartik DynaGrid Widget to display data on yii2. but filter (FILTER_SELECT2) not render on my table. Can someone help me? Please.
'class' => 'kartik\grid\DataColumn',
'attribute' => 'city_id',
'label' => 'City',
'hAlign' => 'center',
'vAlign' => 'middle',
'width' => '70px',
'filterType' => GridView::FILTER_SELECT2,
'filter' => [
1 => 'filter 1',
2 => 'filter 2',
],
'format' => 'html',
'value' => function($data){
$cities = \app\models\City::getData();
if(isset($cities[$data->city_id])){
return $cities[$data->city_id];
}
return $data->city_id;
}
Post your grid config. Maybe you turn off filter in config. Default config is this
....
'gridOptions'=>[
'dataProvider'=>$dataProvider,
'filterModel'=>$searchModel,
....
],

yii2: get relation data in kartik editable widget

I am using kartik yii2 editable extension to edit inline in gridview.
The extension is working fine.
Please refer this screen-shot link [http://awesomescreenshot.com/00753dvb73][1]
In this screen-shot the source field is a dropdown and I want the value of source instead id its id
My View
use kartik\editable\Editable;
[
'attribute'=>'source',
'format'=>'raw',
'value'=> function($data){
//$s = $data->getBacklog_source();//var_dump($s);exit;
return Editable::widget([
'name'=>'source',
'model'=>$data,
'value'=>$data->source,
'header' => 'Source',
'type'=>'primary',
'size'=> 'sm',
'format' => Editable::FORMAT_BUTTON,
'inputType' => Editable::INPUT_DROPDOWN_LIST,
'data'=>$data->getSource(), // any list of values
'options' => ['class'=>'form-control', 'prompt'=>'Select Source'],
'editableValueOptions'=>['class'=>'text-danger'],
'afterInput' => Html::hiddenInput('id',$data->id),
]);
}
],
The relation I made is:
public function getSource()
{
$source = BacklogSource::find()->all();
return ArrayHelper::map($source, 'id', 'Source');
}
public function getBacklog_complexity()
{
return $this->hasOne(BacklogComplexity::className(), [
'id' => 'complexity'
]);
}
Thanks for help in advance
I got the solution something like this:
[
'attribute'=>'status',
'format'=>'raw',
'value'=> function($data){
$s = BacklogStatus::findOne($data->status);
return Editable::widget([
'name'=>'status',
'model'=>$data,
'value'=>$s->Status,
'header' => 'Status',
'type'=>'primary',
'size'=> 'sm',
'format' => Editable::FORMAT_BUTTON,
'inputType' => Editable::INPUT_DROPDOWN_LIST,
'data'=>$data->getStatus(), // any list of values
'options' => ['class'=>'form-control', 'prompt'=>'Select Source'],
'editableValueOptions'=>['class'=>'text-danger'],
'afterInput' => Html::hiddenInput('id',$data->id),
]);
}
],