Joomla 2.5 - component development - using form - forms

I am trying to add some form to my component, but I am not shure what naming conventions must be applied to work it correctly.
Currently I have a working form - it displays fields stored in XML file and loads data from database to it. However, when i try to submit this form (edit or add new records), it doesn't work. After pressing submit (save() method) it just redirects me and displays that record was edited successfuly but it wasn't. When I try to edit existing record, after pressing submit nothing happens and when I try to add new record, it just adds empty/blank record.
So I was doing a little debug and discovered, that problem is in the JController::checkEditId() method. It always returns false which means that JControllerForm::save() returns false as well and that's why it doesn't save it correctly. HTML code of form is correct and I can access the data by using global array $_POST.
I suspect that this problem is because of naming conventions in methods loadFormData, getForm of JModelAdmin class. I am not sure how to name that form.
So here is my code related to this problem:
Subcontroller for displaying the form - controllers/slideshowform.php
class SlideshowModelSlideshowForm extends JModelAdmin{
public function getForm($data = array(), $loadData = true){
return $this->loadForm('com_slideshow.slideshowform', 'editform', array('load_data' => $loadData, 'control' => 'jform'));
}
protected function loadFormData(){
$data = JFactory::getApplication()->getUserState('com_slideshow.edit.slideshowform.data', array());
if (empty($data))
{
$data = $this->getItem();
}
return $data;
}
public function getTable($table = "biometricslideshow"){
return parent::getTable($table);
}
}
views/slideshowform/view.html.php
class SlideshowViewSlideshowForm extends JView{
public function display($tmpl = null){
if (count($errors = $this->get('Errors')))
{
JError::raiseError(500, implode('<br />', $errors));
return false;
}
$this->form = $this->get('form');
$this->item = $this->get('item');
JToolBarHelper::save('slideshowform.save');
parent::display();
}
}
views/slideshowform/tmpl/default.php
<?php
defined('_JEXEC') or die('Restricted access');
JHtml::_('behavior.tooltip');
?>
<form method="post" action="<?php echo JRoute::_("index.php?option=com_slideshow&id=".(int) $this->item->id)?>" name="adminForm" id="slideshow-form">
<fieldset class="adminform">
<legend>Edit slide</legend>
<table>
<input type="hidden" name="task" value="">
<?php echo JHtml::_('form.token'); ?>
<?php
foreach($this->form->getFieldset() as $field){
?>
<tr><td><?php echo $field->label ?></td><td><?php echo $field->input ?></td></tr>
<?php
}
?>
</table>
</fieldset>
</form>
Can someone take o look, please?

you have to add controller SlideshowControllerSlideshowForm and code save method. In there you have to validate the form data and call SlideshowModelSlideshowForm->save event, then redirect with success/failure message.

Related

codeigniter, form validation false verse first time visit

In Codeigniter, the following code is typically used for a page that has a form. But the first time a user lands on the page and a form validation fails gets routed through the same path.
As this example shows, the flash data will trigger. even if the user just land on the page and have not submit any form yet.
I am trying to echo a new class name to some input field to highlight them if validation fails. but currently it highlights the field on first load as well.
I am aware I can echo a validation_error or form_error. is there a way to echo a generic message that is not tied to a field-name and only after submission fails
// rules and other stuff above
if ($this->form_validation->run() == FALSE){
$this->session->set_flashdata('errorClass',"is-invalid");
$this->load->view('defaultOrFalse');
}else{
$this->load->view('success');
}
//view file
<input class=" <?php $this->session->flashdata('errorClass') ; ?>">
Basically I am trying to get bootstrap 4's input validation to show up
https://getbootstrap.com/docs/4.0/components/forms/#server-side
I don't know your exact setup but you can do logic like the following:
<?php
class Some_controller extends CI_Controller {
// controller/search/{$term}
public function some_method($term = null) {
// where some_field is some field in your form
// that gets posted on submit
if ($this->input->post('some_field')) {
// or if (isset($_POST)) {
if ($this->form_validation->run() == FALSE) {
$this->session->set_flashdata('errorClass', "is-invalid");
$this->load->view('defaultOrFalse');
} else {
$this->load->view('success');
}
} else {
// default view
}
}
}
?>
For your second question:
<h5>Username</h5>
<?php echo form_error('username'); ?>
<input type="text" name="username" value="<?php echo set_value('username'); ?>" size="50" <?php if (!empty(form_error('username'))) { echo "class='error'"; } ?> />
Can also make a helper and use instead of form_error to check if field has error for your class (haven't verified this works but it should).
/**
* Checks if form validation field by name
* has error
*
* #param string $field Name of field
* #return boolean
*/
function field_has_error($field) {
$CI = &get_instance();
$CI->load->library('form_validation');
$arr = $CI->form_validation->error_array();
if (isset($arr[$field])) {
return true;
}
return false;
}
Usage:
<?php if (field_has_error('username')) { echo "class='error'"; } ?> />

laravel 4 changing url structure with parameter passing

I'm just a beginner in laravel framework. i created a simple form and controller methods . i think by default the form method is post. but now i need to make it as get method and also wants to pass the selected inputs to controller and shows that parameters in the url also. currently i did like below but failed.
index.blade.php
<?php echo Form::open(array('url' => 'home/find','method' => 'get')); ?>
<select class="location" id="location" name='location'>
<?php
$id1 = /* get user db details based on locations*/
$location_id_drop_down='';
foreach($idl as $lrow)
{
$city_name=Location::where('location_id','=',$lrow['loc_id'])->first();
if($city_name==array()) continue;
if(Input::old('location')==$lrow['loc_id'])
{
$location_id_drop_down.="<option value='" . $city_name['location_name'] . "' selected='selected'>" .$city_name['location_name'] . "</option>";
}
else
{
$location_id_drop_down.="<option value='" . $city_name['location_name'] . "'>" . $city_name['location_name']. "</option>";
}
}
echo $location_id_drop_down;
?>
</select>
<input type="submit" name="search" id="search_submit" class="search_submit" value="Search" />
{{ Form::close() }}
HomeController.php
public function anyFind($s='',$d='',$l='') {
if(Input::get('search'))
{
$location=Input::get('location');
}
else
{
if($l!='~')
$location=$l;
}
/* queries to get the user details and images based on selected location and list them*/
}
Routes.php
Route::get('/find/{location}','HomeController#anySearch');
But this shows the url as mysite.com/home/find?location=Test&search=Search
I need mysite.com/home/find/location
is there any mistake in my code?
Edit
As a part of experiment i tried this method. i gave a redirect like below at the end of my controller function anyfind()
return Redirect::to('/home/find/'.$location);
But this redirects me but did anyone knows how to load the search.search_new.blade.php with this custom url??
Having a field from the form in your url (not query string) is simply not possible with Laravel. What you can do though, is just use javascript for that.
First lets put a placeholder in the action url
<?php echo Form::open(array('url' => 'home/find/%location%','method' => 'get')); ?>
jQuery
$('form').on('submit', function(){ // you maybe need to be a bit more precise with the selector here
var location = $('#location').val();
$(this).prop('action', $(this).prop('action').replace('%location%', location));
});
Vanilla Javascript (if you can't / don't want to use jQuery)
document.getElementsByTagName('form')[0].onsubmit = function(e){
var location = document.getElementById('location').value;
e.target.setAttribute('action', e.target.getAttribute('action').replace('%location%', location));
};
By the way: the code in your question has still some weird stuff in there. I'm just assuming this has happened because of copy paste etc. So if it still doesn't work, make sure you post the correct code
Insert at the end of your method anyFind() inside the HomeController.php where you set the view for the page:
if (Input::get('location') != '') {
return Redirect::route('home.findByLocation',Input::get('location'));
}
return View::make('home', compact('location));
Also in your routes.php add the following code:
Route::get('home/find/{location?}', array('as'=>'home.findByLocation', 'uses'=>'HomeController#anyFind'));

CodeIgniter form_open() action not working correctly

I have have a view in which there's a form that manages products (either add new product or -if an id passed- editing an existing one). If an id is passed then the form action should be eg 'admin/product/manage/5', if no id passed then it should be like this 'admin/product/manage'.
<?php echo form_open('admin/product/manage/{optional product id}', array('class' => 'ajax-form')); ?>
I have also created and this route:
$route['admin/product/manage'] = "admin/product/manage";
$route['admin/product/manage/(:num)'] = "admin/product/manage/$1";
How can I make my form action work correctly? is it possible to put inside the action the route somehow??
This is my Controller:
public function manage($id = NULL){
//fetch a single product to edit or create a new one
if (isset($id) === true) {
$data['prod'] = $this->product_model->get($id);
$data['vers'] = $this->product_version_model->get_by('product_id',$id);
} else {
$data['prod'] = $this->product_model->make_new();// this returns $product->product_name = ''; in order to be empty the input field and not throughing errors
}
$this->product_model->save_product();
$this->product_version_model->save_version();
// load the view
$this->layout->view('admin/products/manage', $data);
}
This is my view:
<?php echo form_open('admin/product/manage', array('class' => 'ajax-form')); ?>
<p>
<label for="product_name">Product *</label>
<input type="text" name="product_name" value="<?php echo set_value('product_name', $prod->product_name); ?>" />
<?php echo form_error('product_name'); ?>
</p>
<?php echo form_close() . PHP_EOL; ?>
You need to declare both possible routes in order of importance, so:
$route['admin/product'] = "admin/product/manage";
$route['admin/product/(:num)'] = "admin/product/manage/$1";
From the Codeigniter Docs:
Routes will run in the order they are defined. Higher routes will always take precedence over lower ones.
Edit:
According to the changes you have made to your question I can say the following:
First of all isset() returns boolean only, so you don't need the type check "=== true". isset($id) is sufficient.
In order to have your form action set to the id you need to include it either in a hidden field or in the action itself.
So for example:
$action_id = (isset($id) ? '/'.$id : ''); // Using ternary operators here
echo form_open('admin/product/manage'.$action_id, array('class' => 'ajax-form'));
and add the id to the view data in your controller:
$data['id'] = $id;
As a side note: In order to comply with SoC (Separation of Concerns) you'd prepare all data in your controller (with e.g. models all having their own task) and pass the processed data to the view instead of partially generating data in the view itself.

Why is CakePHP 2.3.0 adding a '1' to my Form Post Values?

I'm using cakephp 2.3.0. I searched in the manual for quite awhile, but I haven't found the answer. Also, I've searched the Internet, but still haven't found what I'm looking for. SO, I'm posting my question here. Note, I'm fairly new to cakephp.
Scenario:
I have a simple form with two fields: activity and zip code.
I'm using POST on the form.
When I type in some value in those fields and submit, I echo those 'post' values/parameters and display in the browser screen. What I typed in, I can see on the screen, but the number '1' is added to the end of what I typed in the form.
Here is an example. I type in these values in the form, 'walk' and '44555'. Then I click 'Submit'. The post goes to my controller's action, which then calls my view. My view is displayed on the browser screen and I echo out those 'post' values. The results on screen are 'walk1' and '445551'.
Example #2: If I follow the steps above and don't enter any values in my form (I'll add error checking later), what I see on the browser screen is '1' and '1'.
I am unable to figure out why I am getting the value of '1' added to my form's POST values?
I'll be glad to include any other additional php code to this posting, if requested by someone trying to help.
Here is my FORM code (from my view)...I know there are DIV helpers, but I'll get to that later:
echo $this->Form->create(null, array('url' => array('controller'=>'activities', 'action'=>'results'))); ?>
<div class="box1" style="position:relative; top:10px; left:10px; float: left;">
Search here.... <br>
<hr>
<?php echo $this->Form->input('activityName', array('size'=>'30',
'label'=>'Activity Name:', 'value'=>'i.e. walking, etc.'));?>
<br>
<?php echo $this->Form->input('zip', array('size'=>'7', 'label'=>'Postal Code:')); ?>
<br>
</div>
<div class="box1" align="right">
<?php echo $this->Form->end('Go Search');?>
</div>
Here is my controller code:
<?php
class ActivitiesController extends AppController {
public $helpers = array('Html', 'Form');
public function index() {
//other code....
}
public function results() {
$this->layout = 'second';
$name = $this->request->data['Activity']['activityName'];
$pCode = $this->request->data['Activity']['zip'];
$this->set('theName', $name);
$this->set('theZip', $pCode);
$this->set('results', $this->Activity->
find('all', array('conditions' => array('name' => $name, 'postal_code' => $pCode))));
$this->set('title_for_layout', 'Results');
$this->render();
}
}
?>
My final view code. I left off some of the code...just showing the part that matters:
<div style="position:relative; top:10px; left:5px; ">
<?php echo print_r($theName); ?>
<br>
<?php echo print_r($theZip); ?>
Thanks
The 1 comes from printing the return value of print_r() which is true (i.e. 1).
In other words: you shouldn't do echo print_r(), just do print_r(). The function handles the printing by itself, you don't have to print the results manually.
(Also, print_r() is almost never the best choice to print out values except when debugging and even then CakePHP's debug() is much more suitable.)

calling echo $this->action('panLogin','user') and $this->action('panRegister','user') on same script

I have a problem, i'm trying to render 2 forms (login and register) on one layout scrpt (header.phtml), every time i submit on one of the forms both actions for the controller are getting fired and i'm unsure how to fix it.
The forms are getting rendered fine within the layout, however when you click 'Login' or 'Register' on the forms the code fires in both the 'login' and 'register actions.
the header layout script snippet:-
<div class="left">
<h1>Already a member? <br>Then Login!</h1>
<?php
echo $this->action('panlogin', 'user');
?>
</div>
<div class="left right">
<h1>Not a member yet? <br>Get Registered!</h1>
<?php
echo $this->action('panregister', 'user');
?>
</div>
the action scripts (phtmls)
panregister.phtml
<div id="pan-register">
<?php
$this->registerForm->setAction($this->url);
echo $this->registerForm;
?>
</div>
panlogin.phtml
<div id="pan-login">
<?php
$this->loginForm->setAction($this->url);
?>
</div>
the user controller actions:-
class Ajfit_UserController extends Zend_Controller_Action
{
protected $_loginForm;
protected $_registerForm;
public function init()
{
$this->_loginForm = new Ajfit_Form_User_Login(array(
'action' => '/user/login',
'method' => 'post',
));
$this->_registerForm = new \Ajfit\Form\User\Registration(array(
'action' => '/user/register',
'method' => 'post'
));
}
//REGISTER ACTIONS
public function panregisterAction(){
$this->registerAction();
}
public function registerAction(){
$request = $this->_request;
if ($this->_request->isPost()){
$formData = $this->_request->getPost();
}
$this->view->registerForm = $this->_registerForm;
}
//LOGIN ACTIONS
public function panloginAction(){
$this->loginAction();
}
public function loginAction(){
$request = $this->_request;
if(!$auth->hasIdentity()){
if ($this->_request->isPost()){
$formData = $this->_request->getPost();
}
}
$this->view->loginForm = $this->_loginForm;
}
}
Please can someone with a little more knowlegde with the action('act','cont'); ?> code with in a layout script help me out with this problem.
Thanks
Andrew
While David is correct where best practices are concerned, I have on occasion just added another if() statement. Kinda like this:
if ($this->getRequest()->isPost()) {
if ($this->getRequest()->getPost('submit') == 'OK') {
just make sure your submit label is unique.
Eventually I'll get around to refactoring all those actions I built early in the learning process, for now though, they work.
Now to be nosy :)
I noticed: $formData = $this->_request->getPost(); while this works, if you put any filters on your forms retrieving the data in this manner bypasses your filters. To retrieve filtered values use $formData = $this->getValues();
from the ZF manual
The Request Object
GET and POST Data
Be cautious when accessing data from the request object as it is not filtered in any way. The router and
dispatcher validate and filter data for use with their tasks, but
leave the data untouched in the request object.
From Zend_Form Quickstart
Assuming your validations have passed, you can now fetch the filtered
values:
$values = $form->getValues();
Don't render the actions in your layout. Just render the forms:
<div class="left">
<h1>Already a member? <br>Then Login!</h1>
<?php
echo new \Ajfit\Form\User\Login(array(
'action' => '/user/login',
'method' => 'post'
));
?>
</div>
<div class="left right">
<h1>Not a member yet? <br>Get Registered!</h1>
<?php
echo new \Ajfit\Form\User\Registration(array(
'action' => '/user/register',
'method' => 'post'
));
?>
</div>
Then, whichever form gets used will post to its own action.