Symfony2 array of custom objects into form fields - arrays

I get some data from an API inside my Symfony 2 application using Guzzle. Those data are properly mapped into my model. The model is a Contact object with some properties. One of those property is an array of ContactMethod done like this
/**
* #SerializedName("methods")
* #Type("array<My\Bundle\Model\ContactMethod>")
*/
private $methods;
The ContactMethod object has just two properties: type and value
class ContactMethod {
/**
* #SerializedName("type")
* #Type("string")
*/
private $type;
/**
* #SerializedName("value")
* #Type("string")
*/
private $value;
... setters and getters ...
I've created a ContactType with its buildForm function in order to display all the property of Contact in a form. But when it comes to display the methods property I would like to have a TextInput for each of the ContactMethod and that input should take the type as label and the value as value.
class ContactType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options = array())
{
$builder
->add(...all the other simple fields...)
->add(...what shall I add here ? )
I also need this to work in the opposite way: when all the text inputs are filled and submitted, the fields has to be packed together into an array of ContactMethod so I can reserialize and send back the data to the API.
I've tried to play around with custom form types and also Data Transformers but I could not find a solution.

Your Contact object is mapped onto one ContactType, so just add a property methods and its type (e.g.) "method_list" if it's declared as a service or just new MethodListType().
The list is dynamic, so you have to write your own buildView method for the new Type.

Related

Laravel change models table right before query

I need to change the queried table from a Laravel-model right before the query begins.
Normally you make a query like this:
ExampleModel::where('column_name', =, 'value')->get();
For one case I want to use a view-table which contains information from multiple tables combined in one view.
Therefore I need to switch the table of ExampleModel only for this one situation, e.g.:
ExampleModel::table('my_view')->where(...)->get();
It is not an option to use DB::table('my_view')->where(...)->get() because of several local scopes which need to be applied on ExampleModel.
As I could see, there are the following options:
somehow change the models table-name on the fly (as shown above)
Create a new Model used only in this use case which has the view defined as model-table
write all my scopes into a chained DB-command
Are there any other options?
The laravel way to Handle this would be to have a dedicated model for your view, with Scopes applying to each of the relevant models :
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class AgeScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* #param \Illuminate\Database\Eloquent\Builder $builder
* #param \Illuminate\Database\Eloquent\Model $model
* #return void
*/
public function apply(Builder $builder, Model $model)
{
$builder->where('age', '>', 200);
}
}
Then in your ExampleModel AND you MyView Model
protected static function boot()
{
parent::boot();
static::addGlobalScope(new AgeScope);
}
So that when you want to edit a scope it will be reflected on each of your queries
BUT
You will allways know if your model is from your view_table or from you example_model table.
If you need to have some accessor or function used by both, I recomand you to put them in a Trait and use them on both Models
trait ExampleModelTrait
{
getTestAttribute(){
return strtolower($this->column_name);
}
}
and then
use ExampleModelTrait;
you can do this stuff by passing table name to setTable() method for example :
$user = new Users();
$user->setTable('customers');
$user->where(id,1)
...

Registration form with new fields related

i am trying to add fields to my registration form with FosUserBundle.
Adding normal fields to the Userclass like "name", "age" e.g is easy to do:
class RegistrationFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
// add your custom field
$builder
->add('name')
;
}
public function getParent()
{
return 'fos_user_registration';
}
public function getName()
{
return 'acme_user_registration';
}
}
This is all working and the new fields are written to my database table.
But how do i add there a new FormType into the Registration type of the Fos Bundle, like:
A user can have an Address, which is related OneToMany.
I tried it with the following, by first creating the address class and giving him one user:
/**
* #ORM\ManyToOne(targetEntity="User", inversedBy="addresses")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
protected $user;
And then by adding addresses to the User class:
/**
* #ORM\OneToMany(targetEntity="Address", mappedBy="user")
*/
protected $addresses;
public function __construct()
{
parent::__construct();
// your own logic
$this->addresses= new ArrayCollection();
}
Adding the AddressType:
class AddressType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('state', 'text')
->add('city','text')
->add('zipcode', 'text')
->add('street', 'text');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\UserBundle\Entity\Address',
));
}
public function getName()
{
return 'address';
}
}
to the RegistrationFormType works and the fields are displayed in the browser:
public function buildForm(FormBuilderInterface $builder, array $options)
{
// add your custom field
$builder
->add('name')
->add('addresses', new AddressType())
;
}
But when i try to submit the form with new data, i don't know how to say symfony that the address entered should be related to the User.
Im always getting the error:
"The form's view data is expected to be an instance of class Acme\UserBundle\Entity\Address, but is an instance of class Doctrine\Common\Collections\ArrayCollection. You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms an instance of class Doctrine\Common\Collections\ArrayCollection to an instance of Acme\UserBundle\Entity\Address."
What am I doing wrong here?
Regards.
you're trying to add a collection as a single field, when you give a "data_class" you're saying "here this is the form for this entity", but as the error says the system has to manage a collection of forms each one related to a single entity, you need to data transform them to something he can manage in a simple (or prebuilt) way (look for DataTransformers)
or you can use the colletion field type and pass them the address form type
-- edited after the comment --
no, sorry i've missed that, you need an entity form type because you state that a user has one address (and many user can be mapped to the same address, i.e. a family), so there's no need of a collection, though you're in the owning side persisting the user you don't have to worry, if you say cascade persist in your mapping schema for the ManyToOne relation, Doctrine will store the address for you (or use an existing one in case of a matching one)
btw i was fuzzed by your sentence "A user can have an Address, which is related OneToMany." that's misleading, a user can have an address, which is related to a ManyToOne relation (many user can have an address), the address is in a oneToMany relation with users (an address is own by many users)

Joomla 3 custom field get xml field

I am creating a custom field to create an array of input images as media type.
How can I bring back the input array with type media?
class JFormFieldimglist extends JFormField {
//The field class must know its own type through the variable $type.
protected $type = 'imglist';
public function getLabel() {
return "List Image";
}
public function getInput() {
for ($i = 1; $i <= 10; $i++) {
$images.= '<input type="text" value="'.$this->value[$i].'" name="'.$this->name.'['.$i.']" />';
}
return $images;
}
}
From xml i use this
<field name = "myimage" type = "media" directory = "stories" />
There are two issues. The first issue is your extending the core JFormField class. The second issue is the media field type is actually a modal form field. This is a special kind of field which is used to present a more complicated interface in a modal window for the user to select. Examples of this are when you select an Article for a Menu Type Single Article, or click the Image button located underneath the WYSIWYG editors.
My guess is you want to pull in a list of images from a specific folder for the user to select from a drop down. In the example below notice I have completely omitted the getLabel() and getInput() methods and added getOptions(). The reason being is by extending the JFormFieldList class those methods are already built out and outside of special requirements are not needed. You simply override the getOptions() method to provide the core class the list of option you want to be presented in the field.
jimport('joomla.form.helper');
JFormHelper::loadFieldClass('list');
class JFormFieldimglist extends JFormFieldList {
//The field class must know its own type through the variable $type.
protected $type = 'imglist';
public function getOptions() {
// build out your options array
// You should format as array, with full path as key and
// human readable as value
$options = array('/images/flowers/tulip.png' => 'Tulip');
return $options;
}
}
Here are some links for expand on my post.
http://docs.joomla.org/Creating_a_custom_form_field_type
http://docs.joomla.org/List_form_field_type
http://docs.joomla.org/Creating_a_modal_form_field

getting Value of a field by its Name in apex salesforce

in my visualforce page i have some campaign object first user select an object then there is a multi picklist. in this picklist there is Label for all the fields user selects some fields then i have to show the value of these fields in the selected campaign object
for showing multiple picklist my apex function is
public List<SelectOption> getOptionalFields(){
Map <String, Schema.SObjectField> fieldMap= Campaign.sObjectType.getDescribe().fields.getMap();
List<SelectOption> fieldsName =new List<SelectOption>();
for(Schema.SObjectField sfield : fieldMap.Values())
{
schema.describefieldresult dfield = sfield.getDescribe();
fieldsName.add(new SelectOption(dfield.getName(),dfield.getLabel()));
}
but i have no idea how to show value for the the field
for exmple i have object instance like
Campaign c;
now i have to get value of any field whose Name is in string form.how to get corresponding value for that field.one solution is just write like
say
String fieldName;
and use multiple if
if(fieldName=='Name')
c.Name=
if(fieldName=='Id')
c.Id=
is there any other convenient method??please explain!!
You need to read about "dynamic apex". Every "concrete" sObject (like Account, Contact, custom objects) can be cast down to generic sObject (or you can use the methods directly).
Object o = c.get(fieldName);
String returnValue = String.valueOf(o);
There are some useful examples on dynamic get and set methods on Salesforce-dedicated site: https://salesforce.stackexchange.com/questions/8325/retrieving-value-using-dynamic-soql https://salesforce.stackexchange.com/questions/4193/update-a-records-using-generic-fields (second question is a bit more advanced)
You'll still need to somehow decide when to return it as String, when as number, when as date... Just experiment with it and either do some simple mapping or use describe methods to learn the actual field type...

Sorting a CellTable server-side

I'm currently using a Gwt CellTable, bound to my GAE/Objectify backend via RPC calls.
All right now! :-)
Then I want to sort columns, so I read http://code.google.com/intl/it-IT/webtoolkit/doc/latest/DevGuideUiCellTable.html#columnSorting
The Async Remote sorting sections shows very well how to get sorting into my AsyncDataProvider but... how can I retrieve the name of the column the user wants to sort?
It shows this code: ColumnSortList sortList = table.getColumnSortList();
But how can I get String names from that? I simply want to know "surname" or "soldDate", the name of the field the column is bound to! Then I will pass it to my rpc service, and use it to sort data server-side query(...).order(<field_name>)
Am I missing something?
UPD: interesting stuff here: http://groups.google.com/group/google-web-toolkit/browse_thread/thread/77a0eaf8086218a6/effb8d3abe69270b#effb8d3abe69270b
You can keep a list of column names ordered as they are in the table:
List<String> columnNames = new ArrayList<String>();
table.addColumn(surnameColumn, "surname");
columnNames.add("surname");
// add the other columns
Then when you need to get the sort column name:
String sortColumnName;
ColumnSortList sortList = table.getColumnSortList();
if (sortList != null && sortList.size() != 0){
Column <MyEntity, ?> sortColumn = (Column <MyEntity, ?>)
sortList.get(0).getColumn();
Integer columnIndex = table.getColumnIndex(sortColumn);
sortColumnName = columnNames.get(columnIndex);
}
// do your rpc call
*where MyEntity is your data object displayed in the cell table.
A bit late to the party, but here's a more straight-forward solution based off of the current documentation (see section 'ColumnSorting with AsyncDataProvider').
When we're adding our columns we can simply set the dataStoreName:
TextColumn<MyData> surname = new TextColumn<MyData>() {
...
}
surname.setSortable(true);
surname.setDataStoreName("surname"); // Set the column name
table.getColumnSortList().push(surname);
table.addColumn(surname, "Last Name"); // eg. A different name for the UI
Then we can retrieve the column's dataStoreName later when sorting:
#Override
protected void onRangedChanged(HasData<MyData> display) {
...
ColumnSortList.ColumnSortInfo info = table.getColumnSortList().get(0);
String sortColumn = info.getColumn().getDataStoreName(); // Get the column name
boolean sortIsAscending = info.isAscending();
rpcService.requestMyData(
sortColumn,
sortIsAscending,
new AsyncCallback<ArrayList<MyData>>() {...}
);
...
}
Using this method we can pass the column name directly to our RPC method. It even allows us to use a different name (eg. the database column name) than the column name used on the UI/client side.
I have used something like this as an application column object.
public class ScrollTableColumn
{
// --------------------------------------------------------------- Field(s)
private int sequence;
private Column column;
private Header header;
private int size;
private int calculatedSize;
private boolean show;
private PartialColumn partialColumn;
private ColumnNameEnum columnName;
}
Now create a HashMap of the above as follows:
Map<Column, ScrollTableColumn> columnMap
= new HashMap<Column, ScrollTableColumn>();
Add all the columns as you create them both in the ScrollTableColumn and in the columnMap.
Finally you can get the required name as:
ColumnSortList sortList = dataTable.getColumnSortList();
Column<?, ?> column = sortList.get(0).getColumn();
ColumnNameEnum = columnMap.get(column);
String name = ColumnNameEnum.getName();
The proper way is to extend the base column class which will allow you to override cell rendering, pass in column configuration via your constructor, and most importantly set the DataStoreName which is where you should store the field name for the column. Lastly you should not reuse the onrangechanged fire, but access the columnsort handler directly by overriding it. on range change and column sort handler should call some type of method that you have to update your grid. I call mine updateGrid for sanity. This allows you to set any grid parameters used by your async request to specific sort column and direction. The main reason you want to use column sort handler is to access the ColumnSort event which contains your sort direction information
your column class that extends the base GWT column. You can also extend date or number columns too.
public GridStringColumn(String fieldName, String text, String tooltip, boolean defaultShown, boolean sortable, boolean hidden) {
super(new TextCell());
setDataStoreName(fieldName);
this.text_ = text;
this.tooltip_ = tooltip;
this.defaultShown_ = defaultShown;
setSortable(sortable);
this.hidden_ = hidden;
}
create your handler
dataGrid.addColumnSortHandler(new DataGridSortEvent());
your sort event class
protected class DataGridSortEvent implements ColumnSortEvent.Handler {
#Override
public void onColumnSort(ColumnSortEvent event) {
ColumnSortList sortList = dataGrid_.getColumnSortList();
if (sortList != null && sortList.size() > 0) {
Column<T, ?> sortColumn = (Column<T, ?>) sortList.get(0).getColumn();
LOG.info("col_sorta: " + event.isSortAscending());
LOG.info("col_index: " + sortColumn.getDataStoreName());
updateDataList();
}
}
}
updateDataList is your method you use to make the actual AJAX request to your server side. rather then logging you sould store this info in private members of your datagrid class so that your request can parameterize them.
you could also make this work for local caching too, just make a copy of the data from your server locally then return a sorted collection of that cached collection, rather then calling the updateDataList method.
Now you do not need to store a separate list for just string names, which is waste of memory not to mention a synchronicity issue if the column order is change from user interaction or whatever.

Resources