For a standard Varchar (or Text) db field I'd like to replace this with a set of fixed options - but still allow "other" to be selected and for the user to enter a string of their choice.
class MyDataObject extends DataObject {
static $db = array(
'MyVarchar' => "Varchar",
);
function getCMSFields() {
$fields = parent::getCMSFields();
$fields->replaceField(
'MyVarchar',
SomeField(
'MyVarchar',
'Choose an option or enter text',
array(1 => 'Option1',2 => 'Option2')
)
);
return $fields;
}
}
So I'm looking for something to use as SomeField and the user will see a drop down with the values Option1, Option2 and Other. If Option1 or 2 is selected then this is saved into MyVarchar. If Other is selected then it would allow specifying the text directly of MyVarchar as normal.
I'm hopeful there is, as in the case of other answers I've received, a pre-existing module for this.
And...
I've found basically what I was after...
https://github.com/Leapfrognz/alternative-field
Thank you Leapfrognz!
Related
This should be relatively simple. I know how to create a form and hide it and show it if a specific option is selected
I want to have a Dropdown populated with a specific DataObject. That much is simple. But I need to add an option that says 'Add new' to this Dropdown, which is in a form
I can handle the submission (like if the value is something like 'new' instead of an ID), but I do not know how to add this option into the select with Silverstripe, or if it is even possible. Any help is appreciated!
You can use a DropdownField and populate it with whatever key value pairs you want. For example:
$itemsField = DropdownField::create(
'Items',
'Items',
['add-new' => 'Add new'] + $this->Items()->map()->toArray()
);
The third argument is an array that gets turned into the option html elements for the drop down.
Then you can add it to your form's FieldList:
$form = Form::create(
$this,
'MyForm',
FieldList::create(
[
$someField,
$someOtherField,
$itemsField
]
),
$actions,
$requiredFields
);
http://api.silverstripe.org/3.1/class-DropdownField.html
A Dropdown for selecting a $has_one is fine. E.g. if you have a list of Addresses and want to select the Country.
Sometimes a new Country has to be added. For this i used the quickaddnew extension which adds a nice button "add new" beneath the dropdown and opens a form in a modal for adding the new item. You can use it in your code like this:
public function getCMSFields() {
/**
* #FieldList
*/
$fields = parent::getCMSFields();
$countries = function() {
return Country::get()->map('ID','Title')->toArray();
};
$country = new DropdownField('CountryID', 'Country', $countries());
$country->setEmptyString('-- please select --');
$country->useAddNew('Country', $countries);
$fields->insertAfter($country, 'Telephone');
$fields->removeByName('SortOrder');
return $fields;
How do I rename a ckEditorRow panel as highlighted below. I guess its taking the name from the passed in value (in this case 'subject').
I'm trying things like below but getting nowhere
$form->ckEditorRow($subject,'subject',array('options' => array('title'=>'new title')));
thanks
To change label, ovverride attributeLabels in your $subject model.
Simply return array with field name as keys and value as label, ie:
public function attributeLabels()
{
return array(
'subject' => 'Custom Subject Label',
... more labels
);
}
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.
I have code using QuickForm that creates a select widget with the following:
$form->addElement( 'select', 'state_id', 'State:', statesArray() );
statesArray() queries the database to get the states available and returns an associative array with the ids linked to the state names. I'm using a similar technique throughout the solution.
What I'd like to do is prepend this array with two options that are disabled, so that by default the select menu says something like "Please select a state" followed by a dash, both of which are disabled. If I weren't using QuickForm, the select would have the following as the first two options:
<option value="" disabled="disabled">Select a State</option>
<option value="" disabled="disabled">-</option>
Both options are disabled, and if the user leaves the option on the first value, the select widget submits an empty value which is made invalid by the form checking code.
Is there a way to do this with QuickForm?
Thanks,
Chuck
OK, after digging much deeper into the QuickForm documentation, I figured this out. The solution is to not populate the select widget with an array, but to build the select element manually add this to the form.
Originally, I had this:
function dbArray( $tableName, $fieldName ) {
$query = <<< EOT
SELECT `id`, `$fieldName`
FROM `$tableName`
ORDER BY `$fieldName`
EOT;
$link = connectToDatabase();
$result = mysql_query( $query, $link );
while ( $rec = mysql_fetch_assoc( $result ) );
{
$array[$rec['id']] = $rec[$fieldName];
}
return $array;
}
function statesArray() {
return dbArray( 'states', 'name' );
}
$form = new HTML_QuickForm( 'account', 'POST' );
$form->addElement( 'select', 'state_id', 'State:', statesArray() );
I did a version where array( 'none' => 'Please select a State' ) was prepended to the dbArray call before returning the array to the calling code, but this didn't make the option disabled. Adding a rule to confirm that the choice is numeric was the workaround ($form->addRule( 'state_id', 'You must select a state.', 'numeric' )). But I still didn't like that it was selectable. Here's the solution I found.
function statesSelect() {
$select = HTML_QuickForm::createElement( 'select' );
$select->addOption( 'Select a State', '', array( 'disabled' => 'disabled' ) );
$select->addOption( '-', '', array( 'disabled' => 'disabled' ) );
$statesArray = dbArray( 'states', 'name' );
foreach ( $statesArray as $id => $name ) {
$select->addOption( $name, $id );
}
return $select;
}
$form = new HTML_QuickForm( 'account', 'POST' );
$form->addElement( statesSelect() );
$form->addRule( 'state_id', 'You must select a state.', 'required' );
I hope this helps someone else. :)
Techinically, the best solution would be to use optgroup, but browsers usually won't default to this value, but instead to the first option in the select group.
Why not have your Select State have a value of "None" (similar to your given old-school solution) and have leave it enabled, then have the widget return the form as invalid if they leave it blank? Is this outside of the scope of QuickForm?
I think most users don't notice if something is enabled or disabled, and the only benefit of disabling is to make it un-selectable.
Is your goal geared toward validating the input? If so, why not just add some javascript between the form and QuickForm to check if the user has selected a disabled (or value="Null") element before submitting it?
Obviously I need to read the QuickForm documentation to get the full picture, but based on what I can get from your example, you could just add Please Choose State => None to the state_array and then have whatever form validator you plan to use not accept "None" as a valid input.
I have a form created with Symfony forms.
and in the template i have this selectbox, displayed on the page with the render method.
<?php echo $form['field']->render() ?>
is it possible to set the selected option of this select box?
Or does this have to be done in the class that creates this form?
There is the creation of the field done:
public function configure() {
$this->widgetSchema['field'] = new sfWidgetFormSelect(
array("choices" =>
array('1' => 'test1','2' => 'test2')
)
);
}
yes, sure — you should have set corresponding form value — either via bind(), either via widget's default option.
For example,
public function configure()
{
$this->widgetSchema['field'] = new sfWidgetFormSelect(array(
"choices" => array('1' => 'test1','2' => 'test2'),
'default' => 2));
}
Hope I've answered your question.