Zend Forms in Zf2, not able to retain values - php

i am using zend forms in my zf2 application which has two text boxes. Once i submit the data, i take that and i filter the data array which i use to display it on the table. Once the data is filtered and displayed on the table, the form data is reset.
Is there a way to retain the values in the form even after submission ?
Thats the code i have, on a button click i get into this page and the action is as shown below. So this Page has a table which will get populated based on the two text boxes that i have. When i click the submit button, the data in the textboxes disappear and the data gets populated in the table.
So what i want to do here is, retain the entered values in the textboxes. Can i do that ? I know HTTP is a stateless protocol. I know i can do it using front end client side technologies, just wanted to know if there is a work around to do this.
public function searchAction()
{
//search form instantiation
$form = new SampleForm();
// get the post request
$request = $this->getRequest();
//instantiation of select for querying
$select = new Select();
// get parameters
$artist = $request->getPost('artist');
$title = $request->getPost('title');
//prepare search criteria array
$search = array('artist' => $artist, 'title' => $title);
//remove empty criteria from the search criteria list
foreach ($search as $key => $value) {
if (empty($value)) {
unset($search[$key]);
}
}
$result = $this->getAlbumTable()->fetchAll($select->where($search));
return array(
'albums' => $result,
'form' => $form,
);
}

I finally figured out what i was doing. I just had to do this.
if ($request->isPost()) {
$album = new Album();
$form->setInputFilter($album->getInputFilter());
$form->setData($request->getPost());
}

Related

How to automatically fill other form fields after one field is filled?

I'm creating a form in moodle using moodleform class. I have many fields in the form. What I'm wanting to do is when the user fills in the first field, I want to get the data that he/she entered, search the relevant DB table for a field that matches that input, then populate the other fields for that record.
Please note that the user hasn't pressed any submit button yet. I've been trying to find a function that gets the entered data but all efforts have been in vain. What I found was a get_data() method but I don't even know how to use that correctly. I've been reading the moodle docs but nothing is helping. I'm not a beginner to coding but neither am I an expert.
Here's a code snippet:
class requestcourse_form extends moodleform
{
function definition()
{
global $CFG, $currentsess, $DB, $USER, $currentrecord;
$mform =& $this->_form; // Don't forget the underscore!
// Form header
$mform->addElement('header', 'mainheader','<span style="font-size:22px">'.get_string('courserequestform','block_usp_mcrs'). '</span>');
// Course Code field.
$coursecodearray = array();
$coursecodearray[0] = get_string('choosecoursecode', 'block_usp_mcrs');
$allcoursecodes = $DB->get_records_select('block_usp_mcrs_courses', 'id > 0', array(), 'id', 'id, course_code');
foreach ($allcoursecodes as $id => $coursecodeobject) {
$coursecodearray[$id] = $coursecodeobject->course_code;
}
$coursecode = $mform->addElement('select', 'coursecode', get_string('coursecode', 'block_usp_mcrs'), $coursecodearray);
$mform->addRule('coursecode', get_string('required'), 'required', null, 'client');
$mform->setType('coursecode', PARAM_RAW);
// Course Name field. TODO: Course Name to pick automatically after entering Course Code
$coursenamearray = array();
$coursenamearray[0] = get_string('choosecoursename', 'block_usp_mcrs');
$allcoursenames = $DB->get_records_select('block_usp_mcrs_courses', 'id > 0', array(), 'id', 'id, course_name');
foreach ($allcoursenames as $id => $coursenameobject) {
$coursenamearray[$id] = $coursenameobject->course_name;
}
$mform->addElement('select', 'coursename', get_string('coursename', 'block_usp_mcrs'), $coursenamearray);
$mform->addRule('coursename', get_string('required'), 'required', null, 'client');
$mform->setType('coursename', PARAM_RAW);
Any help would be appreciated.
You have to achieve this using javascript, as Moodle has no functionality to fill data in a nested way.
Add AMD module js file where you are calling your mform for display purpose.
In the file where you render your mform
$mform->render();
add below line to call you amd js file.
$PAGE->requires->js_call_amd('local_acestructure/registration', 'init');
In your amd js file make httprequest / ajax call to fetch data based on your course_code select drop down change.
Thank you.

Allow users to update their gravity form single unique entry

I am trying to make a form which will allow them to update their entered unique entry. Suppose there is form which is used to collect, the User Specializations
And this Specializations field is gravity forms multiselect field which is dynamically set. And as they update their specializations also updated in entries tab.
So, i just want to allow they to have this multiselect field updation.
I came across a solution to add multiselect choice dynamically but that only populate the field with all the choices not the user selected also.
So, is there is way to set the user entered choices dynamically?
Possible Solution:
Like we can get the entries and then set search criterion to current user and will get a unique entry and then after we can set these selected values in the choices.
Issue Exists with the above possible solution:
but still there is issue like it will be creating new entry as form dont know it is update operation. So can anyone help?
//Auto Populate Service Field in Form ID=
add_filter('gform_pre_render_2', 'populate_services');
add_filter('gform_pre_validation_2', 'populate_services');
add_filter('gform_pre_submission_filter_2', 'populate_services');
add_filter('gform_admin_pre_render_2', 'populate_services');
function populate_services($form)
{
foreach ($form['fields'] as &$field) {
if ($field->type != 'multiselect' || strpos($field->cssClass, 'populate_services') === false) {
continue;
}
$services = get_specializations();
$choices = array();
foreach ($services as $service) {
$title = stripslashes($service->name);
$choices[] = array(
'value' => $service->ID,
'text' => esc_html($title)
);
}
// update 'Select Duration' to whatever you'd like the instructive option to be
$field->placeholder = 'Select Services';
$field->choices = $choices;
}
return $form;
}

Get data from multiple forms Laravel

I am working on Laravel. I have a blade view page on which multiple forms (of same model) are created. Now, I want, that when I click submit button, an array of all the forms should be returned to controller. But, it returns data of only one form instead of array. How can I achieve this, Can anyone help me?
It's not a real Laravel issue.
The trick is using different forms with each a submit button. Then, it's simple. Check the submitted button.
if ($request->isMethod('post')) {
if ($request->has('submit_button_form_1')) {
// Handle form
}
elseif ($request->has('submit_button_form_2')) {
// Handle form
}
elseif ($request->has('submit_button_form_3')) {
// Handle form
}
}
First of all I dont think you can send multiple forms, that is just way it is.
You have two options.
First: Make one form with all fields from all forms, and then in controller you just take what field you want, just like you would do from arrays so same thing.
Like:
$all_fields= Request::all();
and then
$all_fields['something'], $all_fields['something_else'],
Second: Using ajax, you can manipulate and send values of fields, fields that you need.
What you can do is you need to loop the form field with naming structure as first_name1, first_name2 and so on. Then, after submitting the form, you can validate using the loop in the same way and get the values. You can check my sample code here. It count the number of loops to be made.
You can pass the counter from the view to the controller in hidden field. Then, you can loop for validation and for taking the inputs.
Check my sample code:
//determine number of rows in database
$number_of_loop = Input::get('number_of_loop');
$arrayList = []; //defining the array variable
//declaring the validations rules
for($i = 1; $i < $number_of_loop; $i++){
$rules = array(
'currency'.$i => 'required',
'iso_code'.$i => 'required',
'symbol'.$i => 'required',
'status'.$i => 'required'
);
$validator = Validator::make(Input::all(), $rules);
if($validator->fails()){
return Redirect::back()->withErrors($validator)->withInput();
}
}
for ($i=1; $i <= $number_of_loop; $i++) {
$new_currency = new stdClass();
$currency = Input::get('currency' . $i);
$iso_code = Input::get('iso_code'.$i);
$symbol = Input::get('symbol'.$i);
$conversion_rate = Input::get('conversion_rate'.$i);
$status = Input::get('status'.$i);
$new_currency->currency = $currency;
$new_currency->iso_code = $iso_code;
$new_currency->symbol = $symbol;
$new_currency->conversion_rate = $conversion_rate;
$new_currency->enable = $status;
array_push($arrayList, $new_currency);
}
Update1
For storing all the records, create an array and a new stdclass. Store all the variable in stdclass attributes. and at last, push the new stdclass to the array. Then, you can access all the inputs of form. Check above updated code sample
If you’re using Laravel 5.2 then you can validate array data. You’ll need to put all of your inputs in one form as you just can’t send multiple forms. If each form had different URLs for the action attribute, how would that work?
To send data as an array, you can suffix the name attribute with []:
{!! Form::open() !!}
{!! Form::text('name[]') !!}
{!! Form::text('name[]') !!}
{!! Form::text('name[]') !!}
{!! Form::close() !!}
When this form is submitted, name will be an array with three elements.
To validate, use a wildcard in your validation rule name:
return [
'name.*' => 'required|max:255',
];
You can then access the array of names in your controller through the Request object:
$names = $request->get('names', []);
foreach ($names as $name) {
User::create(['name' => $name]);
}
I don’t know your data structure as you haven’t included it in your question, but this should be enough for you to apply to your given scenario.

Yii2 grid updating with editable field

I followed the post on setting up an editable field in a grid here http://webtips.krajee.com/setup-editable-column-grid-view-manipulate-records/
Everything seems to work - I click on the field, change it's value and it shows the updated value in the grid. However - next time I refresh, the value reverts to the original value.
I've done a little debugging, and it would appear that the save in the controller is failing.
My table has a two key fields (key1 and key2) and a value field. I am trying to update this value field.
My view code is as follows:
$gridColumns = [
'AnotherField',
[
'class' => 'kartik\grid\EditableColumn',
'attribute'=>'value',
'label' => 'some value',
'editableOptions'=> [
'header' => 'profile',
'format' => Editable::FORMAT_BUTTON,
]
];
...
...
<?= GridView::widget([
'dataProvider' => $dataProvider,
'columns' => $gridColumns
]) ?>
and the controller code is as follows:
<snip>
//default code from gii-generated controller
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
// orig post said to use this: $dataProvider = $searchModel->search(Yii::$app->request->getQueryParams());
// Validate if there is an editable input saved via AJAX
if (Yii::$app->request->post('hasEditable')) {
$model = new MyTable;
$post = [];
$posted = current($_POST['MyTable']);
$post['MyTable'] = $posted;
// Load model like any single model validation
if ($model->load($post)) {
// When doing $result = $model->save(); I get a return value of false
$model->save();
$out = Json::encode(['output'=>$output, 'message'=>'']);
}
// Return AJAX JSON encoded response and exit
echo $out;
return;
}
// Non-AJAX - render the grid by default
</snip>
How does the controller know which record to update as I am only passing in the 'value' field, not the keys?
Do I somehow need to add these key1 and key2 fields to the view within the editable widget in order to get these values passed to the controller (so that the load and save know which record to update) or is there some other way that the controller handles this?
In the example on this page http://demos.krajee.com/grid-demo (you can see the column definition too) you can see with firebug that the following values are sent:
Book[5][buy_amount] 1
_csrf MEQ0NnEzNjFhd2dBB2wBCHN0cGVCA3lfZHF1TDReRlAAcQNUPUFjBQ==
editableIndex 5
editableKey 6
hasEditable 1
I believe the 5 in Book[5] is probably matching the index of the record.
This part does that from what I see
$post = [];
$posted = current($_POST['Book']);
$post['Book'] = $posted;
I have never used the widget so I might be wrong.
I have found the solution with some experimentation. I had to unserialize the $editableKey value and extract my key field values from it. I then call 'findModel' to load in the record to be updated.
The updated controller code is as follows:
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
// Validate if there is an editable input saved via AJAX
if (Yii::$app->request->post('hasEditable')) {
$keys = unserialize(Yii::$app->request->post('editableKey'));
$model = $this->findModel($keys['key1'], $keys['key2']);
// Store a default JSON response as desired by editable
$out = Json::encode(['output'=>'', 'message'=>'']);
// Fetch the first entry in posted data (there should only be one
// entry anyway in this array for an editable submission)
$values = current($_POST['MyTable']);
// Load model like any single model validation
if ($model->key1) {
// Update the Profile with the new value passed in
$model->value = $values['value'];
$model->save();
...
Thanks for the advice
I was also looking for a solution of updating table using Editable column. Looking at the ajax post I got similar like this output:
Book[5][buy_amount] 1
_csrf MEQ0NnEzNjFhd2dBB2wBCHN0cGVCA3lfZHF1TDReRlAAcQNUPUFjBQ==
editableIndex 5
editableKey 6
hasEditable 1
Here I found the value of editableKey is the value of id of the table.
So to update specific row on gridview column I used the editableKey and update based on it.
In controller :
if (Yii::$app->request->post('hasEditable')) {
$_id=$_POST['editableKey'];
$model = $this->findModel($_id);
$post = [];
$posted = current($_POST['MyTable']);
$post['MyTable'] = $posted;
// Load model like any single model validation
if ($model->load($post)) {
// When doing $result = $model->save(); I get a return value of false
$model->save();
if (isset($posted['buy_amount']))
{
$output = $model->buy_amount;
}
$out = Json::encode(['output'=>$output, 'message'=>'']);
}
// Return AJAX JSON encoded response and exit
echo $out;
return;
}
I just get the post data using $_id=$_POST['editableKey'];
and set my $model as $model = $this->findModel($_id);
now you can update multiple editable column just adding condition like this
if (isset($posted['buy_amount']))
{
$output = $model->buy_amount;
}
Thanks!

cakePHP pagination and passedArgs

I am trying to build in a "search" box on a results page in my cakephp app. The page uses the cakePHP pagination component to show and "page" results. This is perfect, but I am having difficulties to get the next part to work.
The desired outcome:
A cakephp form (post) with an input box and a couple of select boxes, including a date selector so that I can select between dates. The user should be able to populate these fields and submit
On submit, the user selection should change the cakePHP pagination conditions in the controller
In the view I want the pagination bar to keep record of the user selection, so that when I filter through different pages, it keeps the users search. I understand this can be achieved using $this->passedArgs, hence why I am using post and not get.
The code:
// Form:
<?php
echo $this->Form->create('search', array('class' => false));
echo $this->Form->input('searchFor');
echo $this->Form->input('dateFrom');
echo $this->Form->input('dateTo');
echo $this->Form->end();
?>
// Controller:
if($this->request->is("post")) {
$filters = $this->request->data["search"];
$this->passedArgs["searchFor"] = $filters["searchFor"];
$this->passedArgs["dateFrom"] = $filters["dateFrom"]." 00:00:00";
$this->passedArgs["dateTo"] = $filters["dateTo"]." 00:00:00";
// Assign search parameters:
if($this->passedArgs["searchFor"] != "") {
$conditions["Model.field LIKE"] = "%".$this->passedArgs["searchFor"]."%";
}
$conditions["Model.created >="] = $this->passedArgs["dateFrom"];
$conditions["Model.created <="] = $this->passedArgs["dateTo"];
} else {
$conditions = array("Result.status_id >=" => 12);
}
$this->paginate = array(
'conditions' => $conditions,
'order' => array('Result.created ASC'),
'limit' => 20
);
$this->set("results",$this->paginate("Model");
// The view file:
<?php
$this->Paginator->options(array('url' => $this->passedArgs));
?>
Where I am now:
The initial page loads with all of the results
When I populate the search boxes it does return my results
The problem:
I am convinced the way I am doing it is incorrect as I now need to do 2 checks, a) being if results has been posted and b) check if there is passedArgs available. I am 100% convinced this is not the right way of doing it.
Let's say I have 2 free form fields for search, say name and surname, if I leave surname blank my url would be written as below, and this does not look or appear to be correct. That means I have to assign default values to ensure the items below does not happen, which does not appear to be very dynamic.
http://localhost/site/controller/action/surname:0/name:John/date:0/
On refresh it says the page does not exist because the posted values is not available anylonger.
usually I proceed like this in the controller:
//transform POST into GET
if($this->request->is("post")) {
$url = array('action'=>'index');
$filters = array();
if(isset($this->data['searchFor']) && $this->data['searchFor']){
//maybe clean up user input here??? or urlencode??
$filters['searchFor'] = $this->data['searchFor'];
}
//redirect user to the index page including the selected filters
$this->redirect(array_merge($url,$filters));
}
$conditions = array();
//check filters on passedArgs
if(isset($this->passedArgs["searchFor"])){
$conditions["Model.field LIKE"] = "%".$this->passedArgs["searchFor"]."%";
}
//paginate as normal
$this->paginate = array(
'conditions' => $conditions,
'order' => array('Result.created ASC'),
'limit' => 20
);
The idea is to transform the POST sent by your form into GET. so you wont have problems with the paginator nor the refresh
Hope this helps
What you want can be done a lot more simple and DRY by using this search plugin.
It automates what you want more or less plus it already can do more than your code.
So I suggest you to use the plugin directly or take a look at it how it does the trick. :)

Categories