I have a User model with name and surname columns. I'm trying to create a selector in a form using sfWidgetFormDoctrineChoice, which by default only display the name values.
How can I modify the widget to display both the name and the surname? I know you can pass a query option when initializing the widget, but I cannot make it work:
$this->setWidget('user_id', new sfWidgetFormDoctrineChoice(array(
'model' => $this->getRelatedModelName('User'),
'query' => Doctrine_Query::create()->select('u.name, u.surname')->from('User u'),
'add_empty' => false)
));
Thanks!
Use the method option and create a public function of whatever method name that you want in your User model. An example might be:
$this->setWidget('user_id', new sfWidgetFormDoctrineChoice(array(
'model' => $this->getRelatedModelName('User'),
'method' => 'getFullName',
'add_empty' => false)
));
And then in your lib/model/Doctrine/User.class.php file
public function getFullName() {
return "{$this->getName()} {$this->getSurname()}";
}
Related
Im have ActiveRecord model and view for update form of this model. Also I have getter and setter in model class that looks like this
public function setTopvisorGoogleRegion($value)
{
$this->myvalue = $value;
return(true);
}
public function getTopvisorGoogleRegion()
{
return([1 => '123']); //I return this array for show you essence of the problem
}
Following logic in this code $model->topvisorgoogleregion must return [1 => '123']
In view I have next code
<?php echo($form->field($model, topvisorgoogleregion)->textInput());?>
<?php echo $form->field($model, 'topvisorgoogleregion')->widget(Select2::classname(), [
'data' => [1 => '123', 2 => '456'],
'options' => [
'id'=>'projectCtrl',
'placeholder' => 'Select option',
'multiple' => true
],
'pluginOptions' => [
'allowClear' => true,
'tags' => true,
],
]);
?>
When I open form I want to see option 1 => '123' already selected in Select2. Its logically because when already existing record is updating, ActiveRecord get data that already stored in model (in this case using getter) and fill fields in view with this data (In first field that using textInput I see text 'Array' because getter in model returns array). But Select2 is empty when I open update page. Whats going wrong?
If I delete first field (textInput) nothing changes
I find the solution - in getter I need provide ActiveQuery object, not array. I dont know why and how it works, but it works
I am new to yii2 and trying to get around. I have a dropdownlist whose values in the database are enum. So when the crud was created the dropdownlist had the enum values.
But I want to keep one value selected as default in the drop down list.
My form code is below:
<?= $form->field($model, 'priotiy_level')->dropDownList([ 'low' => 'Low', 'medium' => 'Medium', 'high' => 'High', ], ['prompt' => 'Select Priority Level']) ?>
Instead of the prompt, I want to have medium as a selected value. Can someone please help me with this?
Thank you.
After initialization of the $model instance in your controller set the attribute and then pass $model to view.
$model->priority_level = 'medium';
As #Bizley said, you need to set the value of the attribute in your Controller. In Yii2, you can do that with in one line:
public function actionSomething {
$model = new MyClass(['priotiy_level' => 'medium']);
// code
return $this->render('something', [
'model' => $model
]);
}
Additionally to previous answers you can also use default validator:
class SomeActiveRecord extends ActiveRecord {
// ...
function rules(){
return [
['priotiy_level', 'default', 'value' => 'medium']
// set "username" and "email" as null if they are empty
[['username', 'email'], 'default'],
// set "level" to be 1 if it is empty
['level', 'default', 'value' => 1],
];
}
}
More details see here: Handling Empty Inputs.
This code sets default value for the all actions/forms. If you need different default values on different forms, can be used also scenarios of validation.
Give class to your dropdownList :
Ex.
<?= $form->field($model, 'priotiy_level')->dropDownList([ 'low' => 'Low', 'medium' => 'Medium', 'high' => 'High', ], ['class' => 'priority_list','prompt' => 'Select Priority Level']) ?>
Give Default value using Java Script or Jquery
Ex.
<script>
$(".priority_list").val('medium'); // assing value using jquery
</script>
You can also use ID:
Ex.
<script>
var temp=document.getElementById('project-industry_id');
temp.value='medium';
</script>
I am using Doctrine 2 in my Zend Framework 2 Project. I have now created a Form and create one of my Dropdowns with Values from the Database. My Problem now is that I want to change which values are used and not the one which I get back from my repository. Okay, here some Code for a better understanding:
$this->add(
array(
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'county',
'options' => array(
'object_manager' => $this->getObjectManager(),
'label' => 'County',
'target_class' => 'Advert\Entity\Geolocation',
'property' => 'county',
'is_method' => true,
'empty_option' => '--- select county ---',
'value_options'=> function($targetEntity) {
$values = array($targetEntity->getCounty() => $targetEntity->getCounty());
return $values;
},
'find_method' => array(
'name' => 'getCounties',
),
),
'allow_empty' => true,
'required' => false,
'attributes' => array(
'id' => 'county',
'multiple' => false,
)
)
);
I want to set the value for my Select to be the County Name and not the ID. I thought that I would need the 'value_options' which needs an array. I tried it like above, but get the
Error Message: Argument 1 passed to Zend\Form\Element\Select::setValueOptions() must be of the type array, object given
Is this possible at all?
I was going to suggest modifying your code, although after checking the ObjectSelect code i'm surprised that (as far as I can tell) this isn't actually possible without extending the class. This is because the value is always generated from the id.
I create all form elements using factories (without the ObjectSelect), especially complex ones that require varied lists.
Alternative solution
First create a new method in the Repository that returns the correct array. This will allow you to reuse that same method should you need it anywhere else (not just for forms!).
class FooRepository extends Repository
{
public function getCounties()
{
// normal method unchanged, returns a collection
// of counties
}
public function getCountiesAsArrayKeyedByCountyName()
{
$counties = array();
foreach($this->getCounties() as $county) {
$counties[$county->getName()] = $county->getName();
}
return $counties;
}
}
Next create a custom select factory that will set the value options for you.
namespace MyModule\Form\Element;
use Zend\Form\Element\Select;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\FactoryInterface;
class CountiesByNameSelectFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $formElementManager)
{
$element = new Select;
$element->setValueOptions($this->loadValueOptions($formElementManager));
// set other select options etc
$element->setName('foo')
->setOptions(array('foo' => 'bar'));
return $element;
}
protected function loadValueOptions(ServiceLocatorInterface $formElementManager)
{
$serviceManager = $formElementManager->getServiceLocator();
$repository = $serviceManager->get('DoctrineObjectManager')->getRepository('Foo/Entity/Bar');
return $repository->getCountiesAsArrayKeyedByCountyName();
}
}
Register the new element with the service manager by adding a new entry in Module.php or module.config.php.
// Module.php
public function getFormElementConfig()
{
return array(
'factories' => array(
'MyModule\Form\Element\CountiesByNameSelect'
=> 'MyModule\Form\Element\CountiesByNameSelectFactory',
),
);
}
Lastly change the form and remove your current select element and add the new one (use the name that you registered with the service manager as the type key)
$this->add(array(
'name' => 'counties',
'type' => 'MyModule\Form\Element\CountiesByNameSelect',
));
It might seem like a lot more code (because it is) however you will benefit from it being a much clearer separation of concerns and you can now reuse the element on multiple forms and only need to configure it in one place.
I'm creating a form for a logged-in user to change their password, so I created a subclass of an existing password-reset form I have available. The forms will be identical except with an additional field for existing password. It's worked so far, except I can't figure out a way to manually set the order the new field; the only place I've gotten it to appear is at the end of the form. It seems that ZF2 requires you to add() form elements in the order that you want them rendered. I would do so, except the subclass form's constructor must the parent form's constructor before it can add new fields, by which point the parent form has already added its fields.
I have already tried setting the property order of my new field, but it did not work; I've tried several different combinations (I can't find the documentation for this feature anywhere, after lots of searching).
Subclass constructor snippet:
class ChangePassword extends ResetPassword implements InputFilterProviderInterface {
public function __construct() {
parent::__construct();
$this->add(array(
'type' => 'Zend\Form\Element\Password',
'name' => 'existingPassword',
'order' => 0,
'options' => array(
'label' => 'Existing Password',
'order' => 0,
),
'attributes' => array(
'required' => 'required',
'order' => 0,
)
));
}
Parent constructor snippet:
class ResetPassword extends Form implements InputFilterProviderInterface {
public function __construct() {
parent::__construct('reset-password');
$this->add(array(
'type' => 'Zend\Form\Element\Password',
'name' => 'password',
...
The key you're looking for which affects element order is named priority.
The form add() method accepts a second array containing $flags, and it's in this array that you must add the priority key/value pair.
Your constructor should end up looking something like this ...
class ChangePassword extends ResetPassword implements InputFilterProviderInterface {
public function __construct() {
parent::__construct();
$this->add(array(
'type' => 'Zend\Form\Element\Password',
'name' => 'existingPassword',
'options' => array(
'label' => 'Existing Password',
),
'attributes' => array(
'required' => 'required',
)
), // add flags array containing priority key/value
array(
'priority' => 1000, // Increase value to move to top of form
));
}
}
I have encouter this issue today, Crisp's answer helped but I think it would be nice to precise this :
In the view we have a lot of options to show our form :
<?= $this->form($form)?>
<?= $form->get('{element}') ?>
loop over $form->getIterator()
loop over $form->getElements()
etc...
I have to say i used a lot this structure in all of my projects :
<?php foreach ($form->get('fieldset')->getElements() as $elementName => $element): ?>
<?= $this->partial('partial/formElement', ['element' => $element])?>
<?php endforeach ?>
The problem is : getElements does not use priority, so its just give the element in order of when it was instanciated.
In the view we have to use the iteration method ($form->getIterator()) to get back this flag priority.
I am trying to use the TbEditableColumn and the type select to have a pulldown menu.
The pulldown menu I need is filled by a function that I call.
That is working for basic cases. But for a another column, the pulldown values are dependent from the row in which it is (grid-view).
So for example the function I want to call to fill the pulldown and pass the id of the current data is:
$model->getPulldownValues($data->id)
But that throws an error that the variable $data is not defined. The funny part is that outside the editable array, I can use $data as expected.
See example below:
Any ideas?
$this->widget('bootstrap.widgets.TbExtendedGridView', array(
'type' => 'striped bordered',
'id'=>'order-image-grid',
'dataProvider'=>$model->search(),
'ajaxUpdate'=>true,
'template' => "{items}\n{extendedSummary}",
'rowCssClassExpression'=>'"FMDBGridColumn".$data->order_error',
'columns'=>array(
array(
'class' => 'bootstrap.widgets.TbEditableColumn',
'name' => 'streets',
'htmlOptions'=>array('width'=>'150'),
'value' => 'CHtml::value($data, "street")',
'editable' => array(
'type' => 'select',
'source' => CHtml::listData($model->availableStreets($data->id), 'id', 'street'),
'url' => $this->createUrl('cities/editable'),
'placement' => 'right',
)
),
),
));
Try to change method "availableStreets" into getter, e.g.:
public function getAvailableStreets()
{
// we don't need to send id as parameter of method,
// we can get it directly from model
// e.g.: $id = $this->id;
//
// put your code here
}
then, in widget, use property
$model->availableStreets
instead of method
$model->availableStreets($id)
Also you can put
CHtml::listData() into your getter and use
'source' => 'availableStreets',
instead of
'source' => CHtml::listData($model->availableStreets($data->id), 'id', 'street'),
you have to consider that $data in 'value' => 'CHtml::value($data, "street")', is referring to a model object which $model->search() is providing, but $data outside of the grid is different(You haven't shared what that is).