Yii2: Config global template for all forms fields - php

I have this:
<?php
use app\models\Location;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\helpers\ArrayHelper;
use app\models\Role;
?>
<?php $form = ActiveForm::begin(); ?>
<div class="row">
<div class="col-sm-6">
<?= $form->field($model, 'roleId', Yii::$app->formtemplate->fieldTemplate())->dropDownList(ArrayHelper::map(Role::find()->all(), 'id', 'name'), array('prompt' => '-- Select a role --', 'class' => 'form-control select2')); ?>
</div>
<div class="col-sm-6">
<?= $form->field($model, 'published')->checkbox(['label' => ''], true)->label($model->getAttributeLabel('published'), ['class' => 'form-label semibold']); ?>
</div>
</div>
I think this is unefficient since I have to add the template to each field (I know I can add it per form, but checkbox has a different one, any ideas how to set it globally, for all forms? not only for one form?
So far what I have done is to create a component called FormTemplate to avoid writing the template directly in the view, which is good, but I want to set it globally.
<?php
namespace app\components;
use Yii;
use yii\base\Component;
class FormTemplate extends Component {
public function fieldTemplate($option = []) {
$template = [
'template' => '',
'labelOptions' => [ 'class' => 'form-label semibold']
];
$icon = '';
$position = 'right';
if(!empty($option['position'])) {
$position = $option['position'];
}
if(!empty($option['icon'])) {
$icon = $this->_setFieldIcon($option['icon']);
}
$template['template'] = '<div class="form-group">{label}<div class="form-control-wrapper form-control-icon-'.$position.'">{input}'.$icon.'<div class="error">{error}{hint}</div></div></div>';
return $template;
}
private function _setFieldIcon($option) {
switch($option) {
case 'text':
$icon = '<i class="fa fa-text-width"></i>';
break;
case 'password':
$icon = '<i class="fa fa-key" aria-hidden="true"></i>';
break;
default:
$icon = '';
break;
}
return $icon;
}
}
Any ideas?
UPDATE
I have noticed ActiveField is a component, so maybe I could do it on global config? someone has done something like that?
$config = [
'id' => 'basic',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'components' => [
'activeField' => [
'template' => '...'
]

If you want to customize ActiveField objects for all your application, you should use Yii2 dependency injection container, e.g. :
\Yii::$container->set('yii\bootstrap\ActiveField', [
'template' => '...',
]);
Or for ActiveForm :
\Yii::$container->set('yii\bootstrap\ActiveForm', [
'inputTemplate' => '...',
]);
Read more about practical usage of DI container.

You can create
your ActiveField class as :-
<?php
namespace frontend\widgets;
use yii\helpers\ArrayHelper;
use yii\widgets\ActiveField;
class MyActiveField extends ActiveField
{
public $labelOptions = [ 'class' => 'form-label semibold'];
public function init()
{
$position = ArrayHelper::remove($this->options, 'right');
$icon = $this->_setFieldIcon($this->options);
$this->template ='
<div class="form-group">{label}
<div class="form-control-wrapper form-control-icon-'.
$position.'">
{input}'.$icon.
'<div class="error">{error}{hint}
</div>
</div>
</div>';
parent::init();
}
/**
* #param $option array
* #return string HTML
*/
private function _setFieldIcon($option) {
$icon ='';
switch(ArrayHelper::getValue($option ,'icon' ,'')) {
case 'text':
$icon = '<i class="fa fa-text-width"></i>';
break;
case 'password':
$icon = '<i class="fa fa-key" aria-hidden="true"></i>';
break;
}
return $icon;
}
}
And In ActiveForm use your class as : -
<?php $form = ActiveForm::begin([
//change this with your active field class
'fieldClass' => 'frontend\widgets\MyActiveField'
]); ?>
<div class="row">
<div class="col-sm-6">
<?= $form->field($model, 'roleId',[
'options' => ['icon' => '' ,'position' => '']]
)->dropDownList(ArrayHelper::map(Role::find()->all(), 'id', 'name'), [
'prompt' => '-- Select a role --', 'class' => 'form-control select2'
]); ?>
</div>
<div class="col-sm-6">
<?= $form->field($model, 'published' ,['icon' => '' ,'position' => ''])->checkbox(['label' => ''], true)
->label($model->getAttributeLabel('published'), ['class' => 'form-label semibold']); ?>
</div>
</div>
<?php ActiveForm::end(); ?>

Related

Yii2 Dynamic Form Error on Create - The 'model' property must be set and must extend from '\yii\base\Model'

In Yii2, I have been trying to create a dynamic form using the below tutorials.
Yii2-dynamicForm - GitHub and Youtube Tutorial.
I followed the same step as mentioned in tutorials, unfortunately I am held up with an error(screenshot attached)
And I am not able to resolve this error, can any one help me to find what I am missing.
For the reference I am attaching my Models here, rest the controllers and views are same as the tutorials.
Request Model
<?php
namespace app\models;
use Yii;
class Request extends \yii\db\ActiveRecord
{
public static function tableName()
{
return 'request';
}
public function rules()
{
return [
[['req_date', 'req_on', 'req_updated_on'], 'safe'],
[['req_job', 'req_type', 'material_type', 'req_status'], 'required'],
[['req_by'], 'integer'],
[['req_status'], 'string'],
[['req_job', 'req_type'], 'string', 'max' => 100],
[['material_type'], 'string', 'max' => 150],
];
}
public function attributeLabels()
{
return [
'req_id' => 'Req ID',
'req_date' => 'Req Date',
'req_job' => 'Job No',
'req_type' => 'Type of Request',
'req_on' => 'Required On',
'material_type' => 'Material Type',
'req_by' => 'Req By',
'req_updated_on' => 'Req Updated On',
'req_status' => 'Request Status',
];
}
}
RequestItems Model
<?php
namespace app\models;
use Yii;
use yii\base\Model;
/**
* This is the model class for table "request_items".
*
* #property int $req_item_id
* #property int $req_id
* #property string $item_name
* #property string $item_qty
* #property string $item_unit
*/
class RequestItems extends \yii\db\ActiveRecord
{
/**
* {#inheritdoc}
*/
public static function tableName()
{
return 'request_items';
}
/**
* {#inheritdoc}
*/
public function rules()
{
return [
[['req_id', 'item_name', 'item_qty', 'item_unit'], 'required'],
[['req_id'], 'integer'],
[['item_name'], 'string', 'max' => 100],
[['item_qty', 'item_unit'], 'string', 'max' => 25],
];
}
/**
* {#inheritdoc}
*/
public function attributeLabels()
{
return [
'req_item_id' => 'Req Item ID',
'req_id' => 'Req ID',
'item_name' => 'Item Name',
'item_qty' => 'Item Qty',
'item_unit' => 'Item Unit',
];
}
}
_form.php
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use wbraganca\dynamicform\DynamicFormWidget;
use kartik\select2\Select2;
use kartik\checkbox\CheckboxX;
/* #var $this yii\web\View */
/* #var $model app\models\Request */
/* #var $form yii\widgets\ActiveForm */
?>
<div class="request-form">
<?php $form = ActiveForm::begin(['id' => 'dynamic-form']); ?>
<?= $form->field($model, 'req_date')->hiddenInput()->label(false) ?>
<div class="row">
<div class="col-sm-6">
<?php
$data = ['1001' => '1001/Sample Job 1', '1002' => '1002/Sample Job 2', '1003' => '1003/Sample Job 3'];
echo $form->field($model, 'req_job')->widget(Select2::classname(), [
'data' => $data,
'class'=>'form-control',
'options' => ['placeholder' => 'Select a state ...'],
'pluginOptions' => [
'allowClear' => true
],
]); ?>
</div>
<div class="col-sm-6">
<?= $form->field($model, 'req_type')->radioList(array('Urgent'=>'Urgent','Normal'=>'Normal')); ?>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<?= $form->field($model, 'req_on')->input('date') ?>
</div>
<div class="col-sm-6">
<?= $form->field($model, 'material_type')->radioList(array('Civil'=>'Civil','Mechanical'=>'Mechanical', 'Manpower'=>'Manpower')); ?>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<?= $form->field($model, 'req_by')->hiddenInput()->label(false) ?>
</div>
<div class="col-sm-6">
<?= $form->field($model, 'req_updated_on')->hiddenInput()->label(false) ?>
</div>
</div>
<!-- code for dynamic form -->
<div class="panel panel-default">
<div class="panel-heading"><h4><i class="glyphicon glyphicon-envelope"></i> Request Items</h4></div>
<div class="panel-body">
<?php DynamicFormWidget::begin([
'widgetContainer' => 'dynamicform_wrapper', // required: only alphanumeric characters plus "_" [A-Za-z0-9_]
'widgetBody' => '.container-items', // required: css class selector
'widgetItem' => '.item', // required: css class
'limit' => 4, // the maximum times, an element can be cloned (default 999)
'min' => 1, // 0 or 1 (default 1)
'insertButton' => '.add-item', // css class
'deleteButton' => '.remove-item', // css class
'model' => $modelsAddress,
'formId' => 'dynamic-form',
'formFields' => [
'item_name',
'item_qty',
'item_unit',
],
]); ?>
<div class="container-items"><!-- widgetContainer -->
<?php foreach ($modelsAddress as $i => $modelAddress): ?>
<div class="item panel panel-default"><!-- widgetBody -->
<div class="panel-heading">
<h3 class="panel-title pull-left">Requested Items</h3>
<div class="pull-right">
<button type="button" class="add-item btn btn-success btn-xs"><i class="glyphicon glyphicon-plus"></i></button>
<button type="button" class="remove-item btn btn-danger btn-xs"><i class="glyphicon glyphicon-minus"></i></button>
</div>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<?php
// necessary for update action.
if (! $modelAddress->isNewRecord) {
echo Html::activeHiddenInput($modelAddress, "[{$i}]id");
}
?>
<?= $form->field($modelAddress, "[{$i}]item_name")->textInput(['maxlength' => true]) ?>
<div class="row">
<div class="col-sm-6">
<?= $form->field($modelAddress, "[{$i}]item_qty")->textInput(['maxlength' => true]) ?>
</div>
<div class="col-sm-6">
<?= $form->field($modelAddress, "[{$i}]item_unit")->textInput(['maxlength' => true]) ?>
</div>
</div><!-- .row -->
</div>
</div>
<?php endforeach; ?>
</div>
<?php DynamicFormWidget::end(); ?>
</div>
</div>
<?= $form->field($requestModel, 'req_status')->dropDownList(['Requested' => 'Requested', 'Approved' => 'Approved', 'Rejected' => 'Rejected', 'Hold' => 'Hold',], ['prompt' => '']) ?>
<div class="form-group">
<?= Html::submitButton('Save', ['class' => 'btn btn-success']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
You need to change the
'model'=>$modelsAddress
to
'model'=>$modelsAddress[0]
As stated in the basic example, its an array of models and the way you passing, it will be detected as array rather than a model.

YII2 Validation for several forms in one action

Hellow i'm making several forms and their validation on YII with ajax and i have some problems
Here the view code:
<?
$form = ActiveForm::begin([
'id' => 'test-form',
'options' => ['class' => 'form-horizontal'],
]) ?>
<?= $form->field($model, 'name')->textInput(['placeholder' => "Имя"])->label('Имя'); ?>
<?= $form->field($model, 'lastname')->textInput(['placeholder' => "Фамилия"])->label('Фамилия'); ?>
<?= $form->field($model, 'country')->textInput(['placeholder' => "Страна"])->label('Страна'); ?>
<?= $form->field($model, 'pindex')->textInput(['placeholder' => "Индекс"])->label('Индекс'); ?>
<?= $form->field($model, 'card') ->textInput(['placeholder' => "Ваш номер карты xxxx xxxx xxxx xxxx"])->label('Номер карты');?>
<?= $form->field($model, 'form_name')->hiddenInput(['value' => 'Form']) ?>
<div class="form-group">
<div class="">
<?= Html::submitButton('Отправить', ['class' => 'btn btn-primary']) ?>
</div>
</div>
<?php ActiveForm::end() ?>
<?
$form = ActiveForm::begin([
'id' => 'mobile-form',
'options' => ['class' => 'form-horizontal'],
]) ?>
<?= $form->field($model2, 'name')->textInput(['placeholder' => "Имя"])->label('Имя'); ?>
<?= $form->field($model2, 'lastname')->textInput(['placeholder' => "Фамилия"])->label('Фамилия'); ?>
<?= $form->field($model2, 'country')->textInput(['placeholder' => "Страна"])->label('Страна'); ?>
<?= $form->field($model2, 'pindex')->textInput(['placeholder' => "Индекс"])->label('Индекс'); ?>
<?= $form->field($model2, 'phone') ->textInput(['placeholder' => "Ваш телефон"])->label('Ваш телефон');?>
<?= $form->field($model2, 'form_name')->hiddenInput(['value' => 'Mobile']) ?>
<div class="form-group">
<div class="">
<?= Html::submitButton('Отправить', ['class' => 'btn btn-primary']) ?>
</div>
</div>
<?php ActiveForm::end() ?>
Then im sending data with ajax to controller, code:
namespace app\controllers;
use Yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\web\Response;
use yii\filters\VerbFilter;
use app\models\MainForm;
use app\models\EntryForm;
use app\models\EntryMobile;
class SiteController extends Controller
{
/**
* {#inheritdoc}
*/
public function actionEntry(){
$model = new EntryForm;
$model2 = new EntryMobile;
if(Yii::$app->request->isAjax) {
$model->load(Yii::$app->request->post());
$model2->load(Yii::$app->request->post());
if($model->validate() || $model2->validate()){
$json['ok'] = "";
}else{
$json['error'] = " ";
}
Yii::$app->response->format = Response::FORMAT_JSON;
return $json;
} else {
return $this->render('entry', ['model' => $model,'model2' => $model2]);
}
}
In models i have MainForm , and EntryForm and EntryMobile that extends MainForm with their own rules.
Here is a question:
How to make $model->validation() and $model2->validation() in one method? Or how to make the controller method width on model for two forms. Scenarios doesnt work cause they made me make the same. Two object and etc. Please help
You can use bitwise and for testing both models validations. Like:
$model->validate() & $model2->validate()
Which will then proceed only if both conditions are true but will test both of them anyway (which should throw the validation errors you expect to see).

yii2 dynamic form for single model

I am working yii2 advanced of dynamic form using webraganca for a single model. but i am unable to precede further due to the following error. Any help is appreciated to much.
my code is as follows:
controller.php
namespace frontend\controllers;
use Yii;
use frontend\models\Ireturn;
use frontend\models\IreturnSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\helpers\Json;
use frontend\models\Model;
/**
* IreturnController implements the CRUD actions for Ireturn model.
*/
class IreturnController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* Lists all Ireturn models.
* #return mixed
*/
public function actionIndex()
{
$searchModel = new IreturnSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
if(Yii::$app->request->post('hasEditable'))
{
$ireturnId = Yii::$app->request->post('editableKey');
$ireturn = Ireturn::findOne($ireturnId);
$out = Json::encode(['output'=>'','message'=>'']);
$post = [];
$posted = current($_POST['Ireturns']);
$post['Ireturns']= $posted;
if($ireturn->load($post))
{
$ireturn->save();
$output ='my values';
$out = Json::encode(['output'=>$output,'message'=>'']);
}
return;
}
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single Ireturn model.
* #param integer $id
* #return mixed
*/
public function actionView($id)
{
$model = $this->findModel($id);
$modelsItem = $model->ireturn;
return $this->render('view', [
'model' => $this->findModel($id),
'modelsItem'=>$modelsItem,
]);
}
/**
* Creates a new Ireturn model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
$model = new Ireturn();
$modelsAddress = [new Ireturn];
if ($model->load(Yii::$app->request->post())) {
$modelsAddress = Model::createMultiple(Ireturn::classname());
Model::loadMultiple($modelsAddress, Yii::$app->request->post());
// validate all models
$valid = $model->validate();
$valid = Model::validateMultiple($modelsAddress) && $valid;
if ($valid) {
$transaction = \Yii::$app->db->beginTransaction();
try {
if ($flag = $model->save(false)) {
foreach ($modelsAddress as $modelAddress) {
$modelAddress->id = $model->id;
if (! ($flag = $modelAddress->save(false))) {
$transaction->rollBack();
break;
}
}
}
if ($flag) {
$transaction->commit();
return $this->redirect(['view', 'id' => $model->id]);
}
} catch (Exception $e) {
$transaction->rollBack();
}
}
}
return $this->render('create', [
'model' => $model,
'modelsAddress' => (empty($modelsAddress)) ? [new Ireturn] : $modelsAddress
]);
/*$model = new Ireturn();
$modelsAddress = [new Ireturn];
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
'modelsAddress' => (empty($modelsAddress)) ? [new Ireturn] : $modelsAddress
]);
}*/
}
/**
* Updates an existing Ireturn model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param integer $id
* #return mixed
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
/**
* Deletes an existing Ireturn model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* #param integer $id
* #return mixed
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
/**
* Finds the Ireturn model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param integer $id
* #return Ireturn the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Ireturn::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
/*public function actionEditableDemo() {
$model = new Ireturn(); // your model can be loaded here
// Check if there is an Editable ajax request
if (isset($_POST['hasEditable'])) {
// use Yii's response format to encode output as JSON
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
// read your posted model attributes
if ($model->load($_POST[])) {
// read or convert your posted information
$value = $model->functional;
// return JSON encoded output in the below format
return ['output'=>$value, 'message'=>''];
// alternatively you can return a validation error
// return ['output'=>'', 'message'=>'Validation error'];
}
// else if nothing to do always return an empty JSON encoded output
else {
return ['output'=>'', 'message'=>''];
}
}
// Else return to rendering a normal view
return $this->render('view', ['model'=>$model]);
}*/
}
_form.php
use yii\helpers\Html;
use yii\helpers\ArrayHelper;
use yii\widgets\ActiveForm;
use backend\models\Items;
use backend\models\Departments;
use kartik\select2\Select2;
use dosamigos\datepicker\DatePicker;
use yii\web\View;
use wbraganca\dynamicform\DynamicFormWidget;
use common\models\User;
/* #var $this yii\web\View */
/* #var $model backend\models\Ireturn */
/* #var $form yii\widgets\ActiveForm */
?>
<div class="ireturn-form">
<?php $form = ActiveForm::begin(['id' => 'dynamic-form','options'=>['class'=>'well'],]); ?>
<div class="panel panel-default" >
<!--<div class="panel-heading">
<h4><i class="glyphicon glyphicon-envelope"></i> Items
</h4>
</div>-->
<div class="panel-body">
<div class="row">
<div class="col-xs-4">
<?= $form->field($model, 'dept_id')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Departments::find()->all(),'id','dept_name'),
'language' => 'en',
'options' => ['placeholder' => 'Select departments ...'],
'pluginOptions' => [
'allowClear' => true
],
]);
?>
</div>
<div class="col-xs-3">
<?= $form->field($model, 'voucher_no')->textInput(['maxlength' => true])?>
</div>
</div>
<!-- <div class="panel panel-default">-->
<!-- <div class="panel-heading"><h4><i class="glyphicon glyphicon-envelope"></i> Items</h4></div>-->
<!-- <div class="panel-body">-->
<?php DynamicFormWidget::begin([
'widgetContainer' => 'dynamicform_wrapper', // required: only alphanumeric characters plus "_" [A-Za-z0-9_]
'widgetBody' => '.container-items', // required: css class selector
'widgetItem' => '.item', // required: css class
'limit' => 4, // the maximum times, an element can be cloned (default 999)
'min' => 1, // 0 or 1 (default 1)
'insertButton' => '.add-item', // css class
'deleteButton' => '.remove-item', // css class
'model' => $modelsAddress[0],
'formId' => 'dynamic-form',
'formFields' => [
'items_id',
'unit',
'amount',
'functional',
],
]); ?>
<div class="container-items"><!-- widgetContainer -->
<div class="item panel panel-default"><!-- widgetBody -->
<div class="panel-heading">
<h3 class="panel-title pull-left"> <i class="glyphicon glyphicon-envelope"></i>Item</h3>
<div class="pull-right">
<button type="button" class="add-item btn btn-success btn-xs"><i class="glyphicon glyphicon-plus"></i></button>
<button type="button" class="remove-item btn btn-danger btn-xs"><i class="glyphicon glyphicon-minus"></i></button>
</div>
<div class="clearfix"></div>
</div>
<?php foreach ($modelsAddress as $i => $modelAddress): ?>
<div class="panel-body">
<?php
// necessary for update action.
if (! $modelAddress->isNewRecord) {
echo Html::activeHiddenInput($model, "[{$i}]id");
}
?>
<div class="row">
<div class="col-sm-3">
<?= $form->field($modelAddress, "[{$i}]items_id")->dropDownList(
ArrayHelper::map(Items::find()->all(),'id','item_name'),
['prompt'=>'select items']) ?>
</div>
<div class="col-sm-3">
<?= $form->field($modelAddress, "[{$i}]unit")->textInput(['maxlength' => true]) ?>
</div>
<div class="col-sm-3">
<?= $form->field($modelAddress, "[{$i}]amount")->textInput(['maxlength' => true]) ?>
</div>
<div class="col-sm-3">
<?= $form->field($modelAddress, "[{$i}]functional")->textInput(['maxlength' => true]) ?>
</div>
</div><!-- .row -->
</div>
<?php endforeach; ?>
</div>
</div>
<?php DynamicFormWidget::end(); ?>
<!-- </div>-->
<!-- </div>-->
<div class="padding-v-md">
<div class="line line-dashed"></div>
</div>
<div class="row">
<div class="col-xs-4">
<?= $form->field($model,'user_id')->dropDownList(
ArrayHelper::map(User::find()->all(),'id','full_name'),
['prompt'=>'select employees'])
?>
<?= $form->field($model,'head_id')->dropDownList(
ArrayHelper::map(User::find()->all(),'id','full_name'),
['prompt'=>'select dept heads'])
?>
<?= $form->field($model,'man_id')->dropDownList(
ArrayHelper::map(User::find()->all(),'id','full_name'),
['prompt'=>'select stoke managers'])
?>
<?= $form->field($model,'keeper_id')->dropDownList(
ArrayHelper::map(User::find()->all(),'id','full_name'),
['prompt'=>'select stoke keepers'])
?>
</div>
<div class="col-xs-4">
<?=$form->field($model, 'emp_date')->widget(
DatePicker::className(), [
'inline' => false,
'clientOptions' => [
'autoclose' => true,
'format' => 'yyyy-mm-dd'
]
]);?>
<?=$form->field($model, 'head_date')->widget(
DatePicker::className(), [
'inline' => false,
'clientOptions' => [
'autoclose' => true,
'format' => 'yyyy-mm-dd'
]
]);?>
<?=$form->field($model, 'man_date')->widget(
DatePicker::className(), [
'inline' => false,
'clientOptions' => [
'autoclose' => true,
'format' => 'yyyy-mm-dd'
]
]);?>
<?=$form->field($model, 'keeper_date')->widget(
DatePicker::className(), [
'inline' => false,
'clientOptions' => [
'autoclose' => true,
'format' => 'yyyy-mm-dd'
]
]);?>
</div>
</div>
</div>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
</div>
<?php ActiveForm::end(); ?>
</div>
<?php
$script = <<<EOD
$(".dynamicform_wrapper").on("beforeInsert", function(e, item) {
console.log("beforeInsert");
});
$(".dynamicform_wrapper").on("afterInsert", function(e, item) {
console.log("afterInsert");
});
$(".dynamicform_wrapper").on("beforeDelete", function(e, item) {
if (! confirm("Are you sure you want to delete this item?")) {
return false;
}
return true;
});
$(".dynamicform_wrapper").on("afterDelete", function(e) {
console.log("Deleted item!");
});
$(".dynamicform_wrapper").on("limitReached", function(e, item) {
alert("Limit reached");
});
EOD;
$this->registerJs($script, View::POS_END);
?>
it is not clear why you want to save the child item into the same table as the parent items.
please review your code,
$modelAddress->id = $model->id;
you cannot assign the same id to both parent and child if you are saving it in the same table with unique constrain on the id attribute
alternative, u may create a new column [refference_id] to refer to parent id
$modelAddress->refference_id = $model->id;

Handling breadcumbs on ajax yii2

I have a breadcumbs in yii2. The problem is, I am using pjax to handle crud of my table on database.
Let say, this is my code (in index.php in view):
<?php
$this->title = 'Barangs';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="barang-index">
<?php
Pjax::begin([
'timeout' => 5000,
'id' => 'pjax-gridview'
]);
?>
<h1><?= Html::encode($this->title) ?></h1>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<p>
<?= Html::a('Create Barang', ['create'], ['class' => 'btn btn-success']) ?>
</p>
<?=
GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'NO_URUT',
'CONSIGNEE',
'CONTAINER',
'SIZE',
'COIL_NO',
'NET',
'GROSS',
'CONTRACT_NO',
'KET',
'NAMA_FILE',
'TGL_UNSTUFF',
['class' => 'yii\grid\ActionColumn',
'buttons' => [
'view' => function($url, $model) {
$icon = '<span class="glyphicon glyphicon-eye-open"></span>';
return Html::a($icon, $url);
},
'update' => function($url, $model) {
$icon = '<span class="glyphicon glyphicon-pencil"></span>';
return Html::a($icon, $url);
},
'delete' => function($url, $model) {
$icon = '<span class="glyphicon glyphicon-trash"></span>';
return Html::a($icon, $url, [
"class" => 'pjaxDelete'
]);
},
]
],
],
]);
?>
<?php $this->registerJs('
/* fungsi ini akan dijalankan ketika class pjaxDelete di klik */
$(".pjaxDelete").on("click", function (e) {
/* cegah link menjalankan default action */
e.preventDefault();
if(confirm("Are you sure you want to delete this item?")){
/* request actionDelete dengan method post */
$.post($(this).attr("href"), function(data) {
/* reload gridview */
$.pjax.reload("#pjax-gridview",{"timeout":false});
});
}
});
');
?>
<?php Pjax::end(); ?></div>
My question is, without ajax, breadcumbs will be show Home / Barangs / Create Barang. But in ajax, the breadcumbs looked this : Home / Barangs /
I still need the first breadcumbs format.
Please advise.
when use Pjax => page not refresh but url is changed
use this code maybe your problem solving
<?php Pjax::begin(['enablePushState' => false]); $form = ActiveForm::begin(['action' => '', 'options' => ['data-pjax' => '']]); ?>

Yii2: Updating Grid-view using Pjax

Following this Wiki Yii 2.0: Pjax on ActiveForm and GridView - Yii2
I have tried to use my gridview to update on Ajax without page-reload, but couldn't succeed.
code of my _form.php
<?php
$this->registerJs(
'$("document").ready(function(){
$("#new_medicine").on("pjax:end", function() {
$.pjax.reload({container:"#medicine"}); //Reload GridView
});
});'
);
?>
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use kartik\grid\GridView;
//use yii\grid\Gridview;
use yii\data\ActiveDataProvider;
/* #var $this yii\web\View */
/* #var $model app\models\Medicine */
/* #var $form yii\widgets\ActiveForm */
?>
<!-- <div class="row">
<div class="col-lg-6 col-lg-offset-3"> -->
<div class="medicine-form">
<?php yii\widgets\Pjax::begin(['id' => 'new_medicine']) ?>
<?php $form = ActiveForm::begin(['options' => ['data-pjax' => true ]]); ?>
<?= $form->field($model, 'medicine_id')->textInput(['maxlength' => 10]) ?>
<?= $form->field($model, 'medicine_name')->textInput(['maxlength' => 50]) ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
<?= Html::submitButton($model->isNewRecord ? 'Save & New' : '',$option=['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary','name'=>'save_and_new']) ?>
</div>
<?php ActiveForm::end(); ?>
<?php yii\widgets\Pjax::end() ?>
</div>
Code in my controller
public function actionIndex()
{
$model = new Medicine();
if ($model->load(Yii::$app->request->post()) && $model->save())
{
$model = new Medicine(); //reset model
}
$searchModel = new MedicineSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'model' => $model,
]);
}
code in index.php
<?php
use yii\helpers\Html;
use yii\grid\GridView;
/* #var $this yii\web\View */
/* #var $searchModel app\models\MedicineSearch */
/* #var $dataProvider yii\data\ActiveDataProvider */
$this->title = 'Medicines';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="medicine-index">
<h1><?= Html::encode($this->title) ?></h1>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<p>
<?= Html::a('Create Medicine', ['create'], ['class' => 'btn btn-success']) ?>
</p>
<?php \yii\widgets\Pjax::begin(['id' => 'medicine']); ?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
'medicine_id',
'medicine_name',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
<?php \yii\widgets\Pjax::end(); ?>
</div>
I think I have followed the instructions very carefully, but surely I am missing something as the grid-view is not showing the new records added without page-reload.
Any help will be greatly appreciated.
Thanks.
try to explain how to do it as a widget; it's a generic solution, so contact me in case of troubles:
Controller (#your-alias/controllers/yourController):
...
public function actionManage($param=''){
$model = new YourModel();
if (Yii::$app->request->isPjax && $model->load(Yii::$app->request->post()) && $model->save())
{
$model = new YourModel(); //reset model
}
$model->paramId = $param;
$queryParams = Yii::$app->request->getQueryParams();
$queryParams['YourModelSearch']['param'] = $param;
$searchModel = new YourModelSearch();
$dataProvider = $searchModel->search($queryParams);
return $this->renderAjax('#your-alias/widgets/views/index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'model' => $model,
]);
}...
widgets (#your-alias/widgets/) [form, view]:
_form:
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\widgets\Pjax;
/**
* #var yii\web\View $this
* #var yourModule/models/YourModel $model
* #var yii\widgets\ActiveForm $form
*/
?>
<?php
$js = <<<JS
// get the form id and set the event
$('form#{$model->formName()}').on('beforeSubmit', function(e) {
var \$form = $(this);
// do whatever here, see the parameter \$form? is a jQuery Element to your form
console.log(\$form);
console.log("MODEL CODE = " + $("#yourmodel-code").val());
}).on('submit', function(e){
e.preventDefault();
});
JS;
//$this->registerJs($js);
$this->registerJs(
'$("#new-your-model").on("pjax:end", function() {
commonLib.divAction("#div_new_model", "hide"); //hide form
$.pjax.reload({container:"#models"}); //Reload GridView
});', \yii\web\View::POS_READY
);
?>
<div class="model-form">
<?php Pjax::begin(['id' => 'new-model', 'timeout' => false, 'enablePushState' => false]) ?>
<?php $form = ActiveForm::begin([
'id' => $model->formName(),
//'method' => 'post',
'action' => ['/module/controller/manage?param='.$model->code],
'options' => ['data-pjax' => true ],
//'layout' => 'default',
]); ?>
<?= $form->field($model, 'code')->textInput(['maxlength' => 255]) ?>
...
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
<?php yii\widgets\Pjax::end() ?>
</div>
index view (grid view):
use yii\helpers\Html;
use yii\grid\GridView;
use yii\widgets\Pjax;
/**
* #var yii\web\View $this
* #var yii\data\ActiveDataProvider $dataProvider
* #var yourModule\models\search\YourModelSearch $searchModel
*/
?>
<div class="model-index">
<!--h1><!--?= Html::encode($this->title) ?></h1-->
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<p>
<?= Html::button(Yii::t('bp', 'Add ...'), [
'class' => 'btn btn-success',
'onclick'=>'js:commonLib.divAction("#div_new_model", "show")'
])?>
</p>
<div id="div_new_model" style="display:none">
<?= Html::button(Yii::t('common', 'Cancel'), [
'class' => 'btn btn-success',
'onclick'=>'js:commonLib.divAction("#div_new_model", "hide")'
])?>
<!-- Render create form -->
<?= $this->render('_formModel', [
'model' => $model,
]) ?>
</div>
<?php Pjax::begin(['id' => 'models', 'timeout' => false, 'enablePushState' => false]) ?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
...
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
<?php Pjax::end() ?>
</div>
widget call (in view):
echo #your-alias\widgets\YourWidget::widget([
'param' => $model->param,]);
$.pjax.reload('#my-grid-pjax' , {timeout : false});
To update GridView table without page reload using pjax:
use yii\grid\GridView;
use yii\widgets\Pjax;
Pjax::begin(['id' => 'todaysactivity', 'timeout' => false, 'enablePushState' => false])
Use jQuery/JavaScript as follows:
var url = baseurl + '/activity/logging'; // url where the gridview table need to update
$.pjax.reload({container: "#todaysactivity", url: url}); // refresh the grid
I couldn't find a suitable solution to update the grid-view widget using pjax.
I resolved by using a auto-refresh method for the grid-view page. I understand that this is not the best solution and I am still looking for a suitable solution.
The method I have used is like this:
<script>
function autoRefresh()
{
window.location.reload();
}
setInterval('autoRefresh()', 60000); // this will reload page after every 1 minute.
</script>
What you're looking for is
<script type="text/javascript">
$.pjax.defaults.timeout = false;
</script>
The default pjax timeout setting doesn't give the page time to do anything so it reloads.
Reference

Categories