I am using krajee yii2 depdrop in my form. I follow the instruction and my data still not show on depdrop.
This is my _form.php code :
<?php echo $form->field($model, 'id_trayek')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Trayek::find()->all(), 'id_trayek', 'nama_trayek'),
'language' => 'en',
'theme' => Select2::THEME_KRAJEE,
'options' => ['id' => 'id_trayek', 'placeholder' => '-- Pilih Trayek --', 'class' => 'form-control'],
]); ?>
<?php
echo $form->field($model, 'no_bus')->widget(DepDrop::classname(), [
'type'=>DepDrop::TYPE_SELECT2,
'options' => ['id'=>'no_bus', 'class'=>'form-control'],
'pluginOptions'=>[
'depends'=>['id_trayek'],
'placeholder' => '-- Pilih Bus --',
'url' => Url::to(['/surat-jalan/bus'])
]
]);
?>
This is my controller for depdrop url :
public function actionBus() {
$out = [];
if (isset($_POST['depdrop_parents'])) {
$id_trayek = end($_POST['depdrop_parents']);
$jenis_bus = Trayek::find()->select('jenis_bus')->andWhere(['id_trayek'=>$id_trayek]);
$list = Bus::find()->andWhere(['jenis_bus'=>$jenis_bus])->asArray()->all();
$selected = null;
if ($id_trayek != null && count($list) > 0) {
$selected = '';
foreach ($list as $i => $bus) {
$out[] = ['no_bus' => $bus['no_bus'], 'no_bus' => $bus['no_bus']];
}
echo Json::encode(['output' => $out, 'selected'=>$selected]);
return;
}
}
echo Json::encode(['output' => '', 'selected'=>'']);
}
in console, I found JSON response is OK and error : TypeError: id is undefined on file dependendent-dropdown.js (line 39, col 49)
Error from console
This line is not correct:
$out[] = ['no_bus' => $bus['no_bus'], 'no_bus' => $bus['no_bus']];
Dependent dropdown requires the first array element to be id and the second one to be name. Change to this:
$out[] = ['id' => $bus['no_bus'], 'name' => $bus['no_bus']];
Related
I'd like to get all table names from my PSQL DB using Doctrine, but I don't want relation tables, e.g.:
Tables:
users
clients
users_clients <-- not this
I'm currently fetching them using
$em->getConnection()->getSchemaManager()->listTables();
Any way to do it without excluding results from array using strpos()?
The following code should work:
public class MyController {
public function listTables(EntityManagerInterface $em) {
$allMetadata = $em->getMetadataFactory()->getAllMetadata();
$tableNames = array_map(
function(ClassMetadata $meta) {
return $meta->getTableName();
},
$allMetadata);
// do something with the table names
}
}
Doctrine documentation: ClassMetadata#getTableName()
Here is how I would do it...
public function getTables(): bool|array {
// get connection any way you do
$connection = BasePDO::getInstance()->getEntityManager()->getConnection();
$query = "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'";
$statement = $connection->prepare($query);
// First column is the table name
return $statement->executeQuery()->fetchFirstColumn();
}
I wrote a code that currently works for me, but it's not finished yet. If you got here to find an answer to the same question I had, feel free to analyse code.
But keep in mind that I'm not a pro (far from it).
This I have inside ReportController:
// Returns an array with my entities
$entities = $em->getMetadataFactory()->getAllMetadata();
//Generate my table names, according to Franz's answer
$tableNames = [
function(ClassMetadata $meta) {
return $meta->getTableName();
},
$entities
];
foreach ($tableNames[1] as $tableKey=>$tableName) {
$table[$tableKey] = $tableName->getTableName();
}
// Generate an array of columns from $table
// Code from generateColumnNames() below
$column[] = $this->getDoctrine()
->getRepository(Chamados::class)
->generateColumnNames($table);
//Since I'm displaying some Entity names in PT-BR, I need to treat them.
//I wish I had a better way to do this without having to treat them one by one
foreach ($entities as $entity) {
$e = explode('\\',$entity->getName());
if ($e[2] === "User") {
$e[2] = "Usuários";
}
else if ($e[2] === "Tramite") {
$e[2] = "Trâmites";
}
else if ($e[2] === "Clients") {
$e[2] = "Clientes";
}
$entKey[] = $e[2];
}
//Insert each name into each array value to display them in my form
$entities = array_combine($entKey, $entities);
//Generate the form
$form = $this->createFormBuilder(['aaa'])
->add('entity', ChoiceType::class, [
'required' => true,
'placeholder' => '',
'attr' => [
'style' => 'text-transform:capitalize',
'class' => 'entity-class general-control'
],
'choices' => $entities
])
->add('type', ChoiceType::class, [
'label' => 'Tipo de relatório',
'required' => true,
'placeholder' => '',
'attr' => [
'style' => 'display: none',
'class' => 'type-class general-control'
],
'choices' => [
'Campo' => 0,
'Quantidade' => 1,
'Tudo' => 2,
]
])
->add('select', ChoiceType::class, [
'label' => 'Campos',
'required' => false,
'multiple' => true,
'attr' => [
'style' => 'text-transform:capitalize; display: none',
'class' => 'select-class general-control'
],
'choices' => $column
])
->add('where', ChoiceType::class, [
'label' => 'Onde',
'placeholder' => '',
'attr' => [
'style' => 'text-transform:capitalize; display: none',
'class' => 'where-class general-control'
],
'choices' => $column
])
->add('operator', ChoiceType::class, [
'label' => false,
'attr' => [
'style' => 'display: none',
'class' => 'operator-class general-control'
],
'choices' => [
'Igual a' => '=',
'Diferente de' => '!=',
'Contém' => 'LIKE',
'Entre' => 'BETWEEN',
'Maior ou igual a' => '>=',
'Menor ou igual a' => '<=',
]
])
->add('parameter', TextType::class, [
'label' => false,
'attr' => [
'style' => 'display: none',
'placeholder' => 'Parâmetro',
'readonly' => 'true',
'class' => 'parameter-class general-control'
]
])
->add('submit', SubmitType::class, [
'label' => 'Gerar relatório',
'attr' => [
'class' => 'button-blue submit-class general-control',
'style' => 'display: none'
]
])
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
//Get each form value to use it on generateReport() (code below)
$entity = $form->get('entity')->getData();
$type = $form->get('type')->getData();
$select = $form->get('select')->getData();
$where = $form->get('where')->getData();
$operator = $form->get('operator')->getData();
$parameter = $form->get('parameter')->getData();
//Generate the report, returning an array
$result = $this->getDoctrine()
->getRepository(Chamados::class)
->generateReport($entity, $type, $select, $where, $operator, $parameter);
return $this->redirectToRoute('generalResult', [
'result' => $result,
'entity' => $entity->getTableName()
]);
}
return [
'form' => $form->createView()
];
generateColumnNames() (Inside a Repository):
public function generateColumnNames($table){
$em = $this->getEntityManager();
foreach($table as $t) {
foreach ($em->getConnection()->getSchemaManager()->listTableColumns($t) as $v) {
$column[$t][$v->getName()] = $v->getName();
}
}
return $column;
}
generateReport() (Inside the same Repository):
public function generateReport($entity, int $type, array $selectField, string $whereField, string $operator, string $parameter): array
{
//0 = Fields / 1 = Count / * = Everything
if ($type === 0) {
foreach($selectField as $key=>$value) {
$select[$key] = "c." . $value;
}
$select = implode(", ", $select);
}
else if ($type === 1){
$select = "count('id')";
}
else {
$select = "c";
};
$query = $this->_em->createQueryBuilder()
->select($select)
->from($entity->getName(), 'c');
if ($operator === "LIKE") {
$parameter = "%" . $parameter . "%";
$query->andWhere("LOWER (c." . $whereField . ") " . $operator . " :" . $whereField);
}
else {
$query->andWhere("c." . $whereField . " " . $operator . " :" . $whereField);
}
$query->setParameter(":" . $whereField, $parameter);
$result = $query->getQuery()->getArrayResult();
return $result;
}
I'm using DepDrop for dependency Dropdownlist. for this, I've written follow codes:
in view form:
use kartik\depdrop\DepDrop;
$catList = ['1' => 1, '2' => 2];
echo $form->field($model, 'cat')->dropDownList($catList, ['id' => 'cat-id']);
// Child # 1
echo $form->field($model, 'subcat')->widget(DepDrop::classname(), [
'options' => ['id' => 'subcat-id'],
'pluginOptions' => [
'depends' => ['cat-id'],
'placeholder' => 'Select...',
'url' => \yii\helpers\Url::to(['/faculty/list']),
],
]);
Controller:
public function actionList()
{
$out = [];
if (isset($_POST['depdrop_parents'])) {
$parents = $_POST['depdrop_parents'];
if ($parents != null) {
$cat_id = $parents[0];
$out = [
['id' => '<sub-cat-id-1>', 'name' => '<sub-cat-name1>'],
['id' => '<sub-cat_id_2>', 'name' => '<sub-cat-name2>'],
];
echo Json::encode(['output' => $out, 'selected' => '']);
return;
}
}
echo Json::encode(['output' => '', 'selected' => '']);
}
but it doesn't work. I found out that actionList is't called by include follow code at the first of actionList function.
file_put_contents("c:/testtest.txt", implode(',',$_POST));
and this is head of request:
Request URL: http://admin.same.ir/index.php?r=faculty/list
Request Method: POST
Status Code: 400 Bad Request
Remote Address: 127.0.0.1:80
Referrer Policy: no-referrer-when-downgrade
I don't know what is the problem!!
it was just for CSRF:
I added follow code to controller:
public $enableCsrfValidation = false;
I have 2 select2 dropdownlist the second depends on data from the first one
the first one code :
<?= $form->field($model, 'patient_id')->widget(select2::className(),[
'data'=> arrayhelper::map(patient::find()->all(),'patient_id','patient_name'),
'options'=>['placeholder'=>'select patient Name ... '],
'pluginOptions'=>[
'allowClear'=>true
],
])?>
the second one code :
<?= $form->field($model, 'doctor_id')->widget(select2::className(),[
'data'=> arrayhelper::map(doctors::find()->all(),'doctor_id','doctor_name'),
'options'=>['placeholder'=>'أختر اسم الطبيب '],
'pluginOptions'=>[
'allowClear'=>true
],
])?>
i know the sql code in the second one is :
select doctor_name from doctors
so i need it to be :
SELECT DISTINCT doctor_name from doctors where doctor_id in (SELECT doctor_id from patient_services WHERE patient_id="THE VALUE FROM THE 1st DROPDOWNLIST" )
in the regular dropdownlist it work by like this way Yii2 Lesson - 20 Dependent Drop Down Lists By DoingITeasyChannel but in select2 i didn't find how to do it .
------------------------------- after update ----
as the comments there is DepDrop but i got confused how to use it.
i've changed
<?= $form->field($model, 'patient_id')->widget(Select2::classname(), [
'data' => ArrayHelper::map(patient::find()->asArray()->all(), 'patient_id', 'patient_name')]);
?>
and the other one is :
<?= $form->field($model, 'doctor_id')->widget(DepDrop::classname(), [
'options' => ['placeholder' => 'Select ...'],
'type' => DepDrop::TYPE_SELECT2,
'select2Options'=>['pluginOptions'=>['allowClear'=>true]],
'pluginOptions'=>[
'depends'=>['receipts-doctor_id'], // here i got confused
'url' => Url::to(['/receipts/child']),
'loadingText' => 'Loading child level 1 ...',
]
]);
?>
in controller
public function actionChild() {
$out = [];
if (isset($_POST['depdrop_parents'])) { // what they meaning by depdrop_parents or what i should change it ?
$id = end($_POST['depdrop_parents']);
$list = Account::find()->andWhere(['parent'=>$id])->asArray()->all();
$selected = null;
if ($id != null && count($list) > 0) {
$selected = '';
foreach ($list as $i => $account) {
$out[] = ['id' => $account['id'], 'name' => $account['name']];
if ($i == 0) {
$selected = $account['id'];
}
}
// Shows how you can preselect a value
echo Json::encode(['output' => $out, 'selected'=>$selected]);
return;
}
}
echo Json::encode(['output' => '', 'selected'=>'']);
}
First field (Select2):
<?= $form->field($model, 'patient_id')->widget(Select2::classname(), [
'data' => ArrayHelper::map(patient::find()->asArray()->all(), 'patient_id', 'patient_name')]);
?>
Second field (DepDrop):
<?= $form->field($model, 'doctor_id')->widget(DepDrop::classname(), [
'options' => ['placeholder' => 'Select ...'],
'type' => DepDrop::TYPE_SELECT2,
'select2Options'=> ['pluginOptions' => ['allowClear' => true]],
'pluginOptions'=> [
'depends' => ['receipts-doctor_id'],
'url' => Url::to(['/receipts/child']),
'loadingText' => 'Loading child level 1 ...',
]
]);
?>
Plugin option 'depends' => ['receipts-doctor_id'], shows which element (takes element's ID) must be changed (on click, on select, etc.) in order to send Ajax request and retrieve results from controller. In this case, an element with ID receipts-doctor_id should be present. If you don't know or you want to set ID for parent element, you can use 'options' => ['id' => 'receipts-doctor_id'], for your parent element.
And for controller, you can retrieve value like this:
public function actionChild()
{
$depdropParents = Yii::$app->request->post('depdrop_parents');
if ($depdropParents !== null) {
$value = $depdropParents[0];
// Now your $value contains what was being selected in parent element
}
}
I use select2 ajax loading. I get the code from this link: http://demos.krajee.com/widget-details/select2. When I enter words into field, it display all data/value, but it can't automatic select data/value according to words that I enter into field. So, my select2 always select the first data/value and display all value. What's the problem? These are the codes:
_form.php
$url = Url::to(['/paket/jsonlist']);
$cityDesc = empty($model->no_induk) ? '' : Penerima::findOne($model->no_induk)->nama;
echo $form->field($model, 'no_induk')->widget(Select2::classname(), [
'initValueText' => $cityDesc, // set the initial display text
'options' => ['placeholder' => 'Search for a city ...'],
'pluginOptions' => [
'allowClear' => true,
'minimumInputLength' => 1,
'language' => [
'errorLoading' => new JsExpression("function () { return 'Waiting for results...'; }"),
],
'ajax' => [
'url' => $url,
'dataType' => 'json',
'data' => new JsExpression('function(params) { return {q:params.term}; }')
],
'escapeMarkup' => new JsExpression('function (markup) { return markup; }'),
'templateResult' => new JsExpression('function(no_induk) { return no_induk.text; }'),
'templateSelection' => new JsExpression('function (no_induk) { return no_induk.id; }'),
],
]);
my controller:
public function actionJsonlist($q = NULL, $id = NULL)
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$out = ['results' => ['id' => '', 'text' => '']];
if(!is_null($q))
{
$query = new \yii\db\Query;
$mainQuery = $query->select('no_induk AS id, nama AS text')
->from('penerima')
->limit(20);
$command = $mainQuery->createCommand();
$data = $command->queryAll();
$out['results'] = array_values($data);
}
elseif ($id > NULL)
{
$out['results'] = ['id' => $id, 'text' => \frontend\models\Penerima::find($id)->nama];
}
return $out;
}
Could be you use the attribute name and not the vars
echo $form->field($model, 'no_induk')->widget(Select2::classname(), [
'initValueText' =>'cityDesc', // set the initial display text
or
echo $form->field($model, 'no_induk')->widget(Select2::classname(), [
'initValueText' =>$model->cityDesc, // set the initial display text
Here I have two tables
Employeedetails
Claimprocess
In employeedetails I have 8 columns:
Company_name, Employeecode, Employee_name, father_name, mother_name, wife_name, child1_name, and child2_name.
In Claimprocess table I have 5 columns:
Company_name, Employeecode, Employee_name, Healthcard_no, and claim_for.
In Claimprocess I set a dependent dropdown for employeecode. For example, if admin selects a company_name that automatically shows dependent employeecode, then again admin selects an employeecode that automatically shows the employee_name and employee relations name such as father_name, mother_name, wife_name etc...
This is the dependent dropdown code for employee_code by selecting company_name
claimform.php
<?= $form->field($model, 'company_id')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Company::find()->all(),'id','companyname'),
'language' => 'en',
'options' => [
'placeholder' => 'Select a company ...',
'onchange' => '
$.post( "index.php?r=employeedetails/lists&id='.'"+$(this).val(), function( data ) {
$( "select#claimprocess-employee_id" ).html( data );
});',
],
'pluginOptions' => [
'allowClear' => true
],
]);
?>
employeedetailscontroller.php
public function actionLists($id)
{
$countEmployeedetails = Employeedetails::find()
->where(['company_id' => $id])
->count();
$employeedetails = Employeedetails::find()
->where(['company_id' => $id])
->all();
if($countEmployeedetails>0){
foreach($employeedetails as $employee){
echo "<option value='".$employee->id."'>".$employee->employeecode."</option>";
}
}
else{
echo "<option>-</option>";
}
}
This is dependent dropdown code for employee_name and relations_name by selecting employeecode
claimform.php
<?= $form->field($model, 'employee_id')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Employeedetails::find()- >all(),'id','employeecode'),
'language' => 'en',
'options' => [
'placeholder' => 'Select a employeecode ...',
'onchange' => '
$.post( "index.php?r=employeedetails/lists2&id='.'"+$(this).val(), function( data ) {
$( "select#claimprocess-claim_for" ).html( data );
}),
$.post( "index.php?r=employeedetails/lists1&id='.'"+$(this).val(), function( data ) {
$( "select#claimprocess-employee_name" ).html( data );
});',
],
'pluginOptions' => [
'allowClear' => true
],
]);
?>
employeedetailscontroller.php
public function actionLists1($id)
{
$countEmployeedetails = Employeedetails::find()
->where(['id' => $id])
->count();
$employeedetails = Employeedetails::find()
->where(['id' => $id])
->all();
if($countEmployeedetails >= 0)
{
foreach($employeedetails as $employee)
{
echo "<option value='".$employee->id."'>".$employee->name."</option>";
}
}
else{
echo "<option>-</option>";
}
}
public function actionLists2($id)
{
$countEmployeedetails = Employeedetails::find()
->where(['id' => $id])
->count();
$employeedetails = Employeedetails::find()
->where(['id' => $id])
->all();
if($countEmployeedetails >= 0)
{
foreach($employeedetails as $employee)
{
echo "<option value='".$employee->id."'>".$employee->father_name."</option>";
echo "<option value='".$employee->id."'>".$employee->mother_name."</option>";
echo "<option value='".$employee->id."'>".$employee->wife_name."</option>";
echo "<option value='".$employee->id."'>".$employee->child1_name."</option>";
echo "<option value='".$employee->id."'>".$employee->child2_name."</option>";
}
}
else{
echo "<option>-</option>";
}
}
In claim_for field I have to select relation names of the particular employee, so what I did is combine all relation fields such as father_name, mother_name etc using array_merge and I got a name in form.
claimform.php
<?php
$em = ArrayHelper::map(Employeedetails::find()- >all(),'id','father_name');
$emp = ArrayHelper::map(Employeedetails::find()->all(),'id','mother_name');
$emp1 = ArrayHelper::map(Employeedetails::find()->all(),'id','wife_name');
$emp2 = ArrayHelper::map(Employeedetails::find()->all(),'id','child1_name');
$emp3 = ArrayHelper::map(Employeedetails::find()->all(),'id','child2_name');
$print = array_merge($em,$emp,$emp1,$emp2,$emp3);
// echo "<pre>";print_r($print);exit();echo "</pre>";
echo $form->field($model, 'claim_for')->dropDownList($print,['option' => '']);
?>
The problem:
While selecting relation I am getting all the relations name in the form, but while saving it in gridview I am getting employee_id instead of merge_array id.
So here I used this code to get relation name, but I dont know whether my write code is right or wrong:
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
//'id',
'company.companyname',
'employee.employeecode',
'employee.name',
'claim_for',
[
'attribute' => 'claim_for',
'format' => 'raw',
'value' => function($model, $key, $index, $grid) {
$temp = $model->claim_for;
$si = Employeedetails::find()->where(['id' => $temp])->one();
return $si['father_name'];// here how to bring merged array relation name
},
],
'healthcard_no',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
I've been searching for two days but am not able to get it. If anyone can help, I'd appreciate it.
create field in claimprocess table as claim_for and store the getting value from employeedetails in seperate table. thats it, Hope it will you
claimprocesscontroller.php
$commaList = explode('-', $model->claim_for);
$model->claimer_name = $commaList[1];
employeedetails.php
echo "<option value='".$employee->id. '-' .$employee->name. "'>".$employee-RelationName7."</option>";