Yii2 - Dropdownlist to load other attributes - yii2

I have this Model Class
public function attributeLabels()
{
return [
'id' => Yii::t('course', 'ID'),
'course_code' => Yii::t('course', 'Course Code'),
'course_type' => Yii::t('course', 'Course Type'),
'course_title' => Yii::t('course', 'Course Title'),
'course_unit' => Yii::t('course', 'Course Unit'),
];
}
On Dropdownlist change, I want to load and display course_code, course_type, course_title, and course_unit. But should only save course_title. The other should only be displayed and not save, except course_title.
Am ableto display only course_title. This is my view for the dropdown list.
<?= $form->field($modelDetail, "course_id")->widget(Select2::classname(), [
'data' => ArrayHelper::map(app\modules\course\models\CourseMaster::find()->where(['is_status'=>0])->all(),'id','course_title'),
'language' => 'en',
'options' => ['placeholder' => '--- Select Course ---',
],
'pluginOptions' => [
'allowClear' => true
],
]); ?>
This is what I have done.
But I want to achieve this.
How do I display other attributes as textInput() or label without saving in database. Thanks
Controller
public function actionCreate()
{
$modelDetail = new CourseMaster();
if (Yii::$app->request->isAjax && $modelDetail->load(Yii::$app->request->post())) {
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return ActiveForm::validate($modelDetail);
}
if ($modelDetail->load(Yii::$app->request->post())) {
$modelDetail->attributes = $_POST['CourseMaster'];
if($modelDetail->save())
return $this->redirect(['index']);
else
return $this->render('create', ['modelDetail' => $modelDetail,]);
} else {
return $this->render('create', [
'modelDetail' => $modelDetail,
]);
}
}

If you want to only display other fields without sending it on form submit, you can mark field as disabled:
<?= $form->field($modelDetail, 'course_code')->textInput([
'disabled' => true,
]) ?>
This will render input which cannot be edited directly and it will not be sent on form submit.

Well You can concat the data in the label of dropdown itself, will be an easier option. Use closure on the third argument in ArrayHelper::map($array, $from, $to, $group = null) as follows.
ArrayHelper::map(
app\modules\course\models\CourseMaster::find()->where(['is_status'=>0])->all(),
'id',
function($model){
return $model['course_title']." - ".$model['course_code'];
}
)

Related

Yii2 - Dropdownlist OnChange to Display Other Model Attribute

I have these Model Classes
Model:Subject
public function attributeLabels()
{
return [
'subject_id' =>Yii::t('app', 'ID'),
'subject_title' => Yii::t('app', 'Subject Title'),
];
}
Model:Grouping
public function attributeLabels()
{
return [
'grouping_id' => Yii::t('app', 'Grouping ID'),
'grouping_name' => Yii::t('app', 'Grouping Name'),
];
}
Model:SubjectGrouping
public function attributeLabels()
{
return [
'subject_grouping_id' => 'Subject Grouping ID',
'subject_grouping_grouping_id' => 'Subject Grouping Grouping ID',
'subject_grouping_subject_id' => 'Subject Grouping Subject ID',
];
}
Model:Exam
public function attributeLabels()
{
return [
'exam_id' =>Yii::t('app', 'ID'),
'exam_name' => Yii::t('app', 'Exam Name'),
'exam_group_id' => Yii::t('app', 'Exam Group'),
];
}
Model:SubjectGrouping has Foreign Keys from Model: Grouping (subject_grouping_grouping_id) and Model:Subject (subject_grouping_subject_id)
In Model:Exam, exam_group_id relates to subject_grouping_grouping_id in Model:SubjectGrouping.
Controller
public function actionCreate()
{
$model = new Exam();
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
if ($model->load(Yii::$app->request->post())) {
$model->attributes = $_POST['Exam'];
$model->save();
return $this->redirect(['index']);
} else {
return $this->render(
'create', [
'model' => $model
]
);
}
}
View
<div class="col-xs-12 col-sm-4 col-lg-4">
<?=$form->field($model, 'exam_name')->textInput(['maxlength' => 50, 'placeholder' => 'Enter Exam Name'])?>
</div>
<div class="col-xs-12 col-sm-4 col-lg-4">
<?=$form->field($model, 'exam_group_id')->widget(
Select2::classname(), [
'data' => ArrayHelper::map(app\models\Grouping::find()->all(), 'grouping_id', 'grouping_name'),
'language' => 'en',
'options' => ['placeholder' => '--- Select Grouping ---'],
'pluginOptions' => [
'allowClear' => true
]
]
);
?>
</div>
From the diagram, how do I achieve these?
when Dropdownlist for exam_group_id is onChange the list of subjects with respect to grouping is displayed using the relationship between Model: SubjectGrouping and Model: Subject.
Others fields such as exam_name (textInput) and exam_group_id (Dropdownlist) should be save into the Model: Exam. But the subject list should not be saved. It is only for display purpose.
How do I achieve these?
I am using kartik\widgets\Select2 for the dropdownlist
I have done similar code by Kartik extension for state and country data.
here is the code for that.
<?php
//in view use this
use kartik\widgets\DateTimePicker; // or kartik\select2\Select2
use kartik\widgets\DepDrop;
use kartik\widgets\Select2;
?>
<?php
echo
$form->field($model, 'country_id')->widget(
Select2::className(),
[
'data' => \yii\helpers\ArrayHelper::map(common\models\Country::find()->all(), 'id', 'name'),
'options' => [
'id' => 'country_id',
'prompt' => Yii::t('aspns', 'Select')
]
]
);
?>
<?php
echo
$form->field($model, 'state_id')->widget(
DepDrop::classname(),
[
'data' => !empty($model->state_id) ? \yii\helpers\ArrayHelper::map(common\models\State::find()->where(['country_id' => $model->country_id])->all(), 'id', 'name') : [],
'options' => ['id' => 'state_id', 'placeholder' => Yii::t('aspns', 'Select')],
'pluginOptions' => [
'depends' => ['country_id'],
'url' => Url::to(['//country/get-states'])
]
]
)->label(Yii::t('aspns', 'State'));
?>
// In Controller section you need to do this
public function actionGetStates() {
$out = [];
if (isset($_POST['depdrop_parents'])) {
$parents = $_POST['depdrop_parents'];
if ($parents != null) {
$country_id = (int)$parents[0];
$out = State::find()->where(['country_id'=>$country_id])->select(['id', 'name'=>'name'])->asArray()->all();
return Json::encode(['output'=>$out, 'selected'=>'']);
}
}
return Json::encode(['output'=>'', 'selected'=>'']);
}
Change the code according to your requirement.
Thanks

YII2 Editable Column does not work after PJAX

A column in gridview having EditableColumn integrated which works fine on each page load, but not after any PJAX call executions like search, pagination change etc.
In View EditableColumn code looks like this :
[
'class' => EditableColumn::class,
'attribute' => 'visit_status',
'url' => ['update'],
'type' => 'select',
'editableOptions' => function ($model) {
return [
'source' => [
'PENDING' => 'PENDING',
'APPROVED' => 'APPROVED',
'REJECTED' => 'REJECTED'
],
'value' => $model->visit_status,
'editable' => true
];
},
],
And Controller Action is like below:
public function actionUpdate()
{
$pk = unserialize(base64_decode(Yii::$app->request->post('pk')));
$model = MyModel::findOne($pk);
if ($model) {
$model->visit_status = Yii::$app->request->post('value');
if ($model->validate(['visit_status'])) {
$model->save(false);
} else {
throw new BadRequestHttpException($model->getFirstError('visit_status'));
}
}
}
If PJAX is disabled then it works fine, but cant compromize PJAX for that

how insert Initial value in yii2 ckeditor

<?=
$form->field($model, 'template')->widget(CKEditor::className(), [
'options' => ['rows' => 100],
'preset' => 'full',
'value'=>'<p>Incercam sa editam</p>',
])->label(true)
?>
This is my code
I need to set initial value in editor
You should assign a value in your field template eg in you controller/create
public function actionCreate()
{
$model = new YourModel();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
$model->template ="your initila value ....... text "
return $this->render('#common/views/antigone-contribuente/create', [
'model' => $model,
]);
}
}
once you have assigne to youe $model->template the value you need yuo should see this in your editor in view

Yii2 Dynamic form update fail on kartik-Select2

I am using wbraganca dynamic form widget. It works fine for the Create action.
Let me thanks for those guys making great tutorial video on youtube!!!
I am working on the Update action now. I work it on a purchase order function.
the controller of update action :
public function actionUpdate($id)
{
$model = $this->findModel($id);
$modelsItem = $model->purchaseitems;
if ($model->load(Yii::$app->request->post()) ) {
$oldIDs = ArrayHelper::map($modelsItem, 'purchaseitem_id', 'purchaseitem_id');
$modelsItem = Model::createMultiple(Purchaseitem::classname(), $modelsItem);
Model::loadMultiple($modelsItem, Yii::$app->request->post());
$deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($modelsItem, 'purchaseitem_id', 'purchaseitem_id')));
$valid = $model->validate();
$valid = Model::validateMultiple($modelsItem) && $valid;
if ($valid) {
$transaction = \Yii::$app->db->beginTransaction();
try {
if ($flag = $model->save(false)) {
if (! empty($deletedIDs)) {
Purchaseitem::deleteAll(['purchaseitem_id' => $deletedIDs]);
}
foreach ($modelsItem as $modelItem) {
$modelItem->purchaseitem_purchaseorder_id = $model->purchaseorder_id;
$modelItem->purchaseitem_description = Inventory::findOne($modelItem->purchaseitem_inventory_id)->inventory_partno;
if (! ($flag = $modelItem->save(false))) {
$transaction->rollBack();
break;
}
}
}
if ($flag) {
$transaction->commit();
return $this->redirect(['view', 'id' => $model->purchaseorder_id]);
}
} catch (Exception $e) {
$transaction->rollBack();
}
}
//return $this->redirect(['view', 'id' => $model->purchaseorder_id]);
} else {
return $this->render('update', [
'model' => $model,
'modelsItem' => (empty($modelsItem)) ? [new Purchaseitem] : $modelsItem
]);
}
}
But I think the problem may happen on the view file, as the Select2 field can show the value, which is the 'id' of the product rather than the product code.
view:
<div class="panel panel-default">
<div class="panel-body">
<?php DynamicFormWidget::begin([
'widgetContainer' => 'dynamicform_wrapper',
'widgetBody' => '.container-items',
'widgetItem' => '.item',
'limit' => 50,
'min' => 1,
'insertButton' => '.add-item',
'deleteButton' => '.remove-item',
'model' => $modelsItem[0],
'formId' => 'dynamic-form',
'formFields' => [
'purchaseitem_inventory_id',
'purchaseitem_qty',
'purchaseitem_cost_usd',
'purchaseitem_deliverydate',
],
]); ?>
<?php foreach ($modelsItem as $i => $modelItem): ?>
<div class="item">
<?php
// necessary for update action.
if (! $modelItem->isNewRecord) {
echo Html::activeHiddenInput($modelItem, "[{$i}]purchaseitem_id");
}
?>
<div class="row">
<?= $form->field($modelItem, "[{$i}]purchaseitem_inventory_id")->widget(
Select2::classname(), [
'pluginOptions' => [
'allowClear' => true,
'minimumInputLength' => 2,
'language' => [
'errorLoading' => new JsExpression("function () { return 'Error on finding results...'; }"),
],
'ajax' => [
'url' => Url::toRoute('inventory/inventorylist'),
'dataType' => 'json',
'data' => new JsExpression('function(params) { return {q:params.term}; }')
],
'escapeMarkup' => new JsExpression('function (markup) { return markup; }'),
'templateResult' => new JsExpression('function(purchaseitem_inventory_id) { return purchaseitem_inventory_id.text; }'),
'templateSelection' => new JsExpression('function (purchaseitem_inventory_id) { return purchaseitem_inventory_id.text; }'),
],
])->label(false) ?>
<?= $form->field($modelItem, "[{$i}]purchaseitem_qty")->textInput(['maxlength' => true])->label(false) ?>
<?= $form->field($modelItem, "[{$i}]purchaseitem_cost_usd")->textInput(['maxlength' => true])->label(false) ?>
<?= $form->field($modelItem, "[{$i}]purchaseitem_deliverydate")->widget(
DatePicker::className(), [
'options' => [
['placeholder' => 'Please enter delivery date'],
],
'removeButton' => false,
'pluginOptions' => [
'autoclose'=>true,
'format' => 'yyyy-mm-dd',
'todayHighlight' => true,
]
]
)->label(false) ?>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
I have a thought that the problem maybe related to that few lines of JsExpression function.
'escapeMarkup' => new JsExpression('function (markup) { return markup; }'),
'templateResult' => new JsExpression('function(purchaseitem_inventory_id) { return purchaseitem_inventory_id.text; }'),
'templateSelection' => new JsExpression('function (purchaseitem_inventory_id) { return purchaseitem_inventory_id.text; }'),
For the Select2 query URL method is here:
public function actionInventorylist($q = null, $id = null) {
Yii::$app->response->format = yii\web\Response::FORMAT_JSON;
$out = ['results' => ['id' => '', 'text' => '']];
if (!is_null($q)) {
$query = new Query;
$query->select('inventory_id AS id, inventory_partno AS text')
->from('inventory')
->where(['like', 'inventory_partno', $q])
->limit(10);
$command = $query->createCommand();
$data = $command->queryAll();
$out['results'] = array_values($data);
}
elseif ($id > 0) {
$out['results'] = ['id' => $id, 'text' => Inventory::find($id)->inventory_partno];
}
return $out;
}
I can load the record, when I click in the update view. Most of the data are feed in right place of the form, except the 'partno' field. I use Select2 to let user select partno by text and store the 'id' in table. It works on the Create view.
but in the update view, it only show the 'id' instead of the 'partno'.
if I make input to the field, I can select 'other' partno only, let me explain here:
if there are 2 code, "ABC" with 'id' is 1, "XYZ" with 'id' 2.
the record original is "ABC", the field show "1".
If I input "XYZ", it will show "XYZ" as normal effect of widget. But, if I change back to "ABC", it will show "1" instead of "ABC".
And the form also cannot submit for update. the button click with no effect.
I am new to Yii2 framework, and quite stuck on this issue, does anyone knows how can I solve this?
THANKS!!!!
I just solve the problem, a few issue happened actually.
To solve the Select2 widget cannot display the partno instead of the ID, I find the partno by the ID and feed it with initValueText in Select2. For my case:
$partno = empty($modelItem->purchaseitem_inventory_id) ? '':Inventory::findOne($modelItem->purchaseitem_inventory_id)->inventory_partno;
$form->field($modelItem, "[{$i}]purchaseitem_inventory_id")->widget(Select2::classname(), ['initValueText' => $partno, ...
About the update POST fail issue, I got error of Getting unknown property: backend\models\Purchaseitem::id, and I found it happened on the Dynamic-form widgets Model.php line 25. That lines is $keys = array_keys(ArrayHelper::map($multipleModels, 'id', 'id'));
If I change the 'id' to my ID field name, i.e 'purchaseitem_id', it will work, but this model will only work for this Id field name afterward. So I get the model's primaryKey and make it work for my other model.
add this line $primaryKey = $model->tableSchema->primaryKey; and modify above line $keys = array_keys(ArrayHelper::map($multipleModels, $primaryKey, $primaryKey));

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),
]);
}
],