I am able add/edit/delete with a form created using Cakephp FormHelper.
But I want to use my own form without html helper. And it is a big form. In edit, I set an entity to view. I gave names to elements same as column names.
But the values are not set.
The view is in a plugin.
Can anybody please tell me how to automatically set values in a user-defined form.
I have created a form tag in the form as follows, hoping that "context" will be set and values will appear
<?php echo $this->Form->create( $company ); ?>
and also end , end of the form.
<?php echo $this->Form->end(); ?>
In between the form tags there are many html form elements.
I am posting one of them for which i have set the name same as column name
<div class="form-group panel">
<h6 for="pt-name">Former Name1</h6>
<input type="text" name="company_former_name_one" placeholder="Former Name 1" class="form-control">
</div>
My Controller Code :
public function profile( $id = null )
{
$company = $this->Companies->get( $id );
if ($this->request->is(['post','put']))
{
$post = $this->Companies->patchEntity($post, $this->request->data);
// $post->modified = date("Y-m-d H:i:s");
if( $this->Companies->save($post) )
{
}
}
$this->set('company', $company);
}
CakePHP is not magic
i cannot put the form helpers now, given the time line
The simplest and fastest way to do what you're asking is to use helpers.
I was wondering if there is any default way to set form "context" when not using form helpers
No.
For that to work would require the framework to parse the static html from the template, figure out which bits are supposed to be dynamic, apply some magic/assumptions and then dump the html. CakePHP does not work in this way.
Use helpers
Instead of static html, use appropriate helper methods. For example FormHelper::text
<div class="form-group panel">
<h6 for="pt-name">Former Name1</h6>
<?= $this->Form->text('former_name1') ?>
</div>
Which will generate something like:
<div class="form-group panel">
<h6 for="pt-name">Former Name1</h6>
<input name="former_name1" value="default" type="text">
</div>
Related
I am trying to create a very complex form with ZF2, and I can't find a solution to implement array based names in input elements.
This is a chunck of code from my actual form:
<input type=text name=table[name] value="Table Name">
<input type=text name=table[title] value="Table Title">
<input type=text name=table[columns][names][] value="Column Name 1">
<input type=text name=table[columns][names][] value="Column Name 2">
<input type=text name=table[columns][names][] value="Column Name 3">
<input type=text name=table[columns][labels][] value="Column Label 1">
<input type=text name=table[columns][labels][] value="Column Label 2">
<input type=text name=table[columns][labels][] value="Column Label 3">
I know how to work with Zend/Form, but this is an advanced usaged I can`t master.
Your code looks like a dynamic form rendered into table format. One possibility besides Zend Fieldsets is to generate your basic form structure dynamically wihtin OOP-Constructor, like #Sam said.
In your case, you should have a concept of which the form is structured. E.g. you have an array with data from a database, which gives you for example the number and names of your "columns" and so the structure how to build your dynamic form.
Following example uses Zend Form constructor to generate a dynamic form. Number of columns are dynamic and specified by given array $tableColumns
<?php
class DynamicForm extends Form {
/**
* This constructor builds a Zend Form dynamically
*
* #param array $tableColumns Dynamic data e.g. 'Column Name 1'
*/
public function __construct($tableColumns) {
// Add table name input
$this->add(array(
'type' => 'text',
'name' => 'name'
));
// Add table title input
$this->add(array(
'type' => 'text',
'name' => 'title'
));
// iterate each dynamic data
foreach($tableColumns as $column) {
$this->add(array(
'type' => 'text',
'name' => $column['name']
));
}
}
}
This is how you generate the Zend form structure. Rendering works similar, but within yout view code.
<?php
echo "<table>";
echo "<tr>";
echo "<td>". $this->formElement($form->get('name')) . "</td>";
echo "<td>". $this->formElement($form->get('title')) . "</td>";
foreach($tableColumns as $column) {
echo "<td>". $this->formElement($column) ."</td>";
}
echo "</tr>";
echo "</table>";
?>
In my opinion it is much more comfortable to render a form dynamically into a table format, than it's possible a Fieldset.
But nevertheless Zend Form Collection (e.g. Fieldsets) is a good choice, if you have to add or remove Form-elements dynamically with Javascript and handle your form data also highly dynamically.
More information about Zend From Collections are described at the ZF2 Reference Manual
You make use of Zend\Form\Element\Fieldset for this kind of scenario. It helps a great deal with proper OOP-Construction of Forms.
Is there any way of changing the validation error div structure? I want to insert an image just before the div.
Each error will be displayed inline with the input field, so I want to insert a left arrow image before the validation div.
Currently I am getting this:
<div class="input password required error">
<label for="StudentPassword1">Password</label>
<input type="password" name="data[Student][password1]" value="" id="StudentPassword1" class="form-error">
<div class="error-message">notempty</div>
</div>
I'd like:
<div class="input password required error">
<label for="StudentPassword1">Password</label>
<input type="password" name="data[Student][password1]" value="" id="StudentPassword1" class="form-error">
<img src='...' />
<div class="error-message">notempty</div>
</div>
How would you accomplish this? I'm guessing that I have to modify the core? Thanks
I'm guessing that I have to modify the core?
No. If your app requires changing Cake's core you are likely doing something wrong. Cake has a lot going on and it takes care of a lot of things for you. This happens to be one of the things you can customize to your liking.
When you create your Forms with the FormHelper you can specify default options for input() and one of those options includes the HTML structure and class used to wrap error messages.
I would just modify the CSS of the error-message class to include the image.
.error-message {
background:url( path/to/img.png ) no-repeat top left;
padding-left:40px; /* or whatever you need for the image to fit */
}
<?php echo $this->Form->create('User', array('class'=>'form-horizontal',
'inputDefaults' => array('error' => array(
'attributes' => array(
'wrap' => 'label', 'class' => 'text-error'
)
) )
)); ?>
This will make you customize the error output.
I am learning CakePHP. I am trying to develop a login system, but instead of using the login.ctp as a user/view, I wish I could use it as a element because I have the login form in many other pages. How can I declare within my users_controller that my function login() will use just the element. I said that because I used $this->render('/elements/login') and it did work. However, my element login.ctp was within my default.ctp layout, thus, I had two login forms. One was the element and the other as my content in my default.ctp layout.
Thanks!
Layouts are for the "greater" markup of a page: head and meta information, includes, "footer" stuff like your analytics. Generic content pointers go in the middle - so there's no need to mark anything as specific as a form in a layout unless you really do want to include that form on every page that uses that layout.
It sounds like you either called $this->render() in your view? $this->render() is a controller method. $this->element is the view method.
Or you called $this->element('/elements/login'); from in your login.ctp view? That would mean the controlller rendered the default login.ctp view, which called the login.ctp element.
And thus you saw two. To fix:
To return something other than the default view associated with an action (such as your login snippet), call $this->render('name/of/whatever'); as the last line of the controller method. It will return the view you specify; set will pass whatever variables to it, just like a regular view call and if you want to get fancy, specify the layout as ajax and watch the magic start like $this->render('/elements/login', 'ajax').
If you need to call several elements in a single view file, use the method $this->element('/fancy/nav/whatever'); you can also place them in layouts as appropriate (navigation, etc.)
HTH. :)
I had the same thing done to my project and this is what I did.
Basically, I created a new loginElement.ctp and placed it in the element folder. I create new sets of HTML code that would fit the layout where I wanted to use this element and the loginElement.ctp <form would then submit the data to login action in the users_controller.
If you need to and when I get home later, I can post my exact code here.
==================================== EDIT =========================================
These are the codes I used:
First of all you will notice that the action in the login form points to /login.
I have that setup in my /config/routes.php file as such
Router::connect('/login', array('controller' => 'users', 'action' => 'login'));
Then the other codes are below
/views/elements/thinlogin.ctp
<div id="login">
<form method="post" action="/login" accept-charset="utf-8" class="formBox">
<fieldset>
<input type="hidden" name="_method" value="POST" />
<div class="form-col">
<label for="username" class="lab">Username/Email</label>
<input name="data[User][username]" type="text" id="UserUsername" class="input">
</div>
<div class="form-col form-col-right">
<label for="password" class="lab">Password</label>
<input type="password" name="data[User][password]" id="UserPassword" class="input">
</div>
<div class="form-col form-col-submit">
<input name="" value="Login" class="submit" type="submit">
</div>
<div class="form-col form-col-check">
<label><input name="remember" class="checkbox" type="checkbox">Remember me on this computer</label>
</div>
</fieldset>
</form>
</div>
/views/pages/home.ctp
<div id="home_top_right_top">
<?php
if (!$this->Session->check('Auth.User.id'))
{
echo $this->element('login/thinlogin');
}else{
echo $this->element('login/loggedin');
}
?>
</div>
I am using cakePHP.
I used the cakePHP built-in Form Helper to generate an input text box:
echo $form->input('quote', array('label'=>'Post Number', 'class'=>''));
But when I looked at the HTML source code, I found out these:
<div class="input text">
<label for="ReplyQuote">Post Number</label>
<input name="data[Reply][quote]" type="text" class="" maxlength="12" value="1" id="ReplyQuote" />
</div>
It's really more than enough. I mean the code generated by the Cake built-in Form Helper.
Those DIV tags with class named in a strange naming convention way are not helpful,
because there is space in between the Class name like:
<div class="input text">
Does CakePHP have any options for users to omit those DIV Tags?
Yes.
Check out the options array that you can pass to the FormHelper::input() method. Book reference is at http://book.cakephp.org/view/189/Automagic-Form-Elements
In short, the form helper is adding two distinct classes to the div -- input, and text. If you don't want a div, just do:
echo $form->input( 'quote', array( 'label' => 'Post Number', 'div' => false ) );
Setting the options['class'] value only affects the class selector assigned to the actual input itself (see in your HTML code how the input tag has class=""?)
you can also use $form->text() for input box.
Let's say I have field that looks like this in the view:
<li class="bigfield">
<?php echo $form->input('phone', array(
'placeholder' => 'Phone',
'label' => false,
'between' => '<br />'
)); ?>
</li>
If I have a validation rule on this field and validation fails, I see the following HTML:
<li class="bigfield">
<div class="input text required error">
<br>
<input name="data[Appointment][email]" type="text" placeholder="Email"
maxlength="45" value="" id="AppointmentEmail" class="form-error">
<div class="error-message">Please enter a valid email address</div>
</div>
</li>
I'm like to do something like move the error message div to an entire different part of the page rather then have it inside with the same <li> as the field itself. What would be the most straight forward way of doing this?
Just updating an old post.
The validations errors are automatically passed on to view (as pointed out by #Angel S. Moreno)
$this->validationErrors
In you controller:
$this->set('validationErrorsArray', $this->ModelName->invalidFields());
You will have $validationErrorsArray in your views.
UPDATE (Sept. 2014):
From the view
From CakePHP 2.3 you can access validation errors array from the view:
$this->validationErrors;
From the controller
If you tried to save data in the controller you can access validation errors this way:
$this->ModelName->validationErrors;
If you want to validate data before saving do it this way:
$this->ModelName->set($this->request->data);
if ($this->ModelName->validates()) {
$this->ModelName->save();
} else {
$errors = $this->ModelName->validationErrors;
// handle errors
}
Validating Data from the Controller
From controller you can use:
$this->Modelname->validationErrors['TheFieldYouWantToDisplay'] = 'This is not correct'
In your case it would be like this in your controller:
$this->Appointment->validationErrors['email'] = 'Error message'
This code is just to make a custom error message on the fly. But you can also define $validate in the model and do it like how brancer has described it.