31

CakePHP's FormHelper is how you generate forms when making CakePHP applications. As one might assume, this includes generating input elements, like so:

$this->Form->input('abc');

Which will produce HTML something like this:

<div class="input text">
  <label for="ModelAbc">Abc</label>
  <input name="data[Model][Abc]" class="" maxlength="250" type="text" id="ModelAbc">
</div>

Now, sadly, Bootstrap wants something like the following:

<div class="control-group">
  <label for="ModelAbc" class="control-label">Abc</label>
  <div class="controls">
    <input name="data[Model][Abc]" class="" maxlength="250" type="text" id="ModelAbc">
  </div>
</div>

How do I make CakePHP produce this output?

lericson
  • 1,318
  • 1
  • 12
  • 22
  • 3
    There are helper classes available for this kind of issues which you could expand and improve further if needed: https://github.com/slywalker/cakephp-plugin-boost_cake – Luc Franken Sep 02 '13 at 09:39

9 Answers9

35

Inspired by lericson's answer, this is my final solution for CakePHP 2.x:

<?php echo $this->Form->create('ModelName', array(
    'class' => 'form-horizontal',
    'inputDefaults' => array(
        'format' => array('before', 'label', 'between', 'input', 'error', 'after'),
        'div' => array('class' => 'control-group'),
        'label' => array('class' => 'control-label'),
        'between' => '<div class="controls">',
        'after' => '</div>',
        'error' => array('attributes' => array('wrap' => 'span', 'class' => 'help-inline')),
    )));?>
<fieldset>
<?php echo $this->Form->input('Fieldname', array(
    'label' => array('class' => 'control-label'), // the preset in Form->create() doesn't work for me
    )); ?>
</fieldset>
<?php echo $this->Form->end();?>

Which produces:

<form...>
<fieldset>
<div class="control-group required error">
    <label for="Fieldname" class="control-label">Fieldname</label>
    <div class="controls">
        <input name="data[Fieldname]" class="form-error" maxlength="255" type="text" value="" id="Fieldname"/>
        <span class="help-inline">Error message</span>
    </div>
</div>
</fieldset>
</form>

I basically added the 'format' and 'error' keys, and added the control-label class to the label element.

domsom
  • 3,163
  • 1
  • 22
  • 27
  • I want to add after my input when error occurs. How to achieve that? – RN Kushwaha Sep 14 '14 at 20:42
  • @RNKushwaha not sure I got your question correctly, but if you want to produce a custom error message for that specific situation, you add a custom validator for that. If your question is about producing a specific / modified markup, I suggest you post it as a new question and link it to this one. – domsom Sep 15 '14 at 08:25
  • Ok I'll ask a new question but often people make questions duplicate. – RN Kushwaha Sep 15 '14 at 09:41
17

Here's a solution for Bootstrap 3

<?php echo $this->Form->create('User', array(
'class' => 'form-horizontal', 
'role' => 'form',
'inputDefaults' => array(
    'format' => array('before', 'label', 'between', 'input', 'error', 'after'),
    'div' => array('class' => 'form-group'),
    'class' => array('form-control'),
    'label' => array('class' => 'col-lg-2 control-label'),
    'between' => '<div class="col-lg-3">',
    'after' => '</div>',
    'error' => array('attributes' => array('wrap' => 'span', 'class' => 'help-inline')),
))); ?>
<fieldset>
    <legend><?php echo __('Username and password'); ?></legend>
    <?php echo $this->Form->input('username'); ?>
    <?php echo $this->Form->input('password'); ?>
</fieldset>
<?php echo $this->Form->end(__('Login')); ?>

In case a field needs its own label:

<?php echo $this->Form->input('username', array('label' => array('text' => 'Your username', 'class' => 'col-lg-2 control-label'))); ?>
Shay Rojansky
  • 15,357
  • 2
  • 40
  • 69
ZuyRzuuf
  • 199
  • 2
  • 4
  • Where do you put the label? Great answer. Been so confused the past couple of days trying to figure out why the Bootstrap layouts weren't working in CakePHP. – Mark O'Sullivan Apr 03 '14 at 03:02
  • I can confirm this also works for cake 1.3, thank you! – Elaine Marley Jan 14 '15 at 11:37
  • This works for regular inputs but might not work for radios or checkboxes – ᴍᴇʜᴏᴠ Jan 01 '16 at 12:09
  • The div, before, after, between and errorMessage options have been removed from input(). You can use templates to update the wrapping HTML. The templates option allows you to override the loaded templates for one input. So this answer cannot be correct. https://book.cakephp.org/3/en/appendices/3-0-migration-guide.html#formhelper – Aris Feb 07 '22 at 13:24
11

Here's one way:

<?php echo $this->Form->create(null, array(
    'inputDefaults' => array(
        'div' => array('class' => 'control-group'),
        'label' => array('class' => 'control-label'),
        'between' => '<div class="controls">',
        'after' => '</div>',
        'class' => '')
)); ?>
lericson
  • 1,318
  • 1
  • 12
  • 22
2

Applying the same principle as above to the form->end function as follows:

<?php echo $this->Form->end(array(
    'label' => __('Submit'),
    'class' => 'btn',
    'div' => array(
        'class' => 'control-group',
        ),
    'before' => '<div class="controls">',
    'after' => '</div>'
));?>

To produce:

<div class="control-group">
  <div class="controls">
    <input class="btn" type="submit" value="Submit">
  </div>
</div>
JamesLee
  • 155
  • 7
2

Your answer is correct, but for the benefit of other users there's some other tweaks you can do to take advantage of the error/help text:

Add form-horizontal to class in the Form->create() for more compact forms (labels on the left of the input, rather than on top)

Here's how to put help text underneath a field (has to be done for each field), not forgetting to close the </div>.

echo $this->Form->input('field_name', array(
            'after'=>'<span class="help-block">This text appears 
               underneath the input.</span></div>'));

and to correctly display errors:

// cake 2.0
echo $this->Form->input('abc', array(
    'error' => array('attributes' => array('class' => 'controls help-block'))
));

Outputs:

<div class="control-group required error">
  <label for="ModelAbc" class="control-label">Abc</label>
  <div class="controls">
    <input name="data[Model][Abc]" class="" maxlength="250" type="text" id="ModelAbc">
  </div>
  <!-- error message -->
  <div class="controls help-block">This is the error validation message.</div>
  <!-- error message -->
</div>

It's extra mark-up and not as neat as bootstrap but it's a quick fix. The alternative is to do each error message individually.

and it lines up nicely. I haven't discovered an easy way to make use of inline messages yet however.

Ross
  • 18,117
  • 7
  • 44
  • 64
  • Can't the `'error' => array('attributes' => array('class' => 'controls help-block'))` code go in `inputDefaults`? From your example, it kind of looks like you're implying that it has to be done for each field. – Nick May 24 '12 at 16:22
1

small add for another comments:

if you whant add class and change label base text, you can write next

<?php echo $this->Form->input('Fieldname', array(
    'label' => array('class' => 'control-label','text'=>'HERE YOU LABEL TEXT')
)); ?>
DedMorozzz
  • 342
  • 2
  • 15
1

I had the same problem using slywalker / cakephp-plugin-boost_cake, I open a ticket and he had it fix in a few hours, he updated to 1,03 and told me to use it like this

<?php echo $this->Form->input('email', array(
    'label' => array(
        'text' => __('Email:'),
    ),
    'beforeInput' => '<div class="input-append">',
    'afterInput' => '<span class="add-on"><i class="icon-envelope"></i></span></div>'
)); ?>

I hope it helps some one else too

Alexander Vogt
  • 17,879
  • 13
  • 52
  • 68
1

To get it working with a horizontal form in bootstrap with bootswatch I had to use:

echo $this->Form->create(
    'User',
    array(
        'action'        => 'add',
        'admin'         => 'false',
        'class'         => 'form-horizontal',
        'inputDefaults' => array(
            'format'  => array( 'before', 'label', 'between',
                                'input', 'error', 'after' ),
            'class' => 'form-control',
            'div'     => array( 'class' => 'form-group' ),
            'label'   => array( 'class' => 'col-lg-2 control-label' ),
            'between' => '<div class="col-lg-10">',
            'after'   => '</div>',
            'error'   => array( 'attributes' => array( 'wrap'  => 'span',
                                                       'class' => 'text-danger' ) ),
        )
    )
);

Then you can just use it as normal:

echo $this->Form->input( 'User.username' );
Brulath
  • 11
  • 1
0

Luc Franken posted this link in his comment: http://github.com/slywalker/cakephp-plugin-boost_cake

It took me a while to notice it, so for those who are still looking for the simplest solution:

Simply add the CakePHP Bootstrap plugin from GitHub and let the helper do the job for you!

bdereta
  • 883
  • 9
  • 20