I'm trying to use setTemplates() multiple times in a view, but it doesn't work as expected.
I have two templates which I want to set when I need them.
$bootstrapTemplate = [
'inputContainer' => '<div class="form-group {{type}}{{required}}">{{content}}</div>',
];
$bootstrapTemplateInputGroup = [
'inputContainer' => '<div class="form-group {{type}}{{required}}">{{content}}</div>',
'input' => '<div class="input-group"><div class="input-group-addon">€</div><input type="{{type}}" name="{{name}}"{{attrs}}/></div>'
];
I start to set the templates like this
$this->Form->setTemplates($bootstrapTemplate);
$this->Form->control('title', ['class' => 'form-control', 'label' => __('Titel')]);
// OUTPUT - correct
// <div class="form-group text required"><label for="title">Titel</label><input type="text" name="title" class="form-control" required="required" maxlength="255" id="title"></div>
$this->Form->setTemplates($bootstrapTemplateInputGroup);
echo $this->Form->control('price', ['class' => 'form-control', 'id' => 'price_eur', 'label' => __('Preis EUR')]).'</div>';
// OUTPUT - correct
<div class="form-group number required"><label for="price_eur">Preis EUR</label><div class="input-group"><div class="input-group-addon">€</div><input type="number" name="price" class="form-control" id="price_eur" required="required" step="any"></div></div>
Now I want to switch back to $bootstrapTemplate which doesn't seem to work. Instead the $bootstrapTemplateInputGroup is used
$this->Form->setTemplates($bootstrapTemplate);
echo $this->Form->control('user_zip', ['class' => 'form-control', 'id' => 'user_zip', 'label' => __('PLZ')])
// OUTPUT - wrong
<div class="form-group text"><label for="user_zip">PLZ</label><div class="input-group"><div class="input-group-addon">€</div><input type="text" name="user_zip" class="form-control" id="user_zip"></div></div>
My expected output is the template of $bootstrapTemplate like:
<div class="form-group text required"><label for="user_zip">PLZ</label><input type="text" name="user_zip" class="form-control" required="required" maxlength="255" id="user_zip"></div>
What am I doing wrong here?
FormHelper::setTemplates() doesn't overwrite the complete existing set of templates, it merges it with the given templates, ie the input template set with the second call, will remain changed.
You either have to push() to (store) and pop() from (restore) the template stack using the underlying templater to avoid that:
$this->Form->templater()->push();
$this->Form->templater()->add($bootstrapTemplateInputGroup);
$this->Form->templater()->pop();
or use the FormHelper::create() method's templates option to apply the templates to the specific FormHelper::control() call(s) only:
echo $this->Form->control('title', ['templates' => $bootstrapTemplate, /*...*/]);
echo $this->Form->control('price', ['templates' => $bootstrapTemplateInputGroup, /*...*/]);
echo $this->Form->control('user_zip', ['templates' => $bootstrapTemplate, /*...*/]);
See also
Cookbook > Views > Helper > Form > Options for Control
API > \Cake\View\StringTemplate
Related
I've read CakePHP multiple checkbox array HTML the right way but getting strange results. I have a list of tags (from a Model called Tag). I want to loop through these and output checkboxes for them in a View.
So I have obtained the Tag data in my Controller with:
$tags = $this->Tag->find('list', ['order' => ['name' => 'ASC']]);
$this->set('tags',$tags);
When I loop through it in my View I am trying to output the checkboxes in between Bootstrap markup:
<?php echo $this->Form->create('GroupTag'); ?>
<?php foreach ($tags as $tag_id => $tag): ?>
<div class="checkbox">
<label>
<?php echo $this->Form->checkbox('tag_id[]', array( 'value'=> $tag_id)); ?>
<?php echo $tag; ?>
</label>
</div>
<?php endforeach; ?>
I copied the syntax for tag_id[] from the post I linked to.
But when I inspect the markup it's producing the following as the name attribute for each <input type="checkbox">:
data[GroupTag][tag_id[]]
Should this not be
data[GroupTag][tag_id][]
?
The idea is that I have multiple checkboxes with a name attribute tag_id[] and then in the Controller I can loop through what has been checked.
Please can someone advise on this as I can't get it working and have looked into examples provided on here/docs.
Try this
$this->Form->checkbox('tag_id.', array( 'value'=> $tag_id))
You can also do this:
$this->Form->input('GroupTag.tag_id', [
'type' => 'select',
'multiple' => 'checkbox',
'options' => $tag_id
]);
FormHelper::select(string $fieldName, array $options, array $attributes)
Example:
$options = array(
'Value 1' => 'Label 1',
'Value 2' => 'Label 2'
);
echo $this->Form->select('Model.field', $options, array(
'multiple' => 'checkbox'
));
Output:
<div class="input select">
<label for="ModelField">Field</label>
<input name="data[Model][field]" value="" id="ModelField"
type="hidden">
<div class="checkbox">
<input name="data[Model][field][]" value="Value 1"
id="ModelField1" type="checkbox">
<label for="ModelField1">Label 1</label>
</div>
<div class="checkbox">
<input name="data[Model][field][]" value="Value 2"
id="ModelField2" type="checkbox">
<label for="ModelField2">Label 2</label>
</div>
</div>
<div class="form-group">
<label for="inputEmail" class="col-lg-2 control-label">Title</label>
<div class="col-lg-10">
<input type="text" style="width: 45%;" class="form-control" id="titleId" name="title" placeholder="Title">
</div>
</div>
I have this type of code in my add.ctp file and I don't know how to convert it into like
<? echo $this->Html->input('title',['class'=>'']);
You have to use Form helper instead of CakePHP Html helper. Form helper helps you to create form field as well as help to validate the form. But Html helper helps you to create Html like Html for image displaying. Here we go
$this->Form->input('title', [
'label' => [
'text' => 'Title',
'class' => 'col-lg-2'
],
'style' => [
'width: 45%;'
]
]);
I would like to advise you to go to this link, have a deeper look on the docs :)
Here is the Form helper of CakePHP 3
Here is the Html helper of CakePHP 3
I have created below fields in my form-
<input type="text" id="ProductPrice1" class="small" name="data[Product][price][1]">
<input type="text" id="ProductPrice1" class="small" name="data[Product][price][2]">
<input type="text" id="ProductPrice1" class="small" name="data[Product][price][3]">
<input type="text" id="ProductPrice1" class="small" name="data[Product][price][4]">
Now I am trying to add validation for above fields by using below model function-
public function productValidates() {
$validate= array();
$validate = array(
'name'=> array(
'mustNotEmpty'=>array(
'rule' => 'notEmpty',
'message'=> __('PRODUCTS.TITLE_BLANK_ERROR',true)
)
),
'description'=> array(
'mustNotEmpty'=>array(
'rule' => 'notEmpty',
'message'=> __('PRODUCTS.DESCRIPTION_BLANK_ERROR',true)
)
),
'category_id'=> array(
'mustNotEmpty'=>array(
'rule' => 'notEmpty',
'message'=> __('PRODUCTS.SELECT_CATEGORY_ERROR',true)
)
),
);
$count = $this->data[$this->name]['total_prices'];
for($i=1; $i<= $count;$i++){
$validate['price'][$i] = array(
'1' => array(
'rule' => array('notEmpty',true),
'message' => __('PRODUCTS.PRICE_EMPTY_ERROR',true),
'last' => true
)
);
}
$this->validate = $validate;
return $this->validates();
}
But its not working.
Can you please suggest what’s the issue here?
I suppose that you are using cakephp 2.X
I think that the problem is the loop, instead of that add a custom validation method to check that the prices are not empty.
Here is the link to the book with an example.
http://book.cakephp.org/2.0/en/models/data-validation.html#adding-your-own-validation-methods
Another solution is to make a table Prices with columns id|product_id|value, put the association in the Models, put the validation criteria of the prices into the Price Model and in the ProductController put "saveAll" instead of save.
In this case your form must be like:
<input type="text" id="ProductName" class="small" name="data[Product][name]">
<input type="text" id="ProductDescription" class="small" name="data[Product][description]">
<input type="text" id="PriceValue1" class="small" name="data[Price][0][value]">
<input type="text" id="PriceValue1" class="small" name="data[Price][1][value]">
<input type="text" id="PriceValue1" class="small" name="data[Price][2][value]">
<input type="text" id="PriceValue1" class="small" name="data[Price][3][value]">
if this does not answer your question I will need more data such as the controller and the structure of your db
CakePHP usually place labels before the input, so doing this:
echo $this->Form->input('subject');
We obtain this:
<div class="input text required">
<label for="TicketSubject">Subject</label>
<input name="data[Ticket][subject]" maxlength="255" type="text" id="TicketSubject">
</div>
Is there any way to place the label after the input to obtain this?
<div class="input text required">
<input name="data[Ticket][subject]" maxlength="255" type="text" id="TicketSubject">
<label for="TicketSubject">Subject</label>
</div>
Thanks.
The proper way is using the the 'format' option.
$this->Form->input('subject', array(
'format' => array('before', 'input', 'between', 'label', 'after', 'error')
));
Didn't anyone read the API :)
You can try this:
echo $this->Form->input('subject', array('label' => false, 'after' => $this->Form->label('Subject:')));
You can do like this also -
echo $this->Form->input('subject', array('label' => false, 'after' => '<label for="subject">Subject</label>'));
i am trying to create a Radio button using Cakephp like the one the result should resemble like
<div data-attr="radio" id="1">
<label id="label1">Untitled1</label><br/>
<input type="radio" value="option1" id="Radio11" name="Workexperience"/>
<label for="Radio11">Option1</label>
<input type="radio" value="option2" id="Radio12" name="Workexperience"/>
<label for="Radio12">Option2</label>
</div>
how to generate so using Form helper..
Please suggest me..
This might help,
http://book.cakephp.org/view/189/Automagic-Form-Elements#options-before-options-between-options-separator-a-191
For radio type input the 'separator' attribute can be used to inject markup to separate each input/label pair.
Code View
<?php echo $form->input('field', array(
'before' => '--before--',
'after' => '--after--',
'between' => '--between---',
'separator' => '--separator--',
'options' => array('1', '2'),
'type' => 'radio'
));?>
Output:
<div class="input">
--before--
<input name="data[User][field]" type="radio" value="1" id="UserField1" />
<label for="UserField1">1</label>
--separator--
<input name="data[User][field]" type="radio" value="2" id="UserField2" />
<label for="UserField2">2</label>
--between---
--after--
</div>
Looks like $form->radio() should do what you need. I don't know if it will look exactly like your example.