As I needed a checkbox list I decided to use the checkboxlist , but I cant seem to add the values into the DB, if im using the list it only stores the first value from the list instead of all checked checkboxes.
[['sort_abc'], 'string']//not working
[['sort_abc'], 'integer']//not working
<?=$form->field($model, 'sort_abc[]')->checkBoxLIst( ['1' => 'Item A', '2' => 'Item B', '3' => 'Item C'])->label($model->getAttributeLabel('sort_abc'));?>
DB field
sort_abc | varchar(255) | yes | NULL
Also how can I add a image before every checkbox.
Yii wont magically convert your array to string or (worse) integer. You may use virtual attributes defined by getters/setter to simplify whole thing:
public function getSortAbcArray() {
if (empty($this->sort_abs)) {
return [];
}
return explode(',', $this->sort_abc);
}
public function setSortAbcArray($value) {
$this->sort_abs = implode(',', array_filter($value));
}
Then use this new attribute in form:
<?= $form->field($model, 'sortAbcArray')
->checkBoxList(['1' => 'Item A', '2' => 'Item B', '3' => 'Item C'])
->label($model->getAttributeLabel('sort_abc')); ?>
And in model rules:
['sortAbcArray', 'each', 'rule' => ['integer']]
Then $model->sortAbcArray returns values as array and $model->sort_abc as string, where values are separated by commas.
You don't need to name as array the field: sort_abc[] -> sort_abc
Simply doing it, the model will store in its attribute the checked checkboxes values.
To save the selected values, in your controller you can put:
$post = Yii::$app->request->post();
if (count($post) > 0) {
$post['YourModel']['sort_abc'] = implode(",", $post['YourModel']['sort_abc']);
}
if ($model->load($post) && $model->save()) {
...
}
Related
I want to conditionally change the widget of a plain text field attached to a node by using hook_form_alter in Drupal 8.7.6.
function mymodule_form_node_article_edit_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
$options=[
'test1' => 'AAA',
'test2' => 'BBB',
'test3' => 'CCC',
'test4' => 'DDD',
];
$form['field_testdrop']['widget'][0]['#type']='select';
$form['field_testdrop']['widget'][0]['#options'] = $options;
}
However, when trying to save the node, I get the following error:
Error: Cannot create references to/from string offsets in Drupal\Component\Utility\NestedArray::setValue() (line 155 of core/lib/Drupal/Component/Utility/NestedArray.php).
What can I do to prevent this?
This Works:
$form['field_priority_email_id']['widget'][0]['value']['#type'] = 'select';
$form['field_priority_email_id']['widget'][0]['value']['#options'] = $options;
$form['field_priority_email_id']['widget'][0]['value']['#size'] = NULL;
You have to set '#size' to NULL or the select widget will not render correctly.
I have a Model who has a column (attribute) that stored a comma separated value of IDs.
For Example,
Movie has a column "Genre" that includes more than one genre, e.g.: 40,20,1,3
How can I use Select2 widget to show these values separated when 'multiple' => true
And how can I save them back into comma-separated value as a string. I want a solution that will allow for quick flexibility. I know you can implode and explode the string but seems too much.
Any help appreciated
If I remember correctly pass the default option as part of the $options configuration for the widget:
echo $form->field($model, 'model_attribute_name')->widget(Select2::className(), [
'data' => $data
'options' => [
'class' => 'form-control',
'placeholder' => 'Choose Option...',
'selected' => 40
],
'pluginOptions' => [
'allowClear' => true,
],
])->label('Select2 Form Field');
This is from memory for grain fo salt here. The documentation at http://demos.krajee.com/widget-details/select2 is not very specific about how to do this.
I don't believe you can do that. Select2 sends the data in post as an array, so you would still need to use implode before saving. What i would do instead is in your model class:
class MyModel extends \yii\db\ActiveRecord {
$public myArrayAttribute;
...
public function beforeSave($insert) {
if (parent::beforeSave($insert)) {
$this->myAttribute = implode(',', $this->myArrayAttribute);
return true;
}
return false;
}
public function afterFind() {
parent::afterFind();
$this->myArrayAttribute = explode(',', $this->myAttribute);
}
}
This way myArrayAttribute will hold the values from the comma separated field as an array. Of course you will need to add validation rules for it and use it instead of your other attribute in create and update forms.
if you're displaying a form with already populated fields, maybe you want to update an already existing object, and you want to display the already saved value for the Select2 field, use 'data' => [ 1 => 'Some value' ], where 1 is the value, associated to the value displayed in the form. You can retrieve stuff to put in data from DB beforehand.
Source: https://github.com/kartik-v/yii2-widget-select2/issues/37
Controller side:
$regs = Model::all('id','name');
return view('aview',compact('regs'));
View side:
{{ Form::select('id', $regs) }}
The dropdown gets rendered and populated but displays JSON objects such as {"id:1","name: Aname"} instead of displaying Aname and setting the post value to 1
Try this
In your controller
$regs = Model::pluck('name','id');
Keep your view same
Hope this will work
You can populate like this:
{!! Form::select('id', $regs->lists('name', 'id'), null, ['class' => 'form-control']) !!}
Form::select accepts four parameters:
public function select($name, $list = [], $selected = null, $options = []);
The name of the html field
the list of options
the selected value
an array of html attributes
You can generate the list by using
$regs = Model::all('id','name');
$plucked = $regs->pluck('name', 'id');
// $plcuked = ['id1' => 'name1', 'id2' => 'name2' ...]
And the blade code should look like this
{{ Form::select('name', $plucked, null, ['class' => 'form-control']); }}
I maybe making this problem a bit complicated but I think its worth using the plugin.
You can take the use of very popular plugin - Select2. This plugin of jQuery helps you to fetch data from server and populate the fetched data into our dropdown in minutes. Your code goes like this.
// Code in your Controller Method
$regs = Model::all();
$data = [];
foreach($regs as $reg) {
$data[] = [
'id' => $reg->id,
'text' => $reg->name
];
}
return json_encode(['items' => $data]);
// Code in your desired View
<select id="select_items"></select>
// Code in js
$('#select_items').select2({
ajax: {
url: '/example/api', // <--------- Route to your controller method
processResults: function (data) {
return {
results: data.items
};
}
}
});
You can also integrate search options using this plugins as it helps you to fetch results based on your search keywords (for more see Select2 Examples). Hope this helps you to solve your problem.
I have several fields in my form that i wish to post to the database. All the other fields bar the dropdown field are all working fine
The official documentation for zend 2 is not really clear on how to deal with posting data from a dropdown menu into the database
Here's what i have:
my addAction in the controller
public function addAction()
{
$form = new UsersForm();
$form->get('submit')->setValue('Add');
$request = $this->getRequest();
if ($request->isPost())
{
$users = new Users();
$form->setInputFilter($users->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid())
{
$users->exchangeArray($form->getData());
$this->getUsersTable()->saveUser($users);
// Redirect to list of albums
return $this->redirect()->toRoute('index');
}
}
return array('form' => $form);
}
my form
public function __construct($name = null)
{
// we want to ignore the name passed
parent::__construct('users');
//other form elements...
//the dropdown menu
$this->add(array(
'type' => 'Select',
'name' => 'groupid',
'options' => array(
'label' => 'Group',
'value_options' => array(
'0' => 'Not Selected',
'1' => 'Super Admin',
'2' => 'Company Admin',
),
),
));
//...
}
}
the view
<?php
$form->setAttribute('action', $this->url('user', array('action' => 'add')));
$form->prepare();
echo $this->form()->openTag($form);
echo $this->formRow($form->get('groupid'));
echo $this->formSubmit($form->get('submit'));
echo $this->form()->closeTag();
When i run my application for the addAction, i get an error message:
Statement could not be executed (23000 - 1048 - Column 'GroupID' cannot be null)
where 'GroupID' is the column in my table that takes the value from the dropdown which means the field is not being posted
I need help on this
If the column in your database is GroupID, the form element should also be named that. Yours is groupid (i.e. lowercase). If that doesn't fix the issue, please edit your question to include the DB structure and the code for the saveUser() function.
I need help/guidance in developing a multi-select filter search for my Laravel 4 app.
I have a table in my database called 'accounts'. This table is linked to other tables in the database via the following relationships:
'users' via belongs to (User model has a has many relationship to accounts)
'account_types' via belongs to (AccountType model has a has one relationship to accounts)
In my view I would like 3 multi-select boxes, company names (taken from the accounts table 'company_name' field), account managers (taken from the account_managers table, 'first_name' and 'last_name' fields) and account type (taken from the account_types table, 'type' field).
When a user selects values from these multi-select boxes and submits the form, I need to search the relevant tables and bring back the results. I don't want to use joins for this, as it is very slow. Especially, when bringing back values for the multi-select boxes.
If possible I would like to use Eloquent relationships in a way that brings back the results quickly.
I have this working with joins and query strings but it is very slow, up to 10 to 15 seconds.
I hope someone can help me out with this. Cheers.
OK, I have this working like a charm now by implementing select2, rather than simply loading all contacts in one go. Works much nicer too.
Here's my index method in AdminContactsController.php:
public function index()
{
$contact_names_value = explode(',', Input::get('contact_names_value'));
$accounts_value = explode(',', Input::get('accounts_value'));
$account_managers_value = explode(',', Input::get('account_managers_value'));
// In the view, there is a dropdown box, that allows the user to select the amount of records to show per page. Retrive that value or set a default.
$perPage = Input::get('perPage', 10);
// This code retrieves the order from that has been selected by the user by clicking on table ciolumn titles. The value is placed in the session and is used later in the Eloquent query and joins.
$order = Session::get('contact.order', 'cname.asc');
$order = explode('.', $order);
$message = Session::get('message');
$default = ($perPage === null ? 10 : $perPage);
$contacts_trash = Contact::contactsTrash($order)->get();
$this->layout->content = View::make('admin.contacts.index', array(
'contacts' => Contact::contacts($order, $contact_names_value, $accounts_value, $account_managers_value, $perPage)->paginate($perPage)->appends(array('accounts_value' => Input::get('accounts_value'), 'account_managers_value' => Input::get('account_managers_value'))),
'contacts_trash' => $contacts_trash,
'perPage' => $perPage,
'message' => $message,
'default' => $default
));
}
My scopeContacts method in my Contact.php model:
public function scopeContacts($query, $order, $contact_names_value, $accounts_value, $account_managers_value, $perPage)
{
$query->leftJoin('accounts', 'accounts.id', '=', 'contacts.account_id')
->leftJoin('users', 'users.id', '=', 'accounts.user_id')
->orderBy($order[0], $order[1])
->select(array('contacts.*', DB::raw('contacts.id as cid'), DB::raw('CONCAT(contacts.first_name," ",contacts.last_name) as cname'), DB::raw('CONCAT(users.first_name," ",users.last_name) as amname')));
if (empty($contact_names_value[0])) {
//
} else {
$query = $query->whereIn('contacts.id', $contact_names_value);
}
if (empty($accounts_value[0])) {
//
} else {
$query = $query->whereIn('accounts.id', $accounts_value);
}
if (empty($account_managers_value[0])) {
//
} else {
$query->whereIn('users.id', $account_managers_value);
}
}
Here's my JS code:
$('#contact_names_value').select2({
placeholder: 'Search contacts',
minimumInputLength: 3,
ajax: {
url: '/admin/get-contact',
dataType: 'json',
data: function (term, page) {
return {
contact_names_value: term
};
},
results: function (data, page) {
return {results: data};
}
},
tags: true
});
Here's my method getContactByName implemented in my AdminContactsController.php (similar methods implemented for users and accounts) code:
public function getContactByName()
{
$name = Input::get('contact_names_value');
return Contact::select(array('id', DB::raw('concat(first_name," ",last_name) as text')))->where(DB::raw('concat(first_name," ",last_name)'), 'like', "%$name%")->get();
}
Notice during my select statement, I do a DB::raw and set the 'first_name' and 'last_name' fields to be selected as 'text'. I think this was one of the major issues, as the plugin requires 'id' and 'text' to function.
My route was simply:
Route::get('admin/get-contact', 'AdminContactsController#getContactByName');