I'd like to display errors on my form, highlighting the fields which have errors, and displaying the error text next to the field. If there's no elegant way to display next to each field, above would be fine.
I've found examples from earlier versions, but the API has seemed to change and they do not work for 3.2.
It's just a project I'm learning Kohana with, so it's not critical. I just want to know the "kohana" way of handling this problem.
In my controller, I have this:
if (isset($_POST) && Valid::not_empty($_POST))
{
$post = Validation::factory($_POST)
->rule('zipcode', 'not_empty'));
if ($post->check()) {
$errors = $post->errors('zipcode');
}
}
$this->template->content = View::factory('myview', $data)
->bind('errors', $errors);
And here is my form in 'myview.php':
<?php echo Form::open(); ?>
<dl>
<dt><?php echo Form::label('zipcode', 'Zip Code') ?></dt>
<dd><?php echo Form::input('zipcode') ?></dd>
</dl>
<p><?php echo Form::submit(NULL, 'Get Records'); ?></p>
<?php echo Form::close(); ?>
I've taken the approach of extending the Form helper class to add an 'error' class name on the form fields, as well as showing the error message in the field label.
<?php defined('SYSPATH') or die('No direct script access.');
class Form extends Kohana_Form {
private static function attributes($name, & $attributes = NULL, $errors = NULL)
{
// Set the id attribute
if (!isset($attributes['id']))
{
$attributes['id'] = $name;
}
if ($errors !== NULL)
{
// Merge in external validation errors.
$errors = array_merge($errors, (isset($errors['_external']) ? $errors['_external'] : array()));
// Set the error classname
if (isset($errors[$name]))
{
$attributes['class'] = trim( (string) #$attributes['class'].' error-field');
}
}
}
public static function input($name, $value = NULL, array $attributes = NULL, array $errors = NULL)
{
static::attributes($name, $attributes, $errors);
return parent::input($name, $value, $attributes);
}
public static function select($name, array $options = NULL, $selected = NULL, array $attributes = NULL, array $errors = NULL)
{
static::attributes($name, $attributes, $errors);
return parent::select($name, $options, $selected, $attributes);
}
public static function password($name, $value = NULL, array $attributes = NULL, array $errors = NULL)
{
static::attributes($name, $attributes, $errors);
return parent::password($name, $value, $attributes);
}
public static function textarea($name, $body = '', array $attributes = NULL, $double_encode = TRUE, array $errors = NULL)
{
static::attributes($name, $attributes, $errors);
return parent::textarea($name, $body, $attributes, $double_encode);
}
public static function file($name, array $attributes = NULL, array $errors = NULL)
{
static::attributes($name, $attributes, $errors);
return parent::file($name, $attributes);
}
public static function label($input, $text = NULL, array $attributes = NULL, array $errors = NULL, $view = 'messages/label_error')
{
if ($errors !== NULL)
{
// Merge in external validation errors.
$errors = array_merge($errors, (isset($errors['_external']) ? $errors['_external'] : array()));
// Use the label_error view to append an error message to the label
if (isset($errors[$input]))
{
$text .= View::factory($view)->bind('error', $errors[$input]);
}
}
return parent::label($input, $text, $attributes);
}
}
You then pass in the $errors array into the label and field helper methods:
<?php echo
Form::label('username', 'Username', NULL, $errors),
Form::input('username', $user->username, NULL, $errors);
?>
This idea was suggested on the Kohana forums but I've struggled to find the original thread. Anyway, I've found this approach works best for me.
[edit] View an example of this approach in action here: http://kohana3.badsyntax.co/contact (submit the form)
This is some sample code I have used for a personal experiment with Kohana forms. It is part of a contact form. This should work for you.
The code below shows a contact form. After a user submits the form, it gives feedback (failed + errors / succeed).
if (isset($errors) && count($errors) > 0)
{
echo '<ul>';
foreach ($errors as $error)
{
echo '<li>' . $error . '</li>';
}
echo '</ul>';
}
// form
echo Form::open(null);
// fields
echo Form::label('firstname') . Form::input('firstname', null, array('id' => 'firstname')) . '<br />';
echo Form::label('email') . Form::input('email', null, array('id' => 'email')) . '<br />';
echo Form::label('message') . Form::textarea('message', '', array('id' => 'message')) . '<br />';
// submit
echo Form::submit('submit', 'Send message');
echo Form::close();
In the controller, I validate the form and assign the error- and success messages to the view.
public function action_index()
{
// make view
$view = View::factory('pages/contact')
->bind('post', $post)
->bind('errors', $errors)
->bind('success', $success);
// check if form is submitted
if ($_POST)
{
// trim fields
$post = array_map('trim', $_POST);
$post = Validation::factory($_POST)
->rules('firstname', array(
array('not_empty'),
array('min_length', array(':value', '2'))
))
->rules('email', array(
array('not_empty'),
array('email')
))
->rule('message', 'not_empty');
if ($post->check())
{
$success[] = 'Thank you for your message!';
}
else
{
$errors = $post->errors('contact');
}
}
// view
$this->response->body($view);
}
I hope this helps!
Related
i am trying to customize laravel pagination to fix this issue:
{
"current_page": 2,
"data": {
"10": {},
"11": {},
}
i want the result to be like this:
{
"current_page": 1,
"data": [
{},
{},
}
when i use the whole collection it works good, but if get part of the collection using (where), this issue appear for me.
this coming script of code has been used in the AppServiceProvider boot method:
Collection::macro('paginate', function($perPage, $total = null, $page = null, $pageName = 'page') {
$page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);
return new LengthAwarePaginator(
$this->forPage($page, $perPage),
$total ?: $this->count(),
$perPage,
$page,
[
'path' => LengthAwarePaginator::resolveCurrentPath(),
'pageName' => $pageName,
]
);
});
i found the solution for my issue by replacing this code:
Collection::macro('paginate', function($perPage, $total = null, $page = null, $pageName = 'page') {
$page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);
return new LengthAwarePaginator(
$this->forPage($page, $perPage),
$total ?: $this->count(),
$perPage,
$page,
[
'path' => LengthAwarePaginator::resolveCurrentPath(),
'pageName' => $pageName,
]
);
});
with this one:
if (!Collection::hasMacro('paginate')) {
Collection::macro('paginate', function ($perPage = 15, $page = null, $options = []) {
$page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
return (new LengthAwarePaginator( $this->forPage($page, $perPage)->values()->all(), $this->count(), $perPage, $page, $options))->withPath('');
});
}
AppServiceProvider boot method.
After search the search result is displayed in the screen. That content I must download as excel.
Controller.php
public function searchList(Request $request)
{
$fleet_issues = FleetIssue::all();
$list = FleetIssue::orderBy('check_at', 'desc');
$directory = FleetManagementHelper :: getFleetIssueImageDirectory();
$fleet_issue_type = FleetIssueType::all();
$vehicle_class = VehicleClass::orderBy('id', 'asc')->get();
$location= Location::orderBy('id', 'asc')->get();
if( $request->plate_number){
$list = $list->where('plate_number', $request->plate_number );
}
if( $request->branch){
$list = $location->where('id', $request->branch );
}
if( $request->nric){
$list = $list->where('nric',$request->nric);
}
if( $request->fleet_issue_type_id){
$list = $list->where('fleet_issue_type_id',$request->fleet_issue_type_id);
}
$list = $list->paginate(20);
view('pages.control_panel.view_issues',compact('list','fleet_issues','directory','fleet_issue_type','vehicle_class','location'));
}
Below is to download the excel file from the Export.php
public function downloadExcel()
{
return Excel::download(new Export,'List.xlsx');
}
Below is the Export.php..How can i filter search here??
Export.php
Use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\FromView;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Events\AfterSheet;
class Export implements FromView,ShouldAutoSize,WithHeadings, WithEvents
{
public function headings(): array
{
return [
'Reservation Number', 'NRIC/Passport', 'Vehicle Model','Branch','Date of Checking','Issues'
];
}
public function view() : View
{
$vehicle_class = VehicleClass::orderBy('id', 'asc')->get();
$location= Location::orderBy('id', 'asc')->get();
$fleet_issue_type = FleetIssueType::orderBy('id', 'asc')->get();
$list = FleetIssue::orderBy('check_at', 'desc')->paginate(20);
$directory = FleetManagementHelper :: getFleetIssueImageDirectory();
if( $this->vehicle_model){
$list = $list->where('vehicle_model', $this->vehicle_model);
}
return view('pages.control_panel.fleet_management.fleet_issues.list_fleet_issues',compact('vehicle_class','location','fleet_issue_type','list','directory'));
}
How can i export my result from search to excel?How i can filter the searchlist in Export??How to passing current request variable in export like doing in the controller?
How to add my custom validate in shopware shipping address in confirm order page .once if success that process to confirm order. Please explain how to do this.
Can't you just add additional field to address while address creation?
public static function getSubscribedEvents()
{
return array(
'Shopware_Form_Builder' => ['onFormBuild', 1000]
);
}
public function onFormBuild(\Enlight_Event_EventArgs $event)
{
if (
( $event->getReference() !== \Shopware\Bundle\AccountBundle\Form\Account\PersonalFormType::class &&
$event->getReference() !== \Shopware\Bundle\AccountBundle\Form\Account\AddressFormType::class )
) {
return;
}
/** #var \Symfony\Component\Form\Form $builder */
$builder = $event->getBuilder();
$builder->get('additional')
->add('yourFieldName', \Symfony\Component\Form\Extension\Core\Type\TextType::class, [
'constraints' => [
new NotBlank()
]
]);
}
If no, then you should subscribe to checkout postdispatch and check what you want:
public static function getSubscribedEvents()
{
return array(
'Enlight_Controller_Action_PreDispatch_Frontend_Checkout' => 'onFrontendPreDispatchCheckout',
);
}
/**
* #param \Enlight_Controller_ActionEventArgs $args
*/
public function onFrontendPreDispatchCheckout(\Enlight_Controller_ActionEventArgs $args)
{
/**#var $subject \Shopware_Controllers_Frontend_Checkout */
$subject = $args->getSubject();
$request = $subject->Request();
$response = $subject->Response();
$action = $request->getActionName();
$view = $subject->View();
if (!$request->isDispatched() || $response->isException() ||
// only in case action is payment or confirm we should chcek it
($action != 'payment' && $action != 'confirm') ||
!$view->hasTemplate()
) {
return;
}
$validation = $this->thereWeCheckIt();
if (
$validation['message']
) {
$subject->forward('index', 'account', 'frontend', array(
'errorVariable' => $validation['message'],
));
}
}
Then you need also postDispatch account controller and show errorVariable to customer.
im developing a custom joomla 2.5 component integrating jqGrid.
im setting up a controller task to handle (update mysql record) data sent from jqGrid postData
var grid = jQuery(\"#list\");
grid.jqGrid({
onSelectRow: function(id){
$('#list').editRow(id, true);
},
url: '/index.php?option=com_nutraidev&view=products&format=raw',
datatype: 'json',
mtype: 'GET',
colNames: [...],
rowNum: 25,
rowList: [5, 10, 20, 50],
height: 'auto',
pager: '#pager',
loadonce: true,
sortname: 'ID',
viewrecords: true,
direction:'RTL',
autowidth: true,
sortorder: \"desc\",
caption: 'abc',
width: '70%',
editurl:'/index.php?option=com_nutraidev&view=products&task=Products.save&token=". JUtility::getToken() ."=1',
postData: {'code':\" \",....},
.....
this is the url which makes the request
/index.php?option=com_nutraidev&view=products&task=Products.save&token=". JUtility::getToken() ."=1&format=raw
im getting:
error 500
Invalid controller: name='products', format='raw'
tried it from the browser with the actual token - same result.
here is the important part of my code:
com_nutraidev
- controllers
- products.php
require_once JPATH_COMPONENT.'/controller.php';
class NutraidevControllerProducts extends NutraidevController
{
public function &getModel($name = 'Products', $prefix = 'NutraidevModel')
{
$model = parent::getModel($name, $prefix, array('ignore_request' => true));
return $model;
}
public function save()
{
// Check for request forgeries.
JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
// Initialise variables.
$app = JFactory::getApplication();
$model = $this->getModel('Products', 'NutraidevModel');
$data = JRequest::get('get');
// Attempt to save the data.
$return = $model->updItem($data);
}
}
com_nutraidev
- models
- products.php
jimport('joomla.application.component.modellist');
class NutraidevModelProducts extends JModelList {
public function __construct($config = array()) {
parent::__construct($config);
}
public function updItem($data)
{
// set the variables from the passed data
$code = $data['code'];
$name = $data['name'];
// set the data into a query to update the record
$db = $this->getDbo();
$query = $db->getQuery(true);
$query->clear();
$query->update(' #__product ');
$query->set(' name = '.$db->Quote($name) );
$query->where(' code = ' . (int) $code );
$db->setQuery((string)$query);
if (!$db->query()) {
JError::raiseError(500, $db->getErrorMsg());
return false;
} else {
return true;
}
}
}
com_nutraidev
- views
- products
- view.raw.php
jimport('joomla.application.component.view');
class NutraidevViewProducts extends JView
{
/**
* Display the view
*/
public function display($tpl = null)
{
$app = JFactory::getApplication();
$document = JFactory::getDocument();
// Get data from the model
$items = $this->get('Items');
$this->state = $this->get('State');
$this->params = $app->getParams('com_nutraidev');
// Check for errors.
if (count($errors = $this->get('Errors'))) {;
throw new Exception(implode("\n", $errors));
}
// Assign data to the view
$response->page = 1;//JRequest::getVar('page');
$response->total = 1;//JRequest::getVar('total');
$response->records = count($items);
$i=0;
for ($i = 0; $i < count($items); ++$i) {
$response->rows[$i]['id'] = intval($items[$i]->code); //id
$response->rows[$i]['cell'] = array($items[$i]->code,
$items[$i]->name
);
}
echo json_encode($response);
jexit();
}
public function save($tpl = null)
{
echo "test";
jexit();
}
}
looking at other questions that had the similar issue i double checked my
administrator/components/nutraidev/nutraidev.xml
and made sure
<files folder="site">
<filename>controller.php</filename>
was there.
what could be the reason im getting this error ? i tried it also with view.json.php
and got the same result. thanks
I have a problem with my CakePhp Site.
My index is showing fine with pagination, but when I search the page, pagination is gone and the search results aren't showing (instead the index is showing without paging).
Any idea where my code is wrong?
class ItemsController extends AppController {
var $name = 'Items';
// load any helpers used in the views
var $helpers = array('Paginator', 'Html', 'Form', 'Javascript', 'Misc', 'Time', 'Tagcloud');
var $components = array('RequestHandler');
/**
* index()
* main index page for items
* url: /items/index
*/
function index() {
// get all options for form
$tags = $this->Item->Tag->find('list', array(
'fields'=>'id, name',
'order'=>'Tag.name',
'conditions'=> array(
'Tag.status'=>'1'
)
));
// add name to option
$tags = array(''=>'Tags') + $tags;
//pr($tags);
// if form submitted
if (!empty($this->data)) {
// if reset button pressed redirect to index page
if(isset($this->data['reset'])) {
$this->redirect(array('action'=>'index'));
}
// init
$url = '';
// remove search key if not set
if($this->data['search'] == '') {
unset($this->data['search']);
}
// loop through filters
foreach($this->data as $key=>$filter) {
// ignore submit button
if($key != 'filter') {
// init
$selected = '';
switch($key) {
case 'tag':
$selected = $tags[$filter];
break;
case 'search':
$selected = $filter;
break;
}
// if filter value is not empty
if(!empty($filter)) {
$selected = $this->slug($selected);
$url .= "/$key/$selected";
}
}
}
// redirect
$this->redirect('/items/index/'.$url);
} else {
// set form options
$this->data['tag'] = '';
$this->data['search'] = '';
}
// if any parameters have been passed
if(!empty($this->params['pass'])) {
// only select active items
$conditions = array('Item.status'=>1);
// get params
$params = $this->params['pass'];
// loop
foreach($params as $key=>$param) {
// get the filter value
if(isset($params[$key+1])) {
$value = $params[$key+1];
}
// switch on param
switch($param)
{
case 'tag':
// get tag
$tag = $this->Item->Tag->find('first', array(
'recursive' => 0,
'conditions' => array(
'Tag.slug'=>$value
)
));
// save value for form
$this->data['tag'] = $tag['Tag']['id'];
break;
case 'search':
// setup like clause
$conditions['Item.name LIKE'] = "%{$value}%";
// save search string for form
$this->data['search'] = str_replace('_', ' ', $value);
break;
}
}
//pr($conditions);
// get all items with param conditions
$items = $this->Item->find('all', array(
'order' => 'Item.name',
'conditions' => $conditions
));
// if tag filter has been set
if(isset($tag)) {
// loop through items
foreach($items as $key=>$item) {
// init
$found = FALSE;
// loop through tags
foreach($item['Tag'] as $k=>$g) {
// if the tag id matches the filter tag no need to continue
if($g['id'] == $tag['Tag']['id']) {
$found = TRUE;
break;
}
}
// if the tag was not found in items
if(!$found) {
// remove from list
unset($items[$key]);
}
}
}
} else {
// get all items from database where status = 1, order by name
$items = $this->Item->find('all', array(
'order' => 'Item.name',
'conditions' => array(
'Item.status'=>1
)
));
}
$this->paginate = array(
'limit' => 10
);
$data = $this->paginate('Item');
// set page title
$this->pageTitle = 'Index Page';
// set layout file
$this->layout = 'index';
// save the items in a variable for the view
$this->set(compact('data', 'tags', 'items'));
}
You'll want to pass your search conditions to the paginate functionality. You do this through the controller's paginate property.
function index() {
...
switch($param) {
...
case 'search':
$this->paginate['conditions']['Item.name LIKE'] = "%{$value}%";
More information on setting up pagination can be found here.