Yii2 Kartik Select2 - Template to formatting each list element - yii2

i'm looking to Kartik Select2 Page
In particular i want to add an image to each element of the list like the example:
use kartik\widgets\Select2;
use yii\web\JsExpression;
use yii\bootstrap\Modal;
// Templating example of formatting each list element
$url = \Yii::$app->urlManager->baseUrl . '/images/flags/';
$format = <<< SCRIPT
function format(state) {
if (!state.id) return state.text; // optgroup
src = '$url' + state.id.toLowerCase() + '.png'
return '<img class="flag" src="' + src + '"/>' + state.text;
}
SCRIPT;
$escape = new JsExpression("function(m) { return m; }");
$this->registerJs($format, View::POS_HEAD);
echo '<label class="control-label">Provinces</label>';
echo Select2::widget([
'name' => 'state_12',
'data' => $data,
'options' => ['placeholder' => 'Select a state ...'],
'pluginOptions' => [
'templateResult' => new JsExpression('format'),
'templateSelection' => new JsExpression('format'),
'escapeMarkup' => $escape,
'allowClear' => true
],
]);
In this example as you can see, the filename with the image of the state has the same name of the state.id
src = '$url' + state.id.toLowerCase() + '.png'
and it's simple to use.
But my problem is that the filename for each state is different and is stored in my db. For example i have:
//Active Record
$state->id //my state id
$state->img // the name of the image i want
How can i pass the right image name for each element of the list to the script?
Thank's for any help.

Related

How can I valid random names fields in Yii?

I have a lot of fields generated from loops. I would like to validate them through validation rules (integer). I don't know how to throw so many fields with random names into the model to the rules () function. How can I validate fields without a model?
View:
<?= Html::input('number', 'file[' . $indexRow . ']' . '[' . $indexCell . ']', $cell, $options = ['class' => 'form-control', 'filter' => 'intval', 'integer']) ?>
Controller:
` public function actionEdit($fileName)
{
$siteHelper = new SiteHelper();
$editForm = new EditForm();
$preparedRows = $siteHelper->prepareRows($fileName);
$preparedHTML = '';
if (Yii::$app->request->isPost) {
$post = Yii::$app->request->post();
if (isset($post['file'])) {
$dataFile = $post['file'];
$preparedRows = $siteHelper->updateExcelFile($fileName, $dataFile);
Yii::$app->session->setFlash('success', 'Plik zostaƂ zaktualizowany!');
} else if (isset($post['EditForm'])) {
$events = $post['EditForm']['events'];
$preparedHTML = $siteHelper->prepareHTML($events, $preparedRows, $fileName);
Yii::$app->session->setFlash('success', 'Wygenerowano plik PDF!');
}
}
$viewParameters = [
'rows' => $preparedRows,
'editForm' => $editForm,
'scoreHTML' => $preparedHTML,
'downloadLink' => Url::toRoute(['site/download', 'fileName' => $fileName])
];
return $this->render('edit', $viewParameters);
}`
Model:
`
class EditForm extends Model
{
public $events;
public function rules()
{
return [
[['events'], 'required'],
['events', 'integer'],
];
}
}`
When you have an array you can use each validator:
https://www.yiiframework.com/doc/api/2.0/yii-validators-eachvalidator
The validation function should be:
public function rules()
{
return [
[['events'], 'each', 'rule' => ['required']],
[['events'], 'each', 'rule' => ['integer']],
];
}
You may need to avoid multidemnsional array in html and render the field like this:
<?= Html::input('number', 'file[' . $indexRow . '-' . $indexCell . ']', $cell, $options = ['class' => 'form-control', 'filter' => 'intval', 'integer']) ?>
later you can "explode" the row cell index (isn't it supposed to be col?) to identify the row and the column.
$rowCellIndecies = explode('-', $rowCellIndex);
explode function: https://www.php.net/manual/en/function.explode.php

how to pass a variable from javascript to yii2 function

I have a dropdown list of company names. When I select companies from it and click on 'get info' button I should get rows with selected company id.
View
$typeahead = Select2::widget([
'id' => 'front_companies_select',
'name' => 'state_10',
'data' => $companyNameList,
'options' => [
'placeholder' => 'Select ...',
'multiple' => true
],
]);
<?= Html::SubmitButton( 'Get info', [ 'class' => 'btn btn-success' , 'id' =>'getinfo']) ?>
Javascript file
$("#getinfo").click(function(){
var id = $("#front_companies_select option:selected").val();
console.log(id); //want to pass this id in controller as ap parameter actionInfo($id)
});
Controller
public function actionVerify($id) // want to get id here
{
$model = $this->findModel($id);
$connection = Yii::$app->db;
$model = $connection->createCommand("SELECT * FROM companies where id=$id");
$users = $model->queryOne();
return $this->redirect(['companies/index']); //want to show rows in this gridview
}
Can any one fix it? I am stuck with it..
Asuming that you're in a controller without any URL params you can do something like this:
$("#getinfo").click(function(){
var id = $("#front_companies_select option:selected").val();
window.location.href = 'verify?id=' + id;
});
Otherwise you have to build the URL and passing it to window.location

Yii2 gridview: sending attribute value to filter

I want that a text in gridview is link that sends this text to filter of the same column.
so far I'm doing this way:
'columns'=>[
...
[
'attribute'=>'colname',
'value'=>function($data){
return Html::a($data->colname,Yii::$app->request->url.'&MymodelSearch[colname]='.$data->colname);
},
],
...
]
but it's ugly and doesn't always work
'columns' => [
// ...
[
'attribute' => 'colname',
'format' => 'raw',
'value' => function ($data, $key, $index, $column) {
if ($data->colname)
return
"<span onclick=\""
. (new \yii\web\JsExpression("setFilterColname('"
. Html::encode($data->colname) . "');"))
. "\">"
. \yii\helpers\Html::encode($data->colname)
. "</span>";
}
// ...
]
Add this at bottom of view file
<?php
$this->registerJs("
function setFilterColname(filter_value) {
$('input[name=\"MymodelSearch[colname]\"]').val(filter_value);
$('#w0').yiiGridView('applyFilter');
// #w0 is ID of grid to be submited to filter
}
", $this::POS_END, 'set-filter-colname');
?>

Yii2 - How can I add a search in Dropdownlist Widget

Good day!
How can I add a search on a dropdownlist?
I want a dropdown search like the Select2 widget.
Dropdownlist:
<?= $form->field($modelRis, "[{$i}]lib_item_item_id")->dropDownList(
ArrayHelper::map(LibItem::find()->orderBy('item_description')->all(), 'item_id', 'item_description'),
[
'prompt'=>'Select Item',
'onchange'=>'
var tmp = $(this).attr("id");
var thisId = tmp.split("-");
var tmp2 = "";
var tmp3 = "";
var sample_id = $(this).val();
$.post( "'.Yii::$app->urlManager->createUrl(['online-requisition/listsofunit?item_id=']).'"+$(this).val(),
function( data ) {
$( "#risrequesteditem-"+thisId[1]+"-lib_unit_id").html( data );
$( "#loop-"+thisId[1]+"-lib_item_item_id").val( sample_id );
tmp2 = data;
tmp3 = tmp2.split("=====");
$( "#loop-"+thisId[1]+"-available_stock").val( tmp3[1] );
});
',
'pluginOptions' => [
'allowClear' => true
],
])->label('Item',['class'=>'label-class']); ?>
I can't use the select2 widget because the 'onchange' or this line of code is not supported:
'onchange'=>'
var tmp = $(this).attr("id");
var thisId = tmp.split("-");
var tmp2 = "";
var tmp3 = "";
var sample_id = $(this).val();
$.post( "'.Yii::$app->urlManager->createUrl(['online-requisition/listsofunit?item_id=']).'"+$(this).val(),
function( data ) {
$( "#risrequesteditem-"+thisId[1]+"-lib_unit_id").html( data );
$( "#loop-"+thisId[1]+"-lib_item_item_id").val( sample_id );
tmp2 = data;
tmp3 = tmp2.split("=====");
$( "#loop-"+thisId[1]+"-available_stock").val( tmp3[1] );
});
',
Thanks...
Updates:
If i'm going to used the select2 widget in order to have a search function during the selection of items there will be a problem.
In the :
first selection its working:
And the onchange function has been working also. And automatically fill all the data in form field (Item no, Unit and StockAvailable) after the selection of item.
1st Selection
second selection is not working:
But I can select an item. Only the jquery function onchange is the problem...
2nd Selection
Thanks...
As suggested by Ajith above, you should use the Yii2 Select2 Widget from http://demos.krajee.com/widget-details/select2
If you go through the details you will find that the above widget does allow you to add event handlers by using the pluginEvents parameter settings of the widget.
pluginEvents = [
"change" => "function() { log('change'); }",
"select2:opening" => "function() { log('select2:opening'); }",
"select2:open" => "function() { log('open'); }",
"select2:closing" => "function() { log('close'); }",
"select2:close" => "function() { log('close'); }",
"select2:selecting" => "function() { log('selecting'); }",
"select2:select" => "function() { log('select'); }",
"select2:unselecting" => "function() { log('unselecting'); }",
"select2:unselect" => "function() { log('unselect'); }"
];
Although it's not possible to provide proper code without knowing the context etc of your code snippet, however it can be re-written using Yii2 Select2 widget as below (the code below is untested, but should give you an idea of the structure):
use kartik\widgets\Select2;
$data = ArrayHelper::map(LibItem::find()->orderBy('item_description')->all(), 'item_id', 'item_description');
// Usage with ActiveForm and model
echo $form->field($modelRis, "[{$i}]lib_item_item_id")->widget(Select2::classname(), [
'data' => $data,
'options' => ['placeholder' => 'Select Item'],
'pluginOptions' => [
'allowClear' => true
],
'pluginEvents' => [
'select2:select' => 'function(e) {
var tmp = e.target.id;
var thisId = tmp.split("-");
var tmp2 = "";
var tmp3 = "";
var sample_id = e.target.value;
$.post( "'.Yii::$app->urlManager->createUrl(['online-requisition/listsofunit?item_id=']).'"+$(this).val(),
function( data ) {
$( "#risrequesteditem-"+thisId[1]+"-lib_unit_id").html( data );
$( "#loop-"+thisId[1]+"-lib_item_item_id").val( sample_id );
tmp2 = data;
tmp3 = tmp2.split("=====");
$( "#loop-"+thisId[1]+"-available_stock").val( tmp3[1] );
});
}
'
],
]);
Please note I have used select2:select as the event handler.
I had to provide this as a separate answer because I don't have enough reputation to add a comment.
You can use yii2 select2 widget for this purpose. There is good documentation with demos available at
http://demos.krajee.com/widget-details/select2
An example usage with active form is given below
// Usage with ActiveForm and model
echo $form->field($model, 'state_1')->widget(Select2::classname(), [
'data' => $data,// the select option data items.The array keys are option values, and the array values are the corresponding option labels
'options' => ['placeholder' => 'Select a state ...'],
'pluginOptions' => [
'allowClear' => true
],
'pluginEvents' => [
'change' => 'function(){// write your on change code here}'
]
]);

How to "force" a krajee bootstrap daterangepicker to be readonly?

I'm using krajee DatePicker.
use yii\helpers\Html;
use yii\widgets\DetailView;
use yii\web\View;
use yii\data\ActiveDataProvider;
use kartik\widgets\DatePicker;
use yii\web\JsExpression;
echo DatePicker::widget([
'name' => 'dp',
'id' => 'dp',
'type' => DatePicker::TYPE_INLINE,
'value' => '',
'pluginOptions' => [
'startDate' => $model->fecha_inicio,
'format' => 'yyyy-mm-dd',
'beforeShowDay' => new \yii\web\JsExpression("function(date) {
startDate = new Date('".$model->fecha_inicio."');
endDate = new Date('".$model->fecha_fin."');
between=startDate<=date && endDate>=date;
console.log(date+' '+ (between));
dateFormat = date.getUTCFullYear() + '-' + ('0'+(date.getUTCMonth()+1)).slice(-2) + '-' + ('0'+date.getUTCDate()).slice(-2);
if (dateFormat == '".$model->fecha_inicio."') {
return {classes: 'start-date', tooltip: 'Title'};
}
if (dateFormat == '".$model->fecha_fin."') {
return {classes: 'end-date', tooltip: 'Title'};
}
if (between) {
return {classes: 'in-range available'}; //create a custom class in css with back color you want
}
return false;
}"),
],
'options' => [
// you can hide the input by setting the following
'class' => 'hide'
]
]);
Is there any way to render the DateRangePicker without it being able to recieve user input? (eg. no hover, no date selection). I want to render it on a webpage just to inform the user of a range, but the fact that the user can interact with it feels awkward in this scenario.
You can try to add "readonly" to the options. Just like this:
'options' => [
// you can hide the input by setting the following
'class' => 'hide',
'readonly' => 'readonly'
]
Try to use in your options array attribute disabled. SO it would be
'options' => [
'disabled' => 'true',
'class' => 'hide'
]
Well, this helped me do the trick, based on this answer.
Basically, I ended up using a wrapping div with the style:
<div style="pointer-events:none;"> ... </div>
This solved it easily and directly, and it seems to have decent cross-browser support.
<?php
echo '<div class="well well-sm" style="background-color: #fff; width:245px; pointer-events:none;">';
$date = new \DateTime($model->fecha_inicio);
$days = Proceso::calcularDias ($model->fecha_inicio,$model->fecha_fin);
echo DatePicker::widget([
'name' => 'dp',
'id' => 'dp',
'type' => DatePicker::TYPE_INLINE,
'value' => '',
'pluginOptions' => [
'defaultViewDate' => ([
'year'=>(int)$date->format('Y'),
'month'=>$date->format('m')-1,
'day'=>(int)$date->format('d')
]),
'format' => 'yyyy-mm-dd',
'beforeShowDay' => new JsExpression("function(date) {
startDate = new Date('".$model->fecha_inicio."');
endDate = new Date('".$model->fecha_fin."');
between=startDate<=date && endDate>=date;
dateFormat = date.getUTCFullYear() + '-' + ('0'+(date.getUTCMonth()+1)).slice(-2) + '-' + ('0'+date.getUTCDate()).slice(-2);
if (dateFormat == '".$model->fecha_inicio."') {
return {classes: 'start-date', tooltip: 'Title'};
}
if (dateFormat == '".$model->fecha_fin."') {
return {classes: 'end-date', tooltip: 'Title'};
}
if (between) {
return {classes: 'in-range available'}; //create a custom class in css with back color you want
}
return false;
}"),
],
'pluginEvents'=>[
],
'options' => [
'disabled' => 'true',
// you can hide the input by setting the following
'class' => 'hide'
]
]);
echo '</div>';
?>