Styling a Register Page with Custom Attribute Fields

Permalink 1 user found helpful
Hey all,

I'm looking to design my registration form (along with its numerous custom attribute fields) to match a pretty specific layout design. I've already copied over the register.php as single page and began editing it in that way, however when I get to the point of rendering all of my custom attributes via this:

foreach($attribs as $ak) { 
    print '<div class="registration-field">';
    print $af->display($ak, $ak->isAttributeKeyRequiredOnRegister());   
    print '</div>';               }


I'm wishing I had the flexibility to wrap certain custom attributes like the 'address' field in a different div class so that I can style it differently than normal fields.

I'm considering manually listing out all of the custom form fields rather than rendering in a foreach, ie something like:

<div class="registration-field">
    <div class="address-field">
        <?php echo $form->label('akID[19][address1]', t('Address 1') )?>
        <?php echo $form->text('akID[19][address1]')?>
    </div>
</div>


Which I believe will work so long as I make sure the labels, ids and names match the attribute IDs. But I was wondering if anyone knows of a more elegant solution?

Thanks.

 
jordanlev replied on at Permalink Best Answer Reply
jordanlev
Try this:
<div class="registration-field">
    <div class="address-field">
        <?php $fieldName = 'akID[' . UserAttributeKey::getByHandle('address1')->getAttributeKeyID() . '][value]'; ?>
        <?php echo $form->label($fieldName, t('Address 1')); ?>
        <?php echo $form->text($fieldName); ?>
    </div>
</div>


EDIT: Had a small typo in code --passed the wrong handle to getByHandle() -- now fixed.

And see these links for more info than you probably ever wanted to know about customizing the registration and login pages:
http://www.concrete5.org/community/forums/customizing_c5/i-am-re-co...
http://www.concrete5.org/community/forums/themes/customizing-login-...
Flight643 replied on at Permalink Reply
Hey Jordan,

That works perfectly! Thank you. I'm pretty new to C5 so sorry if this is obvious to piece together, but if I use your code on a custom user attribute that is a select drop down, do you know how I would retrieve the drop down options supplied from the admin end to populate the options?

Thanks again!
jordanlev replied on at Permalink Reply
jordanlev
Heh... actually the select attributes are really complicated. I've only done this with page attributes, not user attributes, so I'm not 100% sure this code works, but try it:
<?php
Loader::model('attribute/type');
Loader::model('attribute/categories/user');
$ak = UserAttributeKey::getByHandle('your_handle');
$satc = new SelectAttributeTypeController(AttributeType::getByHandle('select'));
$satc->setAttributeKey($ak);
$attrOptions = $satc->getOptions();
$dropdownOptions = array('0' => t('--Choose--'));
foreach ($attrOptions as $ao) {
    $dropdownOptions[$ao->ID] = htmlentities($ao->value);
}
$dropdownFieldName = 'akID[' . $ak->getAttributeKeyID() . '][value]';
echo $form->select($dropdownFieldName, $dropdownOptions);
?>


I'd probably put all of the code except for the output of the dropdown up near the top of my file, and only put the last line into my form markup, just to keep things cleaner (but that's just a code style thing -- not necessary).

See this thread for more details (although this thread is about collection attributes -- i.e. page attributes):
http://www.concrete5.org/community/forums/customizing_c5/how-to-wan...
Flight643 replied on at Permalink Reply
Very cool! That worked. I'm with you, I crammed the extra code to the top of the page so my actual form at least looks a little more elegant :).

Thank you very much for the help and links.. it's immensely appreciated (and hey, I think I even learned a few things :)
invision replied on at Permalink Reply
invision
I'm building a custom reg form, and thanks to your help I have everything working, EXCEPT the select. The dropdown appears, and is populated with the values entered in the dashboard, but the form will NOT capture the values and store them to the database.

<?php
   Loader::model('attribute/type');
   Loader::model('attribute/categories/user');
   $ak = UserAttributeKey::getByHandle('job_status');
   $satc = new SelectAttributeTypeController(AttributeType::getByHandle('select'));
   $satc->setAttributeKey($ak);
   $attrOptions = $satc->getOptions();
   $dropdownOptions = array('0' => t('--Choose--'));
   foreach ($attrOptions as $ao) {
      $dropdownOptions[$ao->ID] = htmlentities($ao->value);
   }
   $dropdownFieldName = 'akID[' . $ak->getAttributeKeyID() . '][value]';
   echo $form->label($dropdownFieldName, t('Job Status') );
   echo $form->select($dropdownFieldName, $dropdownOptions);
?>


The only difference in my code is the label, but the form doesn't capture the value without it there, so that shouldn't matter.

Any suggestion on troubleshooting?
jordanlev replied on at Permalink Reply
jordanlev
Hmm... It certainly looks like your code should work. Stupid question: is the $form->select() call inside the <form> tag?
invision replied on at Permalink Reply 1 Attachment
invision
Form tag? Why didn't I think of that?

Just kidding. As I said, the form loads properly and pulls the values from the database, but just won't submit the select element value.

The only other variation from the default reg page is that I have the form elements embedded in fieldset tags:

<form method="post" id="register" action="<?php echo $this->url('/register', 'do_register')?>">
<fieldset id="loginInfo">...
<div id="registerSubmit">
   <?php echo $form->submit('register', t('Register'))?>
   <?php echo $form->hidden('rcID', $rcID); ?>
</div>
    </fieldset>
</form>
<?php  } ?>


It's probably something obvious, but I'm not catching it.

For your viewing pleasure, I've attached the entire register.php file zipped.

Sherm
jordanlev replied on at Permalink Reply
jordanlev
Tricky. I don't have a solution for you off the top of my head. What I'd do is "View Source" on your reg page, copy and paste that to a text file somewhere. Then temporarily revert the site to use the default registration page (not your custom one), view the reg page, do a "View Source", and save that to another text file.

See if you can spot the place in the markup where each is outputting that <select>, and see if there's a difference between them. If they are different, can you post those 2 portions of source here? Might be able to tell you how to change the code to make it work then.
invision replied on at Permalink Reply
invision
Jordan,
Already did the source compare, and on the surface, it appears almost identical (except for the <select id="akID[70][value]") number is different because the attribs appear in a different order.

John,
It must be on the server, because the proper option value
<option value="8">Owner</option>
is being sent to the server.

Any thoughts on how to check on the server where it might be getting messed up?
jordanlev replied on at Permalink Reply
jordanlev
When you say that the <select id="akID[70][value]"> number is different, do you mean that the number 70 is different in the id, or the value is different? And does that select have a "name" attribute (because that's what would be POSTed to the form).
Please paste the appropriate portions of the "view source" here (for both the built-in working reg page and your custom reg page that isn't working).
..oh, that reminds me -- is it actually working if you register from the built-in reg page, or is that broken too?
JohntheFish replied on at Permalink Reply
JohntheFish
Like Jordan, I don't have a solution, but I can suggest an additional diagnostic that can quickly eliminate 50% of where you need to look.

Use the network tab of firebug or chrome developer to view what your form is sending back to the server. You should be able to see a complete list of get/post parameters and see if your select is there.

That way, you will know if the problem lies within the way your form is structured, or in the way the server is processing your form.
invision replied on at Permalink Reply
invision
I would be happy if I could just control the order of the auto-generated attributes in the default reg page.
JohntheFish replied on at Permalink Reply
JohntheFish
I am afraid I can't help on the server processing for this. Its not something I have ever looked at.

However, there is one final bit of analysis on the option going to the server before concluding, which is to double check it is going with the expected form element name, with the correct case, and (being php), the correct [] or not on the end of the name if the server expects and array of elements. Its something that I have been caught out on more than once.

After that, I think I would begin looking inside whatever processes the form and adding a few temporary log calls to trace what is happening.
hereNT replied on at Permalink Reply
hereNT
What I did for this was copy the form attribute helper and make my own. I over-rode the names of the functions to have display, displayTextArea and displayCheckbox.

If you look in the code in /forms/attribute helper, it shows you how you can get the output for individual attributes:

$key = UserAttributeKey::getByHandle('attribute_handle');
echo $key->render('label', false, true);
echo $key->render('form');
timtorres replied on at Permalink Reply
timtorres
This sounds almost exactly what I need. I made a separate thread for this, would you be able to see if you can help?
http://www.concrete5.org/index.php?cID=441443...
Thanks!
hereNT replied on at Permalink Reply
hereNT
Kind of doubtful that I could help you. Swamped with other things. Usually when doing checkboxes I do them manually, wrapping the label around the box so that it checks the box when you click the label. You can't do this with the form helper at all.

For the attribute helper, that's super easy to override, you just make a new one and call that instead of the built in one... Change the code it generates, and you're good to go. I think the html output is specific to bootstrap, I often modify it to just work with whatever my form is.
timtorres replied on at Permalink Reply
timtorres
But with manual I have to go through and update multiple places whenever I add or remove an attribute. And with making my own displayCheckbox method, I wouldn't know how to determine whether to use that or the default display, considering the statement calling display has a mix other other types of attributes:
foreach($attribs as $ak) {
         echo  $af->display($ak, $ak->isAttributeKeyRequiredOnRegister());
hereNT replied on at Permalink Reply
hereNT
Yeah, looping is probably not going to work.

You want to make your own copy of the /form/attribute helper with another name. Copy the function for display, name it display_checkbox or something like that, then modify how you need it.

Then something like this:

$af = Loader::helper('form/my_attribute_helper');
$pak = CollectionAttributeKey::getByHandle('regular_attribute');
echo $af->display($pak, false, true, "form");
$pak = CollectionAttributeKey::getByHandle('checkbox_attribute');
echo $af->display_checkbox($pak, false, true, "form");


You won't be able to just loop over everything, but honestly every time I have tried to just loop over a ton of attributes like this it looks totally ugly and boring an is a horrible form to use.

Another option you could do is maybe check for the attribute type in the loop, then call the display or display_checkbox functions as needed based on that.
timtorres replied on at Permalink Reply
timtorres
The second option is what I'm trying to do but I'll probably go for the manual option. Honestly I'd have to agree with you on how bad looping a form looks. I like to have control over every little design thing.