logo
Ask your Symfony questions! Pay money and get answers fast! (more info)

Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.

If the asker does not get an answer then they have 10 days to request a refund.

$75
Autocomplete and symfony forms

I'm using symfony 1.3/doctrine 1.2. I have a situation where users in my system can send out email messages to multiple recipients, and messages are saved to the db. There are three relevant tables:

- Messages
- Recipients (to/cc) in another.
- Contacts/address book table

I implemented an autocomplete function (jquery autocomplete 1.1, not jquery ui autocomplete 1.8) that is working about 95% about how I want it to work, using the sfFormExtra plugin sfWidgetFormJQueryAutocompleter. Basically, I want it to work just like gmail's autocomplete - you can choose from your address book or type in some other address.

There is nothing that I need to do with setting hidden IDs using the autocomplete - whatever text is input to the to field will be split on commas, each field set as a recipient, and then saved that way.

Here are my issues:
- By default, the value of the field is "Array"
- I cannot set a default "to" value on the form using the normal style of $this->setDefaults(array('to_list' => $this->getOption("default_to")));

I haven't gotten to actually saving the message in the db either yet, so if there are any issues there, please consider. Thanks.

Do I need to use a different widget since my use case is not comprised only of items from the database? I'm familiar with http://snippets.symfony-project.org/snippet/336 , but like I said sometimes I need to be able to just type in an address so that doesn't exactly fit the scenario.


Abbreviated schema:

Contact:
columns:
name: { type: string(150) }
email: { type: string(150) }

Email:
columns:
subject: { type: string(150), notnull: true }
body: { type: clob(65532), notnull: true }
relations:
To: { class: Recipients, local: id, foreign: email_id, refClass: To }

Recipient:
columns:
email_id: { type: integer }
type: { type: string(5) }
recipient: { type: string(200) }
relations:
Email: { local: email_id, foreign: id }

To:
inheritance:
extends: Recipient
type: column_aggregation
keyField: type
keyValue: to

Cc:
inheritance:
extends: Recipient
type: column_aggregation
keyField: type
keyValue: cc



lib/form/doctrine/EmailForm.php

class EmailForm extends BaseEmailForm
{
public function configure()
{
sfProjectConfiguration::getActive()->loadHelpers(array('Url'));
$this->widgetSchema['to_list'] = new sfWidgetFormChoice(return array(
'choices' => NULL,
'renderer_class' => 'sfWidgetFormJQueryAutocompleter',
'renderer_options' => array(
'url' => sfContext::getInstance()->getController()->genUrl('@address_autocomplete'),
'config'=>
'{
width: 320,
max: 10,
highlight: false,
scroll: true,
scrollHeight: 150,
minChars: 2,
multiple: true,
multipleSeparator: ",",
parse: function(data) {
var parsed = [];
for (var i = 0; i < data.length; i++) {
parsed[parsed.length] = {
data: data[i],
value: data[i].Contact.email,
result: "\"" + data[i].Contact.first_name + " " + data[i].Contact.last_name + "\" <"+data[i].Contact.email+">"
};
}
return parsed;
},
formatItem: function(row) {
return row.Contact.last_name + ", " + row.Contact.first_name +" - <i>"+ row.Contact.Account.name +"</i> <br/>" + row.Contact.email;
}
}'
),
));

This question has been answered.

webguy | 03/16/11 at 1:32pm Edit

Previous versions of this question: 03/20/11 at 12:04pm | 03/20/11 at 12:04pm | 03/23/11 at 12:06pm

(1) Responses

See a threaded view of answers?

Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.

  • avatar
    Last edited:
    04/06/11
    12:15am
    Jakub Zalas says:


    Firstly, you need to add a validator for every field. It's one of the changes in the configure() method. Second is setting defaults.

    Next you can overload the doUpdateObject() to create Recepients out of values taken from your autocomplete field.

    There's something wrong with your model definition. Doctrine didn't generate all the needed setters. Only setRecepient() is present in my case. It requires passing Doctrine_Collection and that's what I did in updateRecepients() method. Once you clean this up you might want to change this to something more common (see http://www.doctrine-project.org/projects/orm/1.2/docs/manual/working-with-models/en).

    I simply split recipients by commas and directly put it into the database. You might also consider to clean the input a bit before putting those values into the database. I guess best way is implementing custom validator and replacing sfValidatorString I used.


    class EmailForm extends BaseEmailForm
    {
    public function configure()
    {
    sfProjectConfiguration::getActive()->loadHelpers(array('Url'));
    $this->setDefaults(array('to_list' => $this->getOption('default_to')));
    $this->validatorSchema['to_list'] = new sfValidatorString();
    $this->widgetSchema['to_list'] = new sfWidgetFormChoice(array(
    'choices' => NULL,
    'renderer_class' => 'sfWidgetFormJQueryAutocompleter',
    'renderer_options' => array( // [....] ),
    ));
    }

    protected function doUpdateObject($values)
    {
    parent::doUpdateObject($values);

    $this->updateRecepients($values);
    }

    protected function updateRecepients($values)
    {
    $email = $this->getObject();
    $toCollection = new Doctrine_Collection('To');

    $toList = explode(',', $values['to_list']);

    foreach ($toList as $recipient)
    {
    if (!empty($recipient))
    {
    $to = new To();
    $to->setRecipient($recipient);
    $to->setEmail($this->getObject());
    $toCollection->add($to);
    }
    }

    $email->setRecipient($toCollection);
    }
    }


    Here's an example action I used to test the solution (index) and a mock of autocomplete action (auto). Notice how I passed default_to value.


    public function executeIndex(sfWebRequest $request)
    {
    $this->form = new EmailForm(null, array('default_to' => 'my default'));

    if ($request->isMethod('post'))
    {
    $parameters = array_merge(
    $request->getParameter($this->form->getName()),
    $request->getParameter('autocomplete_email', array())
    );

    if ($this->form->bindAndSave($parameters))
    {
    print_r($this->form->getValues());
    die('saved!');
    }
    }

    public function executeAuto(sfWebRequest $request)
    {
    $this->getResponse()->setContent(json_encode(array(
    array('Contact' => array('first_name' => 'name1', 'last_name' => 'last1', 'email' => 'kuba1@zalas.pl', 'Accou
    array('Contact' => array('first_name' => 'name2', 'last_name' => 'last2', 'email' => 'kuba2@zalas.pl', 'Accou
    )));
    return sfView::NONE;
    }
    }


This question has expired.





Current status of this question: Completed



Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.

If the asker does not get an answer then they have 10 days to request a refund.