Displaying search results on a separate page - php

I have a SilverStripe site with some code to display a search form. The for allows you to search for something based on 3 things. Problem is, I'm not sure how to get the results to display correctly on a separate page.
My code:
class InstitutionSearchPage extends Page {
}
class InstitutionSearchPage_Controller extends Page_Controller {
private static $allowed_actions = array(
'Search'
);
public function Form() {
$fields = new FieldList(array(
DropdownField::create('DegreeType', 'Degree', QualificationType::get()->filter('ParentID', 0)->map()),
DropdownField::create('Course', 'Course', Qualification::get()->map()),
DropdownField::create('City', 'City', City::get()->map()),
));
$actions = new FieldList(array(
FormAction::create('Search')->setTitle('Find a College')
));
$validator = ZenValidator::create();
$validator->addRequiredFields(array(
'DegreeType' => 'Please select a Degree',
'Course' => 'Please select a course',
'City' => 'Please select a city',
));
$form = new Form($this, 'Search', $fields, $actions, $validator);
$form->setLegend('Criteria')->addExtraClass('form-horizontal')->setAttribute('data-toggle', 'validator');
// Load the form with previously sent data
$form->loadDataFrom($this->request->postVars());
return $form;
}
public function Search() {
return array('Content' => print_r($this->getRequest()->postVars(), true));
}
}
It seems to be displaying results on the same page but gives me a bunch of weird data. For example, I got this when I tested the form: Array ( [DegreeType] => 53 [Course] => 1 [City] => 1 [SecurityID] => 02718d0283e27eeb539eff19616e0b23eadd6b94 [action_Search] => Find a College )
The result is supposed to be an organized list of colleges (along with other data).

I guess that what you are seeing is expected behavior, as the form will post to the Search function, and that one is just returning a print_r of an array with the post vars which will be picked up by the template.
Otherwise, there are a lot of things not corresponding with the Silverstripe default way to handle forms. Please take a look here and change your form accordingly: https://docs.silverstripe.org/en/3.4/tutorials/forms/
For example, give the form the same name as your function (or in your case, change the function name to the form name). Then implement the action function.

Related

Zend framework 2 access to Form class from added elements

Question: Is it possible to access to the Form class from an added element?
Example case:
Note: This example makes no sense as it is, but that's not exactly what I'm trying to do: It's just to keep things simple
Suppose to have a custom view helper that wraps an element into a div. Something like:
public function render(ElementInterface $element = NULL) {
return '<div class="myclass">'.$this->view->formElement($element).'<div>';
}
I would like to retrive the class 'myclass' from the element itself and add it to the div only if the form has been submitted. Something like:
public function render(ElementInterface $element = NULL) {
$class='default';
if(isset($_POST['submit'])){
$class=$element->getOption('wrapper_class');
}
return'<div class="'.$class.'">'.$this->view->formElement($element).'<div>';
}
That works (if 'submit' is the name of the submit button) but, if I have two forms into the same page the second form submission will trigger the above condition and the class will be applied.
A workaround could be:
class MyForm extends Form {
public function __construct($name = null){
parent::__construct($name);
$this->add([
'name' => 'myElement',
'type' => MyCustomElement::class,
'options' => [
'triggered_by' => $this->getName(),
'wrapper_class'=>'myClass',
],
]);
$this->add([
'name' => $this->getName(),
'type' => 'submit',
'attributes' => [
'value' => 'Go',
'id' => 'submitbutton',
'class'=>'btn btn-success',
],
]);
}
}
and then: if(isset($_POST[$element->getOption('triggered_by')])){ ... }
But that works good only if the custom element is added directly to the form. If it's added to a fieldset then $this->getName() will return the name of the fieldset. Obviously the name could be added as a string but I would like to avoid it (typos).
The top solution would be to have access to the main form's options/attributes from all the sub-elements but the elements do not extend Form (myElement->extend Element , Form->extend Fieldset->extend Element).
...then...?
Simple answer: no you can't. Elements can also be a part of a fieldset so they're not directly coupled to a form element.
You could take a different approach with your viewhelper. As in: $myHelper::__invoke(Form $form) or $myHelper::setForm(Form $form), which sets the form. From within that method you can check whether or not the form $form::hasValidated() because that tells us that the form was posted. Then from with the $myHelper::render(ElementInterface $element), you could add some logic to add the wrapperclass as in your example. And within your example merge the classes so that the wrapper doesnt replaces all the form element (css) classes.

CakePHP prepopulate form with data from a link

Assume I'm in my items controller.
Ok say I am in my view action (the url would be something like /items/view/10012?date=2013-09-30) which lists a list of items that belongs to a client on a given date.
I want to link to add a new item. I would use the htmlhelper like so:
echo $this->Html('action'=>'add');
In my add action I have a form which has fields like client_id and item_date.
When I'm in my view action I know these values as I am viewing the items for a specific client on a specific date. I want to pass these variables to my add action so it will prefill those fields on the form.
If I add a query string in my link ('?' => array('client_id'=>$client_id)) it breaks the add action as it will give an error if the request is not POST. If I use a form->postLink I get another error as the add action's POST data must only be used for adding the record, not passing data to prefill the form.
I basically want to make my link on the view page pass those 2 variables to the add action in the controller so I can define some variables to prefill the form. Is there a way to do this?
Here is my add controller code. It may differ in content a bit from my question above as I have tried to simplify the question a bit but the concept should still apply.
public function add(){
if ($this->request->is('post')) {
$this->Holding->create();
if ($this->Holding->save($this->request->data)) {
$this->Session->setFlash(__('Holding has been saved.'), 'default', array('class' => 'alert alert-success'));
return $this->redirect(array('action' => 'index'));
}
$this->Session->setFlash(__('Unable to add your holding.'), 'default', array('class' => 'alert alert-danger'));
}
$this->set('accounts', $this->Holding->Account->find('list'));
$sedol_list = $this->Holding->Sedol->find('all', array(
'fields' => array(
'id', 'sedol_description'
),
'recursive' => 0,
'order' => 'description'
)
);
$this->set('sedols', Hash::combine($sedol_list, '{n}.Sedol.id', '{n}.Sedol.sedol_description') );
}
Why not use proper Cake URL parameters?
echo $this->Html->link('Add Item', array(
'action' => 'add',
$client_id,
$item_date
));
This will give you a much nicer URL like:
http://www.example.com/items/add/10012/2013-09-30
And then in your controller, you modify the function to receive those parameters:
public function add($client_id, $item_date) {
// Prefill the form on this page by manually setting the values
// in the request data array. This is what Cake uses to populate
// the form inputs on your page.
if (empty($this->request->data)) {
$this->request->data['Item']['client_id'] = $client_id;
$this->request->data['Item']['item_date'] = $item_date;
} else {
// In here process the form data normally from when the
// user has submitted it themselves...
}
}

Kohana 3.2 - ORM Update field which have been modifed by admin

Im back to professional programming after 5 year late, so i have learn from beginning ;)
So i chose Kohana framework for my first framework i try to bulid first application now and i have a small problem, lets begin.
I use Kohana ORM and Auth module, as you know default Auth module user table have default fields (username, password, lastlogin) i try to extend User by:
Creating new table (user_additionals)
Creating new model (User_Additional)
Model look like this: http://pastie.org/private/412jflfoifyqs46uaxmga - Nothing special. Everything will be okay, i like easy reference like this: $user->additional->firstname etc.
At the moment i have bulid admin panel (admin can edit every user) and... every field. I have 10 fields like firstname, lastname, birthdate presented as form (filled form - placeholder loaded by template assign) and here is my small problem:
I want to give admin possibility to edit one from much fields, if admin need to edit user signature or something else - he edit one field from a lot fields available and click "Submit" it's easy - one form have been updated.
But, if i try use something like this:
$edit = ORM::Factory('User_Additional')->values($_POST); I get validation Exception (which be catched but, here are validation error - model required all fields to be !empty... (By validation rules)
I use temporary solution, but im a perfectionist and i want to create good code from begining, so here you can find my code: http://pastie.org/private/axtwxbt66gtvcwiv97hvlq
My solution start at line 29 (link above).
So my question is:
*How to make exceptions from Validation in cases like this?? *
*How make exceptions from validation for example for action /admin/edituser/ is it possible? *
*How do i can do my model code better? Thanks for any suggestions which can help me *
Thanks!
Validation will only run on "non-empty" fields, unless you specify the "not_empty" rule.
So basically, you could do the following: (when you need to enforce the "non emptiness" of a field)
class Model_User_Additional extends ORM
{
protected $foreign_key_suffix = 'user_id';
protected $_primary_key = 'user_id';
public function enforce_rules(array $fields)
{
$validation = Validation::factory($this->_object);
foreach ($fields as $field)
{
$validation->rule($field, 'not_empty');
}
return $validation;
}
public function rules()
{
/* Removed all not_empty */
return array(
/* 'user_id' => array(
array('not_empty'),
), */
'firstname' => array(
array('text'),
),
'lastname' => array(
array('text'),
),
'birthdate' => array(
array('date'),
),
'postprice' => array(
array('decimal'),
),
'articleprice' => array(
array('decimal'),
),
'phonenumber' => array(
array('phone'),
),
/* 'active' => array(
array('not_empty'),
), */
/* 'lastupdate' => array(
array('not_empty'),
), */
'info' => array(
array('text'),
),
);
}
public function edit_user($values, $expected, $extra_validation = NULL)
{
return $this->values($values, $expected)->update($extra_validation);
}
}
the usage would be:
$user = ORM::factory('User_Additional');
$user->values(array('field' => 'value'))->create($user->enforce_rules(array('user_id')));
/* and the same for updating */
$user->set('info', $_POST['info'])->update($user->enforce_rules(array('info')));

Conditional fieldgroups/fieldsets in Drupal 7

Background: In Drupal 7, I have created a form with CCK (aka the Field UI). I used the Field group module to create a fieldgroup, but I need it to be conditional, meaning it will only display depending on a previous answer.
Previous research: To create a conditional field, you can use hook_form_alter() to edit the #states attribute like so:
function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'person_info_node_form') {
// Display 'field_maiden_name' only if married
$form['field_maiden_name']['#states'] = array(
'visible' => array(
':input[name="field_married[und]"]' => array('value' => 'Yes'),
),
);
}
}
However, there seems to be no way to use the States API for fieldgroups. One thing to note is that, while fields are stored in $form, fieldgroups are stored in $form['#groups'] as well as in $form['#fieldgroups']. I don't know how to distinguish between these, and with this in mind, I have tried to apply a #states attribute to a fieldgroup in the same manner as above. However, it only produces server errors.
Question: Is there a way to make a fieldgroup display conditionally using the States API or some alternative approach?
you have to use the hook_field_group_build_pre_render_alter()
Simply :
function your_module_field_group_build_pre_render_alter(&$element) {
$element['your_field_group']['#states'] = array(
'visible' => array(
':input[name="field_checkbox"]' => array('checked' => TRUE),
),
);
}
This works perfecly. If the group A is in an another group, do this
$element['groupA']['groupB']['#states'] etc....
You may need to add an id attribute if none exists:
$element['your_field_group']['#attributes']['id'] = 'some-id';
$element['yout_field_group']['#id'] = 'some-id';
Here's the simplest solution I came up with. There are essentially 2 parts to this: (1.) programmatically alter the display of the form, and (2.) use the GUI to alter the display of the content.
(1.) First, I used hook_form_alter() to programmatically create the conditional fieldset and add existing fields to it. The code is shown below.
function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'FORM_ID_node_form') {
// programmatically create a conditional fieldset
$form['MYFIELDSET'] = array( // do NOT name the same as a 'Field group' fieldset or problems will occur
'#type' => 'fieldset',
'#title' => t('Conditional fieldset'),
'#weight' => intval($form['field_PARENT']['#weight'])+1, // put this fieldset right after it's "parent" field
'#states' => array(
'visible' => array(
':input[name="field_PARENT[und]"]' => array('value' => 'Yes'), // only show if field_PARENT == 'Yes'
),
),
);
// add existing fields (created with the Field UI) to the
// conditional fieldset
$fields = array('field_MYFIELD1', 'field_MYFIELD2', 'field_MYFIELD3');
$form = MYMODULE_addToFieldset($form, 'MYFIELDSET', $fields);
}
}
/**
* Adds existing fields to the specified fieldset.
*
* #param array $form Nested array of form elements that comprise the form.
* #param string $fieldset The machine name of the fieldset.
* #param array $fields An array of the machine names of all fields to
* be included in the fieldset.
* #return array $form The updated form.
*/
function MYMODULE_addToFieldSet($form, $fieldset, $fields) {
foreach($fields as $field) {
$form[$fieldset][$field] = $form[$field]; // copy existing field into fieldset
unset($form[$field]); // destroy the original field or duplication will occur
}
return $form;
}
(2.) Then I used the Field group module to alter the display of the content. I did this by going to my content type and using the 'Manage display' tab to create a field group and add my fields to it. This way, the fields will appear to be apart of the same group on both the form and the saved content.
Maybe you can try to look at the code of this module to help you find an idea.

Dynamic form fields in Symfony 1.4

I'm working on an e-commerce project and I got stuck at the cart update. Here I have to present a form using the contents of the current cart, with input fields containing the current quantities.
I checked the documentation and the forums, but I didn't find anything useful. The problem is that i cannot declare the exact form fields in my form class because I don't know how many fields will be there. I tried this:
class CartForm extends sfForm {
public function configure()
{
$cart = sfContext::getInstance()->getUser()->getShoppingCart();
foreach ($cart->getItems() as $item) {
$widgetName = $item->getId().'_quantity';
$this->widgetSchema[$widgetName] = new sfWidgetFormInput(
array(),
array(
'class' => 'quantity-input',
'id' => null,
'name' => $widgetName
)
);
$this->widgetSchema->setDefault($widgetName, $item->getQuantity());
$this->validatorSchema[$widgetName] = new sfValidatorInteger(array(
'required' => true,
'min' => 1
),
array());
}
unset($cart);
$this->getWidgetSchema()->getFormFormatter()->setRowFormat('%field%%error%%hidden_fields%');
}
}
but I got some errors:
Fatal error: Cannot use object of type sfShoppingCart as array in /home/sfprojects/mdmall/lib/vendor/symfony/lib/form/sfForm.class.php on line 784
so this is not the right way. I tried to use raw fields without any form classes (and validators) but something very odd happens, instead of getting the $_POST values i get a 404 error because when I submit the form it doesn't trigger this:
cart_update:
url: /cart/update.:sf_format
class: sfRequestRoute
param: { module: cart, action: update, sf_format: html }
requirements: { sf_method: post }
If I remove the requirement, cart/update runs, but I dont have the $_POST data in the request object. Do you have any ideas?
These will help you with regard to dynamically adding form fields and working with validation of those fields:
Dynamic Emedded forms (but the process is similar for fields)
Dynamic Form Fields
Custom Validation

Categories