symfonynerds.com

Nerds who love the symfony-project

Archive for the ‘forms’ Category

So work is beginning in the symfonynerds camp on a few 1.1 apps (just in time to have to migrate to 1.2 :p) and I thought it was time to start documenting some of the little tips we have for it.

Today I was fine tuning an app for UAT and wanted to configure the ‘years’ being listed in a sfWidgetFormDate Date Select.

In the first instance, it was for a ‘date of birth’ field, so I was looking for a range from about 1900 to 2000. The first thing that came to mind was the php function range() but as per this ticket raised (which I commented on as well as posting here) doesn’t work because the array keys increment from 0… So if you selected 1900, your year would be submitted as 0.

One way around it is to create a variable of your own with keys and values for the years, then pass it as the ‘year’ option, like the below.

$years = range(1920, 2000); //Creates array of years between 1920-2000
$years_list = array_combine($years, $years); //Creates new array where key and value are both values from $years list
 
new sfWidgetFormDate(array('years' => $years_list))

Perhaps in the future Symfony could offer a way of automating this with ‘year_min’ and ‘year_max’ options for sfWidgetDormDate, or readers have a faster way of doing it.

  • 15 Comments
  • Filed under: 1.1, 1.2, forms, php, tip
  • Not written by anyone at Symfony Nerds HQ, but  despite this obviously flaw, it’s a good read! :D Get it here. It’s basically a “7 days” step through of the new form system, helped me as a primer for the first dabble with forms in 1.1 I made.

    I’ll also take this opportunity to appologise for the lack of 1.1 related articles appearing to date… This is driven purely by the fact the Symfony Nerds Data Centre (we’re yet to move to “the cloud” :p ) is still running 1.0 in the production environment, but we’re almost ready to begin migration to 1.1 and as of last week all our new apps will be coded in it, so more articles should be arriving soon. (Just don’t ask about the work I did on validating AJAX components of forms in 1.0 which is now useless!!!)

  • 2 Comments
  • Filed under: 1.1, forms
  • Symfony ‘time’ input field

    Unless I’m just going blind, there is no mention of this in the manual, but if you want to have a dropdown on your form for someone to input a time, there is a helper for it… just use:

    echo select_time_tag('cutover_time', 'now');

    The first arg is the name for the field, the second is the time to display. ‘Now’ means it will display the current (to your server) time when someone loads the form.

    If you’re also using a input_date_tag in the same form (quite likely you’d get a date and time together), then the helper will be automatically loaded for you, but if you just had this on a form without an input_date_tag you would also need to include somewhere:

    use_helper('DateForm');
  • 2 Comments
  • Filed under: 1.0, forms
  • This was meant to be a helpful post on getting an ajax observe_field working on a radiobutton_tag, but it is just as likely to lead to frustration, because there is a problem with prototype which means it won’t work as you may expect (more on that later), but it may still be useful for some, so here’s how you do it:

    I have used two radio buttons, one each for for ‘Yes’ and ‘No’. I originally thought you needed to specify the id as an option, but you don’t, it’s made up of the name and value of the radio button, so for the first one below the id is radio_but_yes

    echo radiobutton_tag('radio_but[]', 'Yes', false);
    echo ' Yes   ';
    echo radiobutton_tag('radio_but[]', 'No', true);
    echo ' No';

    Then you just have the usual overserve field, here duplicated for each dropdown. You’ll note I also set script to true as the content I show when selecting yes will also have Javascript in it.

    echo observe_field('radio_but_yes', array(
            'update' => 'lower_div',
            'url'       => 'order/Content',
            'with'     => "'type=' + value",
    	'script'   => 'true'
    ));
     
    echo observe_field('radio_but_no', array(
            'update'   => 'lower_div',
            'url'      => 'order/Content',
            'with'     => "'type=' + value",
    	'script'   => 'true'
    ));

    And of course your Div to display the content.

    echo '<div id="lower_div"></div>';

    As I said though, it seems there is a problem with prototype (the ajax library Symfony is using to do this) in that it only fires once… So in my case ‘No’ is the default, if someone selects ‘Yes’ the new fields I want will be displayed, however if they then change their mind and switch back to ‘No’ the fields will still be displayed…

    So for now, you’ll probabaly only want to use this if that doesn’t matter… for me it does, because mandatory fields will be shown, and if the user doesn’t want them, it will be frustrating that the form won’t submit until they’re completed, so in this case I’m going to just use a checkbox, or you could use a dropdown, both of these work fine.

  • 5 Comments
  • Filed under: 1.0, ajax, forms
  • Symfony Tip: 1.1 Model Building

    Consider this a twitter post more than blog material… but I am just playing around with Symfony 1.1 CRUD generation, and it seems there is an extra step from v1.0… After generating your model, but before trying to generate a CRUD, you need to run the command:

    symfony propel:build-forms

    If you don’t, then when you do a symfony propel-generate-crud, you will get the error:

    Fatal error: Class 'CustomerForm' not found in /usr/share/php/symfony/generator/sfAdminGenerator.class.php on line 722

    In the example above its Class ‘CustomerForm’ because Customer was the name of the class I chose to try and generate the form for.

    I’m off to do some more reading on forms/CRUD in 1.1, I’m getting the feeling it’s going to be a LOT different to 1.0….eHabib, you better add another offline package for what I just linked to I think, it will be my weeks reading in the can… I mean office… (ok I did mean can)

  • 5 Comments
  • Filed under: 1.1, forms, generators
  • Before I begin, this is not a general overview of object_select_tag, the book has a fair bit about it, but rather, details on using it to achieve a fairly specific objective I had…

    I needed:

    • A dropdown select
    • The dropdown to be populated with values from a DB table
    • Not using ALL the values from the DB table, only a subset
    • Include a blank entry at the start so an observe_field could be used on it to give magic AJAX powers to the dropdown (without a blank field, you can’t trigger a request on the first entry being selected unless you first select something else)

    I went through a few different attempts (which I will blog on later) before getting to this final one, but each came up short in meeting ALL of the above requirements at once. The answer was actually found by the one and only eHabib, but it impressed me so much I thought I would post on it first and steal his glory. :D

    Step 1: In the indexSuccess.php template

    echo object_select_tag('', '', array('name'=>'request_type', 'id'=>'request_type', 'related_class'=>'Property', 'peer_method'=>'getRequestTypes', 'include_blank'=>'true'));

    So to explain the above arguments (have a read of the API also):

    • ” - blank because in this case I don’t want to preselect any value in the list
    • ” - blank because, well, I _think_ because we specify the related_class it no longer needs this so is ignored (you can write anything in here) - be good if a reader has a comment on this…
    • ‘name’ and ‘id’ - to give a name and id to the dropdown as a form element
    • ‘related_class’ - the class of the model to look up
      ‘peer_method’ - the peer method (for the above class) written to return the result set wanted in the dropdown list (see below)
    • ‘include_blank’ - to give me the blank row at the start of the dropdown that I wanted

    Step 2: In the lib/model/PropertyPeer.php file:

    class PropertyPeer extends BasePropertyPeer
    {
      public static function getRequestTypes()
      {
        $c = new Criteria();
        $c->add(PropertyPeer::PROPERTY_TYPE_ID, '1');
        $request_types = PropertyPeer::doSelect($c);
        return $request_types;
      }
    }

    So this is my query on the Property table of the DB to return the values where property_type_id=1

    Step 3: In the lib/model/Property.php file:

    class Property extends BaseProperty
    {
      public function __toString()
      {
        return $this->getPropertyName();
      }
    }

    Our old friend __toString which gives us the PropertyName rather than the Id in the dropdown.

  • 8 Comments
  • Filed under: 1.0, Symfony MVC, forms
  • Symfony has an awesome feature that automatically re-populates your form for you without writing any code. All you have to do is specify it in your app/module/validate/myForm.yml file:

    fillin: 
      enabled: true

    So what happens if you have multiple forms on the same page? Well all you have to do is ensure that each one of your forms has ID and a Name:

    echo form_tag('mymodule/action', 'name=myForm id=myForm');

    Then in your yml validation file for that form, ensure that you specify the form name:

    fillin: 
      enabled: true
      param:
        name: myForm
    ....

    That’s it. Click here to read more about Symfony Form Validation.

    I don’t like the default symfony ‘down arrow’ to associated with a form error. So I want to make it look a bit more sexy. Here is what you need to do:

    1. Edit your application settings.yml file to overwrite the default ‘down’ arrow. The following settings indicate no prefix or suffix, but a CSS class ‘formerror’ which we will define later:

    all:
      .settings:
        #Form validator style settings
        validation_error_class:     formerror
        validation_error_prefix:    ''
        validation_error_suffix:    ''
        validation_error_id_prefix: error_for_

    2. Find a nice icon to use to display next to a field with an error. For example, I like this one:

    3. Update your CSS file to include a formerror class:

    .formerror{
       padding: 3px 20px 0px;
       background: url(../images/icon_sml_alert.png) no-repeat left bottom;
       color: red;
    }

    4. Now when you use the Symfony form helper to validate a field, it will automatically set the CSS class to ‘formerror’. For example;

    echo form_error('request_type');

    Will print (if the error is triggered)

    <div style="" class="formerror" id="error_for_request_type">Please specify the request type </div>

    So you get something looking a bit nicer than that ‘down’ arrorw:

    Looks hot! - I know you like it, now wipe off that drool on your keyboard and get back to work….