FormHelper - Pre-populated select drop-down - CakePHP - cakephp

If I have:
// Controller
$this->Model->id = $id;
$this->request->data['Model'] = $this->Model->read();
And then:
// View (input field)
$this->Form->input('some_field'); // THE FORM FIELD WILL BE PRE-POPULATED
But if I want it to be a select box instead:
// View (with select)
$this->Form->select('some_field', $options); // THE SELECT BOX ISN'T PRE-POPULATED
Questions then:
a. Why isn't the select-box pre-populated like the input field is?
b. Do I really have to manually pre-populate like this?
// View (with select)
$this->Form->select('some_field', $options, array('value' => $this->request->data['Model']['some_field'])); // THE SELECT BOX IS PRE-POPULATED
c. Is the above method the most efficient method of pre-populating select boxes which already has a value?

no, some_field would be prepoluated by your passed form data if you would do it correctly.
did you debug what you produced there? a multi-level array which is not cake standard.
the correct approach would be:
$this->request->data = $this->Model->read();
since the array already contains the Model key (which debug() would have shown!).
but careful to do this only if not posted!
to your last question, no, if possible, use the controller or at least default. value would make your form lose the previously selected value if validation fails.
my old cake1.3 post might also shed some light on it: http://www.dereuromark.de/2010/06/23/working-with-forms/

Related

checkboxes for table records

I want to let user to publish or unpublish some articles at once. So, in articles list view, I want to put a checkbox beside each row (article) and send these checkboxes to controller.
I tried to use $this->Form->input('status') after each row in my loop, but it created same checkbox for each article. (inputs name and id are the same)
How to create an array of checkboxes or something like this? And how to check them in controller?
Note: Each article has a status field, which is a tinyint 1 character field. (so Cake can understand it's a checkbox)
You will need to specify an 'index' for each input.
In stead of this:
$this->Form->input('Article.status');
Use this:
$this->Form->input('Article.0.id');
$this->Form->input('Article.0.status');
$this->Form->input('Article.1.id');
$this->Form->input('Article.1.status');
// ....
$this->Form->input('Article.xxx.id');
$this->Form->input('Article.xxx.status');
It's the 'index' is just a counter to make sure that 'unique' inputs are generated. However, it is important that each row contains an input for the id of that row; CakePHP will need that to determin which record it should update the status for.
Further reading
Documentation on the naming of fields/inputs can be found here:
FormHelper field naming conventions
CakePHP - Create a form which edits multiple rows of the same model

Convert a text box to dropdown box from Add view

Can you help me figure this out please? I have 4 form elements on my add view (app\views\tickets\add.ctp) but the 'status' input is on a text box. I want that to be converted to drop down box populated with data from a field in a table called Status. How do I go about doing it?
echo $this->Form->input('problemno');
echo $this->Form->input('status');
echo $this->Form->input('description');
echo $this->Form->input('user_id');
Thanks,
Lyman
If you want to force the type of input field, do not use the input() method, but use the method for the type you want.
To get a drop down list, you can use the select() method:
$options = array('status1' => 'status1', 'status2' => 'status2', ...);
$this->Form->select('status', $options);
See http://book.cakephp.org/view/1430/select
If the model associated with your 'Status' table is related to you current model ('Ticket', presumably) with a hasMany,hasOne, or belongsTo (...as long as your 'Status' model shows up when you debug $this->Ticket->read(null, <some_ticket_id>)) you can do
echo $this->Form->input('StatusModel.field')
and cake will automagic that field to be whatever it needs to be.
You will have to search around for how to make cakePHP give you a dropdown selection based on database field.
This is not exactly a correct way. It might be good, or you might find changing it later on to be a problem. But if you just want to create a dropdown with some options, here you go:
echo $this->Form->input('status', array('options'=>array('status1'=>'status1','status2'=>'status2','status3'=>'status3')));

Getting related data using Wizard Component

The short version of this question is:
How can I take data that only exists in an array (ie: not saved in a model yet) and relate it to a value in a $this->find('list') array from a model?
The long version of this question is:
I'm using CakePHP and the Wizard Component for a 3-step application form.
The 3 form steps are contact, course and details.
After these steps, there is a 'review' step which I want to display all of the submissions from the previous 3 form steps for the user to check one last time before pressing submit. For the most part, this works very well. I just need to do the following in the controller:
function _prepareReview() {
$contact = $this->Wizard->read('contact');
$course = $this->Wizard->read('course');
$details = $this->Wizard->read('details');
$this->set(compact('contact','course','details'));
}
Then, in review.ctp I can reference things like $contact['Contact']['firstname']; to get the person's firstname etc.
However, the problem is getting data from 'related' models. For example, there's a "Nationality" field which is just an ID. In the 'details' step, I use find('list') to get a list of all nationalities from the Nationality model as a dropdown menu which displays properly and then Cake saves the corresponding ID as it should do.
But, when I come to the 'review' step in the Wizard Component, I only get the actual ID from the Wizard Component's array. I couldn't really expect to get anything else.
I can't see any obvious way to access $details[Detail][Nationality][name] (or something like this) from the context of the Wizard Component because setting recursive doesn't work because the data isn't actually in the model at this stage, it's just an array of form data.
So, in other words, I have data in an array (NOT coming from a model, but from a form subsmission) as follows:
Array
(
[Details] => Array
(
[firstname] => Test
[nationality_id] => 3
)
)
Then I have the following coming from a $this->Detail->Nationality->find('list') which looks like this:
Array
(
[0] => American
[1] => Australian
[2] => British
[3] => Canadian
)
So how can I get $details['Details']['nationality_id']; from the Wizard Component to display 'Canadian' instead of '3' for example? How to I make the relationship when only one of the arrays is coming from a model? I only need this to momentarily confirm all of the data to the user. The id '3' will, of course, be written to the Model once the user presses submit, and this is already working as it should do.
Or is this a completely crazy way of doing things and I should look at a totally different approach such as saving the data first? I don't really want to save it until the user clicks the final submit, though.
I can see what you are getting at here - CakePHP isn't automatically querying these related models for you (as you aren't pulling from the database) but you can't help but think you are missing out on some of the framework's free functionality.
If you were still using FormHelper::input() it would automatically select the correct option (given you perform a Model::find('list') and passed the options list to the view first), but I'm assuming you wish for the review screen to be free of form inputs (disabled or not).
The most straightforward approach would be to simply perform the same Model::find('list') calls you do for each step in the wizard, set the data from each to the view, and print out the appropriate value manually:
// controller
$nationalities = $this->Review->Details->Nationality->find('list');
$this->set(compact(/*..., */ 'nationalities'));
// view
<?php echo $nationalities['Nationality'][$details['Detail']['nationality_id']]; ?>
outputs 'Canadian' (the value for $nationalities['Nationality'][3])
It might be possible to get CakePHP to do it for you by calling DboSource::queryAssociation() just right - if your up for the challenge - but is probably overkill for this particular problem.
// model
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$data = $db->queryAssociation($model, $linkModel, $type, $association, $assocData, $queryData, $external, $resultSet, $recursive, $stack) {

cakephp habtm relationships with input rather than select box?

I'm creating a form in cakephp that has a typical HABTM relationship. Let's say that I'm developing an order form with a coupon code. From a logic point of view, I need to accept a text-entry for the coupon code, so the incoming data would not be the proper primary key, but rather a different field.
I would then need to validate that data, and retrieve the proper primary key id, and then update the orders_coupons table with that coupon_id, and order_id.
When using a select box the value would always be the proper coupon_id, but where is the appropriate location for me to put the logic to handle this? Should I modify the data using beforeSave?
your question isn't very clear b/c it sounds like you can both specify the coupon via a select box or in just a free form text box.
My inclination is to add a new method to the Model that would update the record with the "human readable key". So the function would first read the coupon_id from the DB, and then do the update.
As you said, you'll just have to look up the coupon id...
// assuming $data looks like:
// array('Order' => array(...), 'Coupon' => array('code' => ...))
$coupon_id = $this->Order->Coupon->field('id', array('code' => $data['Coupon']['code']));
if (!$coupon_id) {
// user put in a non-existing coupon code, punish him!
} else {
$data['Order']['coupon_id'] = $coupon_id;
$this->Order->save($data);
}
If I get this correct, this is pretty much the same as tagging?! (There is a text input box for habtm items and the string is submitted to the controller without the ids).
If so, I would recommend to split the processing. Submit the data to the controller and then pass the coupon-string to a proper function in the coupon-model, that gets the coupon-ids (saves new items) and returns them back to the controller to save the complete habtm-data.

How do I add a 'Choose One' option to a combobox selector and then validate it in CakePHP?

I am a Cake PHP novice.
I want to edit the table "Issue". This table contains a field "priority_id" related to another table called "Priority" by an foreign key. This table contains three values "Severe", "Disaster", "ToDo". User can select the priority using a combobox (input select).
The priorities are loaded like this:
$priorities = $this->Issue->Priority->find('list');
This works for me.
I need to add a fourth option to the combobox called "Choose". This value will be a default one. The user cannot submit the form when this value is selected. The motivation is to force the user to select one of the meaningful values instead of submitting the first one randomly.
1) How can I fill the array $priorities ?
2) How can i validate the form?
Thanks
In the issues/add.ctp and issues/edit.ctp views, add an empty key to the options array sent as the 2nd param to the $form->input() method, e.g.
echo $form->input('priority_id', array('empty' => 'Choose'));
This will add an option at the top of the combo box with text 'Choose' and the value of the option will be an empty string.
The in your Issue model, you can add a validation for the priority_id field, e.g.
var $validate = array(
'priority_id' => array('numeric')
);

Resources