Cakephp2 - Creating Form from loop - php

I have translates table with example data:
So, this table holds records, which will represent custom translation texts.
Now i want to build a form to edit all of those rows in one page / form.
This is controlle code:
public function translate() {
$this->loadModel('Translate');
$data = $this->Translate->find('all');
$this->set('data', $data);
pr ($this->request->data);
if ($this->request->is('post','put')) {
if ($this->Translate->save($this->request->data)) {
$this->Session->setFlash('Recipe Saved!');
return $this->redirect($this->referer());
}
}
}
And view - please note, that i have used loop for creating inputs, not sure if cakephp has better way to do this.
<?php echo $this->Form->create('Translate'); ?>
<?php
foreach ($data as $d) {
echo $this->Form->input('text', array('label' => 'Link strony', 'type' => 'text','value'=>$d['Translate']['text']));
echo $this->Form->input('id', array('type' => 'hidden', 'value' => $d['Translate']['id']));
}
?>
<?php echo $this->Form->end(array('class' => 'btn btn-success floatRight', 'label' => 'Zapisz')); ?>
For now, this code works, but not as i expect. $this->request->data shows only last input, ignoring other ones. Attached, you see debug of $this->request->data. Only last item is edited. All i want is to have ability to edit selected input and save. Thanks for help.

Looks like you're saving multiple rows in a single form. In that case,
you need to change your approach a bit.
Use proper indices in the Form helper.
Use saveAll() instead of save() to save multiple data.
Changes to the View file:
<?php
foreach ($data as $k => $d) {
echo $this->Form->input('Translate.'.$k.'.text', array(
'label' => 'Link strony',
'type' => 'text',
'value' =>$d['Translate']['text']
));
echo $this->Form->input('Translate.'.$k.'.id', array(
'type' => 'hidden',
'value' => $d['Translate']['id']
));
}
?>
And then, in your controller:
if ($this->request->is('post','put')) {
$this->Translate->saveAll($this->request->data['Translate']);
/* Other code */
}

Try to specify the name as array (translate[]) :
echo $this->Form->input('text', array('label' => 'Link strony', 'type' => 'text','value'=>$d['Translate']['text'],'name'=>'translate[]'));

Related

Generate controls for pivot table

I would like to iterate and edit data from a pivot table in edit.ctp.
Displaying and editing one entity works fine with the code below (if there is at least one entry):
edit.ctp
echo $this->Form->control('winkels.0._joinData.winkel_id', [
'options' => $winkels,
'label' => 'Winkel',
'type' => 'select'
]);
echo $this->Form->control('winkels.0._joinData.url');
echo $this->Form->control('winkels.0._joinData.prijs');
I could get the depth of the array and change the index of winkels, but that's just dirty... I am not even sure if that would work.
So I tried the code below but it does not create the right HTML:
if(!empty($product->winkels)) {
foreach ($product->winkels as $winkel) {
echo $this->Form->control($winkel->_joinData->winkel_id, [
'options' => $winkels,
'label' => 'Winkel',
'type' => 'select'
]);
echo $this->Form->control($winkel->_joinData->url, [
'label' => 'URL',
'value' => $winkel->_joinData->url
]);
echo $this->Form->control($winkel->_joinData->prijs, [
'label' => 'Prijs',
'value' => $winkel->_joinData->prijs
]);
}
}
Is there a clean way the generate these controls for the pivot table? Also if $product->winkels is empty, how do I make the first entry?
Additional info:
--- EDIT ---
I have adjusted my code, but I seems that it fails to create the "pivoting table"
if(!empty($product->winkels)) {
foreach ($product->winkels as $index => $winkel) {
echo $this->Form->control('winkels.$index.winkel_id');
echo $this->Form->control('winkels.$index._joinData.winkel_id', [
'options' => $winkels,
'label' => 'Winkel',
'type' => 'select'
]);
echo $this->Form->control('winkels.$index.url', [
'value' => $winkel->_joinData->url]
);
echo $this->Form->control('winkels.$index.prijs', [
'value' => $winkel->_joinData->prijs]
);
}
} else {
echo $this->Form->control('winkels.0.winkel_id');
echo $this->Form->control('winkels.0._joinData.winkel_id', [
'options' => $winkels,
'label' => 'Winkel',
'type' => 'select'
]);
echo $this->Form->control('winkels.0._joinData.url');
echo $this->Form->control('winkels.0._joinData.prijs');
}
As you can see in the debug result, a lot of the structure is missing:
There's nothing dirty about using the array's index, that's actually exactly how you'd do it, ie something along the lines of:
foreach ($product->winkels as $index => $winkel) {
echo $this->Form->control("winkels.$index.id");
echo $this->Form->control("winkels.$index._joinData.winkel_id", [/* ... */]);
echo $this->Form->control("winkels.$index._joinData.url", [/* ... */]);
echo $this->Form->control("winkels.$index._joinData.prijs", [/* ... */]);
}
Also don't forget the primary key if you want to update existing records! And note that you don't need to provide the value, the form helper will find the value itself based on the given field name.
And if winkels is empty, then you simply start with the index 0, just like in your first example.
See also
Cookbook > Views > Helpers > Form > Creating Inputs for Associated Data

Unable to retain values in form after unsuccessful submission of form in codeigniter

I am creating a form in codeigniter where user needs to fill data and submit it, but after submission of form if there are any errors the user gets redirected back to the form, however at this stage the values that he had entered should stay in the form.
I am getting the flashdata error but the values are not getting retained in the form. I tried to use set_value but just getting blank form in return. Can any one please point out the error
View
<?php echo form_open_multipart('student/data/'.$student->id); ?>
<p><?php echo $this->session->flashdata('req_msg'); ?></p>
<?php
$data = array(
'type' => 'text',
'name' => 'name',
'placeholder' => 'Full Name',
'class' => 'form-control',
'id' => 'form-first-name',
'value' => set_value('name')
);
?>
<?php echo form_input($data); ?>
<?php
$data = array(
'type'=>'tel',
'pattern'=>'^\d{10}$',
'name' => 'contactno',
'placeholder' => 'Enter 10 digit Contact No',
'class' => ' form-control',
'required' => 'required',
'id' => 'form-first-name',
'value' => set_value('contactno')
);
?>
<?php echo form_input($data); ?>
<div class="form-group">
<?php
$data = array(
'type' => 'submit',
'class' => 'btn btn-primary',
'name' => 'submit',
'content' => 'Upload',
'id' => 'btn-submit'
);
echo form_button($data);
?>
</div>
<?php echo form_close(); ?>
Controller
$this->form_validation->set_rules('contactno', 'Contact Number', 'trim|is_unique[student.contactno]');
if ($this->form_validation->run() == FALSE)
{
$this->session->set_flashdata('req_msg', 'Contact number already exists');
redirect('student/data/'.$studentid);
}
Your view file's code is absolutely correct. You only need to few modifications in your controller's method.
There few key points you need to know before implementing solution in your code:
Redirect only when your validation rules passes successfully and your motive behind taking user's input is done
When your validation rules does not pass then load your view instead redirecting it
Put form_error(FIELD_NAME) along with each input to show validation error
Below is the example of action:
public function add()
{
$this->form_validation->set_rules('contactno', 'Contact Number', 'trim|is_unique[student.contactno]');
if ($this->form_validation->run() !== FALSE) {
// Your database or model function calling will be coded here and make sure it returns boolean value
if ($isTrue) {
$this->session->set_flashdata('req_msg', 'Congrats! You have successfully submitted data');
redirect('student/data/'.$studentid);
}else{
// Handle error logs here
}
}
$this->load->view('your_view', $this->view_data);
}
This is the complete solution. I am sure you will get all the values set in form field in case of validation rule fails.
Let me know if you face any issue.
The problem is caused because you redirect after FALSE form_validation. You must load the view there like below :
if ($this->form_validation->run() == FALSE) {
//your code
$this->load->view('your_view', $this->view_data);
}
In your view you have to use set_value() in your inputs.
More info # documentation

View Sending an Action to a Controller and returning a query

I'm kinda noob yet using cakephp, but I would love to know how to use it, for that, I'm trying to develop something pretty simple.
I have a form, that has an input type = 'text' and I wanna search in my database what I just type in this input.
How can I do that ?
I know that I have to get what is inside of my input text and execute a function in my controller that will receive a parameter and execute the query and return the same query to my view.
Other thing that I couldn't do it yet is this:
<button type="submit" class="btn"><i class="icon-search"></i></button>
I wanna change this to cake format, like:
echo $this->Form->input('button', array('class' => 'btn', type = 'submit'));
but no idea how to add the icon.
Thanks.
You can specify the button text like.
<?php
echo $this->Form->button(
"<i class='icon-search'></i>",
array(
'class' => 'btn',
'type' => 'submit',
'escape' => false
)); // make sure you've use escap = false with html input.
?>
and for the search you can define the action like this.
<?php
public function search() {
$conditions = array();
$params = $this->passedArgs;
if(isset($params['text_field_name']) && !empty($params['text_field_name'])){
$conditions['ModelName.text_field_name like'] = $params['text_field_name'].'%';
}
$this->Paginate->settings = array(
'conditions' => $conditions
);
$this->set('variable_name', $this->Paginator->paginate());
}
?>
you can also use this for searching
---- in your .ctp file
<?php echo $this->Form->create('ModelName'); ?>
<?php echo $this->Form->input('ModelName.search_word'); ?>
<?php echo $this->Form->submit(" <i class='icon-search'></i> " , array('escape' => false , 'class' => 'btn' ) ); ?>
<?php echo $this->Form->end(); ?> // note that no params for end() method
---- in your controller file
$searchWord = $this->request->data['ModelName']['search_word'] ;
$this->paginate = array('limit' => 30 ,
'conditions' => array('OR' => array('ModelName.field1' => "%".$searchWord."%" ,
'ModelName.field2 LIKE' => "%".$searchWord."%" )));
$this->set('searchResults', $this->paginate());

Yii Dropdown List Empty Value as Default

I have a dropdownlist in my _form model and I want to add a empty value (which I want as default). I have the following:
In _form:
<?php echo $form->labelEx($model,'country_id'); ?>
<?php echo $form->dropDownList($model,'country_id',Country::items(),array('empty' => '--Select a country--')); ?>
<?php echo $form->error($model,'country_id'); ?>
In Model Country:
public static function items()
{
return CHtml::listData(Country::model()->findAllBySql(
'SELECT * from country'),
'id', 'name');
}
Even my empty option is in the first row in dropdownlist, the 1st country in list shows as default.
I tried:
<?php echo $form->dropDownList($model,'country_id',
Country::items(),array('empty'=>'--Select a country--',
'options'=>
array(
'3'=>array('selected'=>'selected')
)
));
?>
In this way I can choose the default option, but cant set it to empty value, just countries that came from model:items.
Any idea?
Are you sure that country_id property of your model is not set to anything when you print the dropdown list? The following works for me if $model instance is created using new Country() operator but not by populating properties from database:
<?php echo $form->dropDownList(
$model,
'country_id',
Country::items(),
array(
'empty'=>'--Select a country--')
);
?>
Read documentation. There is 'prompt' parameter.
Try this:
<?php
echo $form->dropDownList($model,'country_id',Country::items(), array(
'prompt' => '--Select a country--'
));
?>
See more details here http://www.yiiframework.com/forum/index.php/topic/11195-how-to-edit-the-default-option-in-dropdownlist/
You always can do something like array_merge in your items method
public static function items()
{
return array_merge(array(''=>'--Select a country--'), CHtml::listData(Country::model()->findAllBySql(
'SELECT * from country'),
'id', 'name'));
}
I believe youre looking for:
echo $form->dropDownList($model,'country_id',Country::items(),array('prompt'=>''));
if you use yiibooster maybe this will help
<?php echo $form->dropDownListGroup(
$model,
'kode_cuti_sub2',
array(
'empty'=>'--Select a country--',
'widgetOptions' => array(
'data' => array('Something ...', 'Pilih Jenis Cuti'=>Chtml::listData(Cuti::model()->cuti_sub2(),'kode','jenis_cuti')),
'options' => array(
'placeholder' => 'Pilih NIP Pegawai',
'width' => '100%',
),
),
'wrapperHtmlOptions' => array(
'class' => 'col-sm-5',
),
)
); ?>
in my case it's worked

Add class attribute to Form Errors

I´m developing an application using Zend Framework 2 and I use FormRow helper to render a label, the input and errors (if present) in a Form.
//within the view
echo $this->formRow($form->get('Name'));
When a user submits the form without filling the required input text field FormRow render´s it with the following error message:
<label>
<span>Name: </span>
<input class="input-error" type="text" value="" placeholder="Insert Name Here" name="Name">
</label>
<ul>
<li>Value is required and can't be empty</li>
</ul>
How can I set a class for the li tag to style it afterwards?
I know that I can echo the formElementErrors with the desired class attribute via..
<?php echo $this->formElementErrors($form->get("Name"), array('class' => "valuerequired", 'message' => "errortestmessage")); ?>
..but FormRow will still render the error message without the class.
Just for reference I´m setting the entity this way:
public function getInputFilter()
{
if (!$this->inputFilter) {
$inputFilter = new InputFilter();
$factory = new InputFactory();
$inputFilter->add($factory->createInput(array(
'name' => 'Name',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 100,
),
),
),
)));
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
See the code of formElementErrors
Basically you could do something like:
$this->formElementErrors($elem)
->setMessageOpenFormat('<ul%s><li class="some-class">')
->setMessageSeparatorString('</li><li class="some-class">');
But that is quite unhandy...
The better solution would be to extend the Zend\Form\View\Helper\FormElementErrors by your own class and then register the view-helper formElementErrors to your class. So basically you'd have something like this:
namespace Mymodule\Form\View\Helper;
use Zend\Form\View\Helper\FormElementErrors as OriginalFormElementErrors;
class FormElementErrors extends OriginalFormElementErrors
{
protected $messageCloseString = '</li></ul>';
protected $messageOpenFormat = '<ul%s><li class="some-class">';
protected $messageSeparatorString = '</li><li class="some-class">';
}
Last thing then would be to register the view helper with this new Class. For this you provide the following code inside your Modules Module.php
public function getViewHelperConfig()
{
return array(
'invokables' => array(
'formelementerrors' => 'Mymodule\Form\View\Helper\FormElementErrors'
),
);
}
displaimer: This code isn't tested, let me know if there are some errors, but i think this should work out quite well.
Ok, the solution to my own problem was right in front of me, instead of using:
//within the view
echo $this->formRow($form->get('Name'));
I called each element of the form individually:
//within the view
echo $this->formLabel($form->get('Name'));
echo $this->formInput($form->get('Name'));
echo $this->formElementErrors($form->get("Name"), array('class' => "some_class", 'message' => "errormessage"));
Don´t know if it´s the most efficient way of doing it, plz drop a line if you think otherwise.
FormRow check if "form_element_errors" plugin registered. And if so use it as default to display error messages.
So Sam's example work. You should redefine standard plugin and inform mvc about it.
I'v done it in module.config.php
'view_helpers' => array(
'invokables' => array(
'formElementErrors'=> 'MyModule\View\Helper\FormElementErrors',
and FormRow start display errors as I wish :)
As your problem, please try
Change
//within the view
echo $this->formRow($form->get('Name'));
to
//within the view
echo $this->formRow($form->get('Name'),null,false);
// Note: add more 2 last parameters, false- for $renderErrors => will NOT render Errors Message.
//Look original function in helper/formrow.php: function __invoke(ElementInterface $element = null, $labelPosition = null, $renderErrors = null, $partial = null)
Render Errors Message as your funciton
echo $this->formElementErrors($form->get('name'), array('class' => 'your-class-here'));
From the documentation of ZF2. Here's the link: http://framework.zend.com/manual/2.0/en/modules/zend.form.view.helpers.html#formelementerrors
echo $this->formElementErrors($element, array('class' => 'help-inline'));
// <ul class="help-inline"><li>Value is required and can't be empty</li></ul>
I use echo $this->formElementErrors($form, array('class' => "error-messages")); to show all error messages in one place:
echo $this->formElementErrors($form, array('class' => "error-messages"));// Print all error messagess
echo $this->formLabel($form->get('Name'));
echo $this->formInput($form->get('Name'));
echo $this->formLabel($form->get('Name2'));
echo $this->formInput($form->get('Name2'));

Categories