Zend-form setValue , view has empty value like <input value="" > - zend-framework

I have a quite complex form setup using Zend-Form. At one point I'm setting value of a hidden input using :
$oHidden = new Zend_Form_Element_Hidden('ratings'.$k);
$oHidden->setValue('ratings');Zend_Debug::dump($oHidden);
$this->addElements(array($oHidden));
This method works well in other places of the same form, but this one, and another one just like i t outputs :
<input type="hidden" name="ratings1" value="" id="ratings1" />
I've dumped the $oHidden variable and it outputs :
object(Zend_Form_Element_Hidden)#143 (29) {
...
["_value":protected] => string(7) "ratings"
["_view":protected] => NULL
["_isPartialRendering":protected] => bool(false)
}
So it sets the value just fine for a while but it doesn't render it. Please let me know where to start looking reasons for this behavior.
Thanks,
Alek

The problem is precisely the isValid() function. It clears all values from the form and then repopulates it with the parametres that are passed to it. If a parametre is absent, it apparently won't appear anymore in the form, even if it was set explicitly a few lines earlier.
My case was an optional "redirect" hidden field in a login form. Here's the code (simplified for readability):
$form = new Form_Login();
$redirect = $this->_getParam('redirect','/user/login/welcome');
$form->addElement('Hidden','redirect',array('value' => $redirect));
if ($this->_request->isPost() && $form->isValid($this->_getAllParams())) {
// WTF! the "request" field has no value!!!
}
The workaround was setting the action parametre:
$form = new Form_Login();
$redirect = $this->_getParam('redirect','/user/login/welcome');
$this->_setParam('redirect',$redirect);
$form->addElement('Hidden','redirect',array('value' => $redirect));
if ($this->_request->isPost() && $form->isValid($this->_getAllParams())) {
// AHA! now it works!
}
I know the question is half a year old, but oh well, better late than never :D.

$hidden = new Zend_Form_Element_Hidden(array('name' => 'ratings', 'value' => 'ratings'));
Try it!

Related

Codeigniter 3: foreach inside form_input

I'm just starting with CodeIgniter and I can't output the value of my form_input. Here's my code:
<?= form_input('gender','','type="text" class="form-control form-input" value="'.foreach($profile as $prof){echo $prof->gender;}.'" disabled id="name" style="cursor:default"');?>
is my syntax even correct?
No, your syntax is not correct. Your arguments to form_input are wacky and, as you have it, only one input field is created. The "value" of that input might be something like
value='malefemalefemalemalemalemalsemalefemale',
Pretty sure that's not what you want.
Actually, from the code you post it's hard to know what you do want. My guess is this
<?php
//create an array with attribute values that don't change
$attributes = [
'class' => "form-control form-input",
'style' => "cursor:default",
];
//create a counter
$i = 0;
foreach($profile as $prof)
{
//inputs need a unique "name" and "id", use the counter for that purpose
$attributes['name'] = 'gender'.$i;
$attributes['id'] = "name".$i;
//add the 'value' of each profile to the array
$attributes['value'] = $prof->gender;
//send the array to form_input
echo form_input($attributes, NULL, 'disabled');
echo "<br>"; //new line
$i++; //increase value of counter by one for next loop run
}
The above will output a text field (each on a separate line) for each profile.
Documentation on `form_input'.
The "name" of the inputs will be "gender0", "gender1", etc, which will work. That is not the only way to do it. You could also use input arrays. That syntax is name='gender[]'. Either approach will work for the "name" but it won't work for the "id" attributes which must be unique.

SugarCRM 6.5 CE: how to remove button in detailview according to a condition

I'm trying to remove buttons in detail view of a Lead if it is alredy converted.
I saw a similar question and it use javascript to hide buttons. I'm trying to obtain same result via php.
This is my view.detail.php in custom\modules\Leads\views\ folder
class LeadsViewDetail extends ViewDetail {
function __construct(){
parent::__construct();
}
function preDisplay() {
parent::preDisplay();
if($this->bean->converted==1) {
echo "hide";
foreach ($this->dv->defs['templateMeta']['form']['buttons'] as $key => $value) {
unset($this->dv->defs['templateMeta']['form']['buttons'][$key]);
}
} else {
echo "show";
}
}
}
Using this code, after a Quick Repair & Rebuilt, I see "hide" or "show" correctly according to the Lead status but buttons are not updated correctly.
If I open a converted Lead after QR&R, I will never see the buttons.
If I open a unconverted Lead after QR&R, I will see the buttons all times.
I'm stuck with this situation. Can anyone explain me where is the problem? How I can solve it?
Every help is very appreciated.
You can probably handle this without extending the ViewDetail by using Smarty logic ("customCode") in custom/modules/Leads/metadata/detailviewdefs.php. It looks like the Convert button is already only rendered when the user has Edit privileges, so it's not a big deal to add one more condition to it...
$viewdefs['Leads']['DetailView']['templateMeta']['form]['buttons'][] = array('customCode' => '
{if $bean->aclAccess("edit") && $bean->converted}
<input title="{$MOD.LBL_CONVERTLEAD_TITLE}"
accessKey="{$MOD.LBL_CONVERTLEAD_BUTTON_KEY}"
type="button"
class="button"
name="convert"
value="{$MOD.LBL_CONVERTLEAD}"
onClick="document.location=\'index.php?module=Leads&action=ConvertLead&record={$fields.id.value}\'" />
{/if}');
Alternatively, if you do have several conditions and they'd get too messy or difficult for Smarty logic to be reasonable, we can combine a small amount of Smarty Logic with the extended ViewDetail.
This except of custom/modules/Leads/metadata/detailviewdefs.php is actually the out-of-the-box file from SugarCRM CE 6.5.24, where it looks like they've actually tried to make this customization easier by supplying a Smarty var $DISABLE_CONVERT_ACTION. For reference, it simply needs the global config variable disable_convert_lead to be set and enabled, but I suspect that this was a relatively new feature not included in earlier versions. Still, it's a good example of using the View to set a simple Smarty variable that we can pivot on:
<?php
$viewdefs['Leads']['DetailView'] = array (
'templateMeta' => array (
'form' => array (
'buttons' => array (
'EDIT',
'DUPLICATE',
'DELETE',
array (
'customCode' => '{if $bean->aclAccess("edit") && !$DISABLE_CONVERT_ACTION}<input title="{$MOD.LBL_CONVERTLEAD_TITLE}" accessKey="{$MOD.LBL_CONVERTLEAD_BUTTON_KEY}" type="button" class="button" onClick="document.location=\'index.php?module=Leads&action=ConvertLead&record={$fields.id.value}\'" name="convert" value="{$MOD.LBL_CONVERTLEAD}">{/if}',
//Bug#51778: The custom code will be replaced with sugar_html. customCode will be deplicated.
'sugar_html' => array(
'type' => 'button',
'value' => '{$MOD.LBL_CONVERTLEAD}',
'htmlOptions' => array(
'title' => '{$MOD.LBL_CONVERTLEAD_TITLE}',
'accessKey' => '{$MOD.LBL_CONVERTLEAD_BUTTON_KEY}',
'class' => 'button',
'onClick' => 'document.location=\'index.php?module=Leads&action=ConvertLead&record={$fields.id.value}\'',
'name' => 'convert',
'id' => 'convert_lead_button',
),
'template' => '{if $bean->aclAccess("edit") && !$DISABLE_CONVERT_ACTION}[CONTENT]{/if}',
),
),
We can combine this $DISABLE_CONVERT_ACTION reference with a custom/modules/Leads/views/view.detail.php like the following to set it based on whatever condition we want:
<?php
require_once('modules/Leads/views/view.detail.php');
class CustomLeadsViewDetail extends LeadsViewDetail {
/*
* while we might normally like to call parent::display() in this method to
* best emulate what the parnts will do, we instead here copy-and-paste the
* parent methods' content because LeadsViewDetail::display() will set the
* DISABLE_CONVERT_ACTION Smarty var differently than we want.
*/
public function display(){
global $sugar_config;
// Example One: Disable Conversion when status is Converted
$disableConvert = ($this->bean->status == 'Converted');
// Example Two: Disable Conversion when there is at lead one related Call
// where the status is Held
$disableConvert = FALSE;
$this->bean->load_relationships('calls');
foreach($this->bean->calls->getBeans() as $call){
if($call->status == 'Held'){
$disableConvert = TRUE;
break; // exit foreach()
}
}
// Example Three: Disable Conversion if the User is in a specific Role, e.g.
// Interns who are great for data entry in Leads but shouldn't be making
// actual sales
global $current_user;
$disableConvert = $current_user->check_role_membership('No Lead Conversions');
// In any of the above examples, once we have $disableConvert set up
// as we want, let the Smarty template know.
$this->ss->assign("DISABLE_CONVERT_ACTION", $disableConvert);
// copied from ViewDetail::display();
if(empty($this->bean->id)) {
sugar_die($GLOBALS['app_strings']['ERROR_NO_RECORD']);
}
$this->dv->process();
echo $this->dv->display();
}
}

approach for validated form controls in AngularJS

My teammates and I are learning AngularJS, and are currently trying to do some simple form field validation. We realize there are many ways to do this, and we have tried
putting input through validation filters
using a combination of controller and validating service/factory
a validation directive on the input element
a directive comprising the label, input and error output elements
To me, the directive approach seems the most "correct". With #3, we ran into the issue of having to communicate the validation result to the error element (a span sibling). It's simple enough to do some scope juggling, but it seemed "more correct" to put the span in the directive, too, and bundle the whole form control. We ran into a couple of issue, and I would like the StackOverflow community's input on our solution and/or to clarify any misunderstandings.
var PATTERN_NAME = /^[- A-Za-z]{1,30}$/;
module.directive("inputName", [
function () {
return {
restrict: "E",
require: "ngModel",
scope: {
fieldName: "#",
modelName: "=",
labelName: "#",
focus: "#"
},
template: '<div>' +
'<label for="{{fieldName}}">{{labelName}}</label>' +
'<input type="text" ng-model="modelName" id="{{fieldName}}" name="{{fieldName}}" placeholder="{{labelName}}" x-blur="validateName()" ng-change="validateName()" required>' +
'<span class="inputError" ng-show="errorCode">{{ errorCode | errorMsgFltr }}</span>' +
'</div>',
link: function (scope, elem, attrs, ngModel)
{
var errorCode = "";
if (scope.focus == 'yes') {
// set focus
}
scope.validateName = function () {
if (scope.modelName == undefined || scope.modelName == "" || scope.modelName == null) {
scope.errorCode = 10000;
ngModel.$setValidity("name", false);
} else if (! PATTERN_NAME.test(scope.modelName)) {
scope.errorCode = 10001;
ngModel.$setValidity("name", false);
} else {
scope.errorCode = "";
ngModel.$setValidity("name", true);
}
};
}
};
}
]);
used as
<form novalidate name="addUser">
<x-input-name
label-name="First Name"
field-name="firstName"
ng-model="firstName"
focus="yes"
model-name="user.firstName">
</x-input-name>
<x-input-name
label-name="Last Name"
field-name="lastName"
ng-model="lastName"
model-name="user.lastName">
</x-input-name>
...
</form>
First, because both form and input are overridden by AngularJS directives, we needed access to the ngModel API (ngModelController) to allow the now-nested input to be able to communicate validity to the parent FormController. Thus, we had to require: "ngModel", which becomes the ngModel option to the link function.
Secondly, even though fieldName and ngModel are given the same value, we had to use them separately. The one-way-bound (1WB) fieldName is used as an attribute value. We found that we couldn't use the curly braces in an ngModel directive. Further, we couldn't use a 1WB input with ngModel and we couldn't use a two-way-bound (2WB) input with values that should be static. If we use a single, 2WB input, the model works, but attributes like id and name become the values given to the form control.
Finally, because we are sometimes reusing the directive in the same form (e.g., first name and last name), we had to make attributes like focus parameters to be passed in.
Personally, I would also like to see the onblur and onchange events bound using JavaScript in the link function, but I'm not sure how to access the template markup from within link, especially outside/ignorant of the larger DOM.

Form not passing through hidden field value correctly in Facebook, but ok elsewhere

I have a script that first checks if the form page is referred from a GET parameter
$page['is_referred'] = isset($_GET['rfr']) ? 1 : 0;
Then that set value is used as the value of a hidden field in a Symfony2 form
$form = $app['form.factory']->createBuilder('form', $data)
//....
->add('referred', 'hidden', array(
'data' => $page['is_referred'],
))
->getForm();
then
if ('POST' === $request->getMethod()) {
$form->bindRequest($request);
if ($form->isValid()) {
//...
$referred = $form->get('referred')->getData();
$msg_referer = "Thanks from Referrer";
$msg_noreferer = "Thanks";
if( 1 == $referred ){
$page['thanks'] = $msg_referer;
}else{
$page['thanks'] = $msg_noreferer;
}
//..
}
}
The hidden field is read okay on the main site when ?rfr is in the url, but when iframed in Facebook and ?rfr is present, the $msg_noreferer message is displayed instead. Any ideas as to why this happens?
EDIT: I should also mention that the field value is correctly set in Facebook when I check the source, but it just doesn't seem to post the data through correctly
I should also mention that the field value is correctly set in Facebook when I check the source, but it just doesn't seem to post the data through correctly
I’d say, the value is posted alright, but the form validation does not accept it, because the hidden field does not get added to the form on validation.
Have you checked this, if the code adding the hidden field to the form is actually being executed when handling the POST request received from the browser …?

Conditional File Count Validator for a Zend_Form_File_Element

In my project we have a Form where the user either needs to upload a file or specify some other information, for example in a text input.
I know that there is the possibility to attach a Count validator to the Form Element, and this works like this:
$upload->addValidator('Count', false, array('min' => 1, 'max' => 3));
This validator gets called, no matter if there are files uploaded or not. But as soon as i replace the validator with a custom version, and do not upload any files, the validator does not get called.
Looking at the isValid() method of Zend_File_Transfer_Adapter_Abstract, I can see the problem:
[...]
foreach($check as $key => $content) {
if (array_key_exists('validators', $content) &&
in_array('Zend_Validate_File_Count', $content['validators'])) {
$validator = $this->_validators['Zend_Validate_File_Count'];
$count = $content;
[...]
Seems like the Count Validator got some special treatment here. But how can I include my customized Validator, without overwriting Zend Files?
Because we do not extend the Zend_Form class, sadly I also cannot overwrite the isValid() method of the involved Form. Any Ideas left? Thanks for your time!
This would probably be easiest with a bit of ajax. That way you could evaluate the selection prior to posting the form.
To do it in PHP, an Element validator is probably not the way to go. It would be better to handle the selection with an if() statment.
pseudocode...
//if file element contains something and text doesn't
if($this->getRequest->getPost('file'=='' && 'text' != ''){
$file = $form->file->receive();
//do some stuff
//if text element contains something and file dosen't
}elseif ($this->getRequst->getPost('file' != '' && 'text' == '') {
if($form->isValid($this->_request->getPost('text')) {
//do some stuff
}
}
This is the idea, hope it helps.