First, I've successfully implemented a Multiple Select box with option groups based on providing an providing a group of options structured like this:
$options = [
'Group 1' => [
'Value 1' => 'Label 1',
'Value 2' => 'Label 2'
],
'Group 2' => [
'Value 3' => 'Label 3'
]
];
echo $this->Form->select('field', $options);
This is straight from the Cookbook at: http://book.cakephp.org/3.0/en/views/helpers/form.html#creating-select-pickers
It works great, and makes a select box exactly as it should. My issue is that I would like to change the display to be multiple checkboxes. In order to do that, I've switched the code to:
echo $this->Form->input('field', [
'multiple' => 'checkbox',
'options' => $options
]);
When I do this, the display ends up being a single checkbox, with all the options listed out next to it.
In searching stackoverflow, I found the following: How to create multiple checkboxes grouped by fieldsets in Cakephp 3
Most seem to indicate that the functionality is not included in Cake, and that you need to build it on your own. There is one comment on the initial question that references the cookbook and that it specifically states:
If you would like to generate a select with optgroups, just pass data in hierarchical format. This works on multiple checkboxes and radio buttons too, but instead of optgroups wraps elements in fieldsets:
No one seems to address the comment on that question. My question is really simple. Does CakePHP 3 allow for multiple checkboxes created as outlined in the documentation, or is the documentation incorrect and this functionality isn't included in the core? If the answer is that the functionality is included in the core, what's the trick to getting it to work?
Thanks!
in that multi select checkbox
<?= $this->Form->select('input_name',$checkboxarray, array('selected' =>$send_checkbox_select,'multiple' => 'checkbox')); ?>
$checkboxarray=[
'Value 1' => 'Label 1',
'Value 2' => 'Label 2'
`],
Related
I have a fairly simple query that generates a different SQL statement, with regard to the contained fields, depending on whether or not I specify fields to select. I know that is very confusing, so I will try to describe the problem with code.
I have the following associations set up, and they work fine with a simple find(), but not when I try to use find()->select.
CollectionsTable:
$this->belongsTo('IconMedia', [
'foreignKey' => 'icon_media_id',
'className' => 'Media'
]);
$this->belongsTo('HeroMedia', [
'foreignKey' => 'hero_media_id',
'className' => 'Media'
]);
MediaTable:
$this->hasMany('CollectionsIconMedia', [
'foreignKey' => 'icon_media_id',
'className' => 'Collections'
]);
$this->hasMany('CollectionsHeroMedia', [
'foreignKey' => 'hero_media_id',
'className' => 'Collections'
]);
The full, simple version of the query, which returns all fields, including the fields for the associated tables HeroMedia and IconMedia.
$this->Collections->find()
->contain(['Participations', 'HeroMedia', 'IconMedia']);
generates
SELECT Collections.id AS `Collections__id`,
Collections.name AS `Collections__name`,
Collections.slug AS `Collections__slug`,
Collections.description AS `Collections__description`,
Collections.icon_media_id AS `Collections__icon_media_id`,
Collections.hero_media_id AS `Collections__hero_media_id`,
Collections.user_id AS `Collections__user_id`,
Collections.created AS `Collections__created`,
Collections.modified AS `Collections__modified`,
HeroMedia.id AS `HeroMedia__id`,
HeroMedia.file AS `HeroMedia__file`,
HeroMedia.description AS `HeroMedia__description`,
HeroMedia.caption AS `HeroMedia__caption`,
HeroMedia.source AS `HeroMedia__source`,
IconMedia.id AS `IconMedia__id`,
IconMedia.file AS `IconMedia__file`,
IconMedia.description AS `IconMedia__description`,
IconMedia.caption AS `IconMedia__caption`,
IconMedia.source AS `IconMedia__source`
FROM collections Collections
LEFT JOIN media HeroMedia ON HeroMedia.id = (Collections.hero_media_id)
LEFT JOIN media IconMedia ON IconMedia.id = (Collections.icon_media_id)
This is exactly what I expect. However, I would like to limit the selected fields returned from the collection table. I tried the following statement:
$this->Collections->find()
->select( [ 'id', 'name', 'slug', 'description', 'icon_media_id', 'hero_media_id' ] )
->contain(['Participations', 'HeroMedia', 'IconMedia']);
This unfortunately generates the following SQL. Notice that the JOINs are still present, but the SELECTs for IconMedia and HeroMedia are gone.
SELECT Collections.id AS `Collections__id`,
Collections.name AS `Collections__name`,
Collections.slug AS `Collections__slug`,
Collections.description AS `Collections__description`,
Collections.icon_media_id AS `Collections__icon_media_id`,
Collections.hero_media_id AS `Collections__hero_media_id`
FROM collections Collections
LEFT JOIN media HeroMedia ON HeroMedia.id = (Collections.hero_media_id)
LEFT JOIN media IconMedia ON IconMedia.id = (Collections.icon_media_id)
Maybe there is a problem with the virtual tables HeroMedia and IconMedia (not sure of the proper CakePHP name for them), but they seem to work properly for the simple find() without ->select. I've tried reading through the Query Builder and Associations Docs, but haven't found anything to explain this phenomenon.
You need to use Table::aliasField() on all your fields.
->contain([
$this->aliasField('name'),
'OtherTable.field',
'YetAnotherTable.field'
]);
Selecting All Fields From a Table
Passing Conditions to Contain Check the 2nd half of this section
See enableAutoFields()
I created a hasMany association between a Projects & Comments tables.
From this url : /projects/add, the user can create a new project and write several comments.
The request return an array like this :
[
'name' => 'Project name',
'comments' => [
(int) 0 => [
'text' => 'This is a comment on this project'
],
(int) 1 => [
'text' => 'Comment'
]
]
]
In the validator comments, I added a minLength 30 rules.
In the example above, the validator will return an error on the second comment and block recording.
What I want is to save the project and the good comments, and return an error like this : " The project has been saved, But one or more comment was not saved ".
Thank you for your help !
This answer shows one way to do what you're looking for. Try the save and unbind the hasMany relationship if there are validation errors with the associated model.
I think it would be cleaner to just split the save calls though.
if (!$this->Project->save($this->request->data['Project'])) {
throw new Exception($this->Project->getErrors());
}
if (!$this->Project->Comment->save($this->request->data['Comment'])) {
$message = 'The project has been saved, But one or more comment was not saved';
}
I would like to add an aggregating option ("All options" in the example) to a dropdown filter in grid, that covers all other options, and looks like this:
All options
Option1
Option2
Option3
...
I have tried this way:
grid:
'filter' => ['All options', yii\helpers\ArrayHelper::map(app\models\RelatedModel::find()->all(), 'id', 'name'),]
ModelSearch:
if ($this->RelatedModelId == 'All options') {
$query->andFilterWhere(['in', 'RelatedModelId', \yii\helpers\ArrayHelper::getColumn(RelatedModel::find()->all(), 'id')]);
} else {
$query->andFilterWhere(['RelatedModelId' => $this->RelatedModelId ,]);
};
It works (maybe not the most beautiful solution of the world, but it's okay for me at the moment). The only thing that's disturbing me, is this 0 (or 1 sometimes, depending on how I change code) in the dropdown list:
All options
0
Option1
Option2
Option3
...
And I know it's because of the brackets [] in filter ('filter' => [...]), but at the moment this is the only way I could achieve the functionality I need. I have no idea how to make it work witout the brackets. Is there a simple way (to put an additional tiny little option somwhow, somewhere maybe) not to show this 0 or do I have to do it completely different? It's not really a big problem that is looks like this, but would be better not to see it. Or can I put this All into the map function?
'filter' => yii\helpers\ArrayHelper::map(array_merge(['All options', app\models\RelatedModel::find()->all()]), 'id', 'name'),
I've also tried array_merge() but without a success.
Any ideas? Thanks in advance!
This:
'filter' => \yii\helpers\ArrayHelper::map(\app\models\RelatedModel::find()->all(), 'id', 'name'),
will already render empty option (with no text) for resetting choice in this drop-down list.
For search just set:
$this->andWhere(['your_field_id' => $this->your_field_id]);
in your search model and you ready to go.
Also don't forget to add this attribute as safe attribute in rules section:
public function rules()
{
return [
['your_field_id', 'safe'],
],
}
You can see an example in CRUD generator.
If you want to customize shown text, append prompt option to existing yii\grid\DataColum $filterInputOptions:
'filterInputOptions' => ['class' => 'form-control', 'id' => null, 'prompt' => 'All'],
Also by putting this in view you are violating MVC principle:
\yii\helpers\ArrayHelper::map(\app\models\RelatedModel::find()->all(), 'id', 'name'),
Either call this in a controller and pass as parameter to view or wrap in some getList() method.
I am using drupal 7 and need a form that provides a select box with optgroups and allows the user to select multiple items.
I can create the #options array along with optgroup by using
array(
['Option Group 1']=>array(
[1]=>'First Item',
[2]=>'Second Item',
),
['Option Group 2']=>array(
[3]=>'Third Item',
),
);
but if I then set
'#multiple'=>TRUE
I just get a select full of checkboxes with array() as the list item title
If I set
'#attributes'=>array('multiple'=>'multiple')
The form looks correct but drupal does not recognise any of my selections and sends me back to the form saying I need to select an option from the list.
I cannot get the values to auto check. The list of options displays fine.
$this->data['Business']['ExpertiseType'] has values.
Business habtm ExpertiseType defined in all three models still set to their default bake.
Business belongsTo FormEoiEntry
$this->data = $this->FormEoiEntry->find('first', ['conditions'=>['FormEoiEntry.id'=>1324], 'recursive'=>2]);
$this->Form->create('FormEoiEntry');
$this->Form->input('Business.ExpertiseType', ['multiple'=>'checkbox']);
$this->Form->end();
Am I missing something here? I cannot figure out why it is not being detected and checking the boxes.
set expertise_types from your controller like this.
$this->set('expertise_types', $this->FormEoiEntry->find('first', [
'conditions'=>['FormEoiEntry.id'=>1324],
'recursive'=>2,
]);
and in your view
$this->Form->input('Business.ExpertiseType', [
'options' => $expertise_types,
'multiple'=>'checkbox'
]);
update
In that case pass the selected options values to the $this->request->data['Business']['ExpertiseType']
just like this
$this->request->data['Business']['ExpertiseType'] = array(
'select option value 1', // you can put your option values
'select option value 2',
'select option value 3',
'select option value 4',
);