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
Related
So I've got an issue with element-api in php, which is a plugin for CRAFT cms, could someone help - what am I doing wrong here? I can't print time.json - always getting :
{"error":{"code":0,"message":"Class name must be a valid object or a
string"}}
here's the code:
<?php
use Craft;
use craft\elements\Entry;
use craft\controllers\TemplatesController;
use League\Fractal\TransformerAbstract;
use craft\web\View;
use craft\elements\User;
return [
'endpoints' => [
'tooltip-modal.json' => function() {
$affiliateId = Craft::$app->request->getParam('entryId');
$siteLanguage = Craft::$app->request->getParam('siteLanguage');
$data = [
'elementType' => Entry::class,
'paginate' => false,
'transformer' => function(Entry $affiliate) {
$view = Craft::$app->getView();
// $view->setTemplateMode($view::TEMPLATE_MODE_SITE);
return [
'affiliate' => $view->renderTemplate('modals/tooltipAffModal.twig', ['affiliate' => $affiliate])
];
},
'criteria' => ['id' => $affiliateId, 'site' => $siteLanguage]
];
return $data;
},
'time.json' => function() {
// $userId = Craft::$app->request->request->getParam('userId');
$data = [
'elementType' => User::class,
'paginate' => false,
'transformer' => function(User $user) {
return [
'date' => $user->winHistory::find()->orderBy(['id' => SORT_DESC])->one()
];
},
// 'criteria' => ['id' => $affiliateId, 'site' => $siteLanguage]
];
return $data;
}
]
];
i have a problem with Kartik Select2. When I want save multiple data in my controller, nothing is saved. And I remove foreach in controller, Yii return me error with information about $university_id IS NULL.
User Form
<?= $form->field($user_university, 'university_id')->widget(Select2::classname(),[
'name' => 'university_id[]',
'data' => ArrayHelper::map(
\app\models\University::find()->asArray()->all(),
'id',
function ($university) {
return $university['name'];
}
),
'size' => Select2::MEDIUM,
'options' => ['placeholder' => 'Select a state ...', 'multiple' => true],
'pluginOptions' => [
'allowClear' => true
],
]); ?>
User Controller
$user = new User();
$user->scenario = User::SCENARIO_CREATE;
$auth_assignment = new AuthAssignment();
$user_company = new UserCompany();
$user_university = new UserUniversity();
$user_status = UserStatus::find()
->select('id')
->where(['name' => UserStatus::NON_AUTHORIZED_USER])
->one();
if ($user->load(Yii::$app->request->post()) && $auth_assignment->load(Yii::$app->request->post())) {
$user->auth_key = Yii::$app->getSecurity()->generateRandomString();
$user->password_hash = Yii::$app->getSecurity()->generatePasswordHash($user->password);
$user->password_reset_token = Yii::$app->getSecurity()->generateRandomString();
$user->status_id = $user_status->id;
$user->created_at = date('Y-m-d H:i:s');
$user->updated_at = date('Y-m-d H:i:s');
if ($user->save()) {
$auth_assignment->user_id = $user->id;
$auth_assignment->created_at = date('Y-m-d H:i:s');
$universities = $user_university->university_id;
foreach((array) $universities as $university)
{
$newUserUniversity = new UserUniversity();
$newUserUniversity->user_id = $user->id;
$newUserUniversity->university_id = $university;
$newUserUniversity->created_at = date('Y-m-d H:i:s');
$newUserUniversity->save(false);
}...
User University Model Rule
public function rules()
{
return [
[['user_id', 'university_id', 'created_at'], 'required'],
[['user_id', 'university_id','confirm'], 'integer'],
[['created_at','university_id'], 'safe'],
[['university_id'], 'exist', 'skipOnError' => true, 'targetClass' => University::className(), 'targetAttribute' => ['university_id' => 'id']],
[['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']],
];
}
Looking at your code i can't see where you are loading the data from the post request into the $user_university before you start looping on the university_id. You need to call $user_university->load(Yii::$app->request->post()), look the following piece of code from your script
if ($user->save()) {
$auth_assignment->user_id = $user->id;
$auth_assignment->created_at = date('Y-m-d H:i:s');
// this below line will give you an empty string rather than
// the selected ids of the `university` that you selected
// in the multi-dropdown
$universities = $user_university->university_id;
and the very next line is the foreach((array) $universities as $university) in which you are trying to save which won't run even once, as there isnt any array loaded in the $unversities. So you can add a call before you get the array from the attribute, dont know if your requirements are to return the user with an error if the data is not loaded for the $user_university otherwise you need to add it to the main check
if ($user->load(Yii::$app->request->post()) && $auth_assignment->load(Yii::$app->request->post()) &&
$user->university->load(Yii::$app->request->post())) {
So your code should look like below
$user = new User();
$user->scenario = User::SCENARIO_CREATE;
$auth_assignment = new AuthAssignment();
$user_company = new UserCompany();
$user_university = new UserUniversity();
$user_status = UserStatus::find()
->select('id')
->where(['name' => UserStatus::NON_AUTHORIZED_USER])
->one();
//validate all models
$allModelsValid=$user->load(Yii::$app->request->post()) && $auth_assignment->load(Yii::$app->request->post()) && $user_university->load(Yii::$app->request->post());
if ($allModelsValid) {
$user->auth_key = Yii::$app->getSecurity()->generateRandomString();
$user->password_hash = Yii::$app->getSecurity()->generatePasswordHash($user->password);
$user->password_reset_token = Yii::$app->getSecurity()->generateRandomString();
$user->status_id = $user_status->id;
$user->created_at = date('Y-m-d H:i:s');
$user->updated_at = date('Y-m-d H:i:s');
if ($user->save()) {
$auth_assignment->user_id = $user->id;
$auth_assignment->created_at = date('Y-m-d H:i:s');
$universities = $user_university->university_id;
foreach((array) $universities as $university)
{
$newUserUniversity = new UserUniversity();
$newUserUniversity->user_id = $user->id;
$newUserUniversity->university_id = $university;
$newUserUniversity->created_at = date('Y-m-d H:i:s');
$newUserUniversity->save(false);
}...
Also apart from above i dont find a reason to use the name as university_id[] for the dropdown rather than university_id
There are multiple ways of Usage of select2 now currently you are using Usage with ActiveForm and model see below multiple ways.
use kartik\select2\Select2
// Usage with ActiveForm and model
echo $form->field($model, 'state_1')->widget(Select2::classname(), [
'data' => $data,
'options' => ['placeholder' => 'Select a state ...'],
'pluginOptions' => [
'allowClear' => true
],
]);
// With a model and without ActiveForm
echo Select2::widget([
'model' => $model,
'attribute' => 'state_2',
'data' => $data,
'options' => ['placeholder' => 'Select a state ...'],
'pluginOptions' => [
'allowClear' => true
],
]);
// Without model and implementing a multiple select
echo '<label class="control-label">Provinces</label>';
echo Select2::widget([
'name' => 'state_10',
'data' => $data,
'options' => [
'placeholder' => 'Select provinces ...',
'multiple' => true
],
]);
// A disabled select2 list input
echo '<label class="control-label">State</label>';
echo Select2::widget([
'name' => 'state_11',
'data' => $data,
'disabled' => true
]);
I guess your problem is in :
'data' => ArrayHelper::map(
\app\models\University::find()->asArray()->all(),
'id',
function ($university) {
return $university['name'];
}
),
Please check data attribute .. check you are passing correct array or not.
I'm trying to add my own action button in Yii2-Kartik Gridview.
This is my custom button:
This is my code in index.php
[
'class' => 'yii\grid\ActionColumn',
'template' => '{edit}',
'buttons' => [
'edit' => function ($url, $model) {
return Html::a('<button type="button" class="btn btn-edit-npwp"><i class="glyphicon glyphicon-plus-sign"></i></button>', $url, [
'title' => Yii::t('app', 'Edit'),
'data-toggle' => "modal",
'data-target' => "#myModal",
'data-method' => 'post',
]);
},
],
'urlCreator' => function ($action, $model, $key, $index) {
if ($action === 'edit') {
$url = Url::toRoute(['vatout-faktur-out/add-data', 'id' => $model->fakturId], ['data-method' => 'post',]);
return $url;
}
}
],
and this is my action in controller.php
public function actionAddData($id) {
$model = new VatoutFakturOut();
return $this->render('addData', [
'model' => $model,
]);
}
I want to process the data from the row that I've clicked the button.
But, this return error
Missing required parameters: id
Why does this happen? And how to fix this?
Thanks
In urlCreator you used if statement to check, if action is edit, and if it is, you add param id to your button url. Otherwise it doesnt have one, so there's two solutions:
Remove if statement from:
'urlCreator' => function ($action, $model, $key, $index) {
$url = Url::toRoute(['vatout-faktur-out/add-data', 'id' => $model->fakturId]);
return $url;
}
Or remove$id from your actionAddData() - because youre not using it at all:
public function actionAddData() {
$model = new VatoutFakturOut();
return $this->render('addData', [
'model' => $model,
]);
}
I am trying to implement the 2amigos SelectizeDropDownList widget in a form to add new values to a table directly within the dropdown.
I am using the model Book and the Model Author so basically want to be able to add a new author in the book form.
This is the book controller at the update function:
public function actionUpdate($id) {
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['index']);
} else {
return $this->render('update', [
'model' => $model,
'categories' => BookCategory::find()->active()->all(),
'publishers' => Publisher::find()->all(),
'copirights' => Copiright::find()->all(),
'authors' => Author::find()->all(),
]);
}
}
This is the form:
<?=
$form->field($model, 'author_id')->widget(SelectizeDropDownList::className(), [
// calls an action that returns a JSON object with matched
// tags
'loadUrl' => ['author/list'],
'value' => $authors,
'items' => \yii\helpers\ArrayHelper::map(\common\models\author::find()->orderBy('name')->asArray()->all(), 'id', 'name'),
'options' => [
'class' => 'form-control',
'id' => 'id'
],
'clientOptions' => [
'valueField' => 'id',
'labelField' => 'name',
'searchField' => ['name'],
'autosearch' => ['on'],
'create' => true,
'maxItems' => 1,
],
])
?>
And this is the function author controller:
public function actionList($query) {
$models = Author::findAllByName($query);
$items = [];
foreach ($models as $model) {
$items[] = ['id' => $model->id, 'name' => $model->name];
}
Yii::$app->response->format = \Yii::$app->response->format = 'json';
return $items;
}
The form works fine to load, filter, search and add new items.
But it is not inserting the new typed attribute in the author table.
Do I need to add something in the book controller?
How can I check if it is a new value or a change of an existing author?
Thanks a lot
I made it work with the following code, not sure the most elegant because i am checking the if the author_id is a number or a string.
In my case the author won't be a number anyway.
public function actionUpdate($id) {
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post())) {
$x = Yii::$app->request->post('Book');
$new_author = $x['author_id'];
if (!is_numeric($new_author)) {
$author = new Author();
$author->name = $new_author;
$author->save();
$model->author_id = $author->id;
}
if ($model->save()) {
return $this->redirect(['index']);
}
} else {
return $this->render('update', [
'model' => $model,
'categories' => BookCategory::find()->active()->all(),
'publishers' => Publisher::find()->all(),
'copirights' => Copiright::find()->all(),
'authors' => Author::find()->all(),
]);
}
}
Please look the picture below.
As you can see total is 215340 in the summary column. What I want is that in the next page it should start summing those numbers on this number.
Here is a code.
GridView::widget([
'dataProvider' => $dataProvider,
// 'filterModel' => $searchModel,
'columns' => [
[
'class' => 'kartik\grid\SerialColumn'],
// 'id',
[
'attribute' => 'customer_id',
'value' => function ($data) {
return $data->customerDetail->account_no;
}
],
[
'attribute' => 'naration',
'pageSummary' => 'Total',
],
[
'attribute' => 'transaction_type',
'label' => 'Deposits',
'pageSummary' => true,
'pageSummaryOptions' => ['id' => 'total_sum'],
'value' => function ($data) {
if($data->transaction_type==10)
return $data->amount;
else
return 0;
}
],
[
'attribute' => 'transaction_type',
'label' => 'Withdrawals',
'pageSummary' => true,
'value' => function ($data) {
if($data->transaction_type==11)
return $data->amount;
else
return 0;
}
],
[
'class' => 'backend\components\TotalColumn',
'label' => 'Balance',
'attribute' =>'amount',
],
],
// This line displays sum of the columns.
'showPageSummary' => true,
]);
?>
I was thinking about sending this page's sum to the next page using $_GET but the problem is when user going to previous pages i.e. from page 3 to 2. Do you any widget or something for this problem?
My idea is using mysql to select sum of all records in the current column and add this value with the total value of the previous page, I need to know offset and limit of the current page for this query, I can get those values from data provider, to achieve this I have to override the function \yii\grid\Column::renderFooterCellContent().
Extend \yii\grid\DataColumn class
namespace frontend\components;
use yii\helpers\ArrayHelper;
class DataColumn extends \yii\grid\DataColumn
{
protected function renderFooterCellContent()
{
if ($this->footer instanceof \Closure) {
return call_user_func($this->footer, ArrayHelper::getValue($this, 'grid.dataProvider.pagination'));
} else {
return parent::renderFooterCellContent();
}
}
}
Your view file
use frontend\models\Client;
use yii\db\Expression;
use yii\db\Query;
use yii\grid\GridView;
use yii\data\Pagination;
use frontend\components\DataColumn;
echo GridView::widget([
'dataProvider' => $dataProvider,
'dataColumnClass' => DataColumn::className(),
'showFooter' => true,
'columns' => [
//['class' => 'yii\grid\SerialColumn'],
'id',
[
'attribute' => 'num_users',
'footer' => function ($pagination) {
if ($pagination instanceof Pagination) {
$offset = $pagination->offset;
$limit = $pagination->limit;
$cquery = (new Query())
->select(['sub_users' => new Expression('SUM(num_users)')])
->from([
'cpage' => (new Query())
->select('num_users')
->offset($offset)
->limit($limit)
->from(Client::tableName())
]);
//negative offset is illegal
if ($offset > 0) {
$pquery = (new Query())
->select(['sub_users' => new Expression('SUM(num_users)')])
->from([
'ppage' => (new Query())
->select('num_users')
->offset(0)
->limit($offset)
->from(Client::tableName())
]);
$cquery->union($pquery, true);
}
return (new Query())->from(['subt' => $cquery])->sum('sub_users');
}
}
],
]
]);
Raw SQL query
SELECT SUM(sub_sum_users) FROM (
SELECT SUM(num_users) as sub_sum_users FROM (
SELECT num_users FROM `clients` LIMIT 20 OFFSET 120
) cpage
UNION ALL
SELECT SUM(num_users) as sub_sum_users FROM (
SELECT num_users FROM `clients` LIMIT 20 OFFSET 100
) ppage
) sublt
Note:
You could consider to use ActiveRecord, my girdview has a lot of join queries so it's very heavy for me
$offset = $pagination->offset;
$limit = $pagination->limit;
$cquery = Client::find()
->select(['sub_users' => new Expression('SUM(num_users)')])
->from([
'cpage' => Client::find()->select('num_users')->offset($offset)->limit($limit)
]);
//negative offset is illegal
if ($offset > 0) {
$pquery = $cquery = Client::find()
->select(['sub_users' => new Expression('SUM(num_users)')])
->from([
'ppage' => Client::find()->select('num_users')->offset(0)->limit($offset)
]);
$cquery->union($pquery, true);
}
return (new Query())->from(['subt' => $cquery])->sum('sub_users');